kc developer training
TRANSCRIPT
Kuali Coeus Developer Training
August 22 – 26, 2011
Geoff McGregor, Technical Consultant
Goals for the Week
‣ Reinforce and build on Rice basics curriculum, in the context of KC
‣ KC is heavily dependant on Rice
‣ Learn best practices for customizing and enhancing KC for your institution
‣ Combination of lecture and exercises
Installation and Configuration
‣ Dependency resolution, building, etc. handled by Maven
‣ Oracle and MySQL scripts provided, including installer for various options – upgrade, new, bundled, embedded
‣ Startup parameters defined in a set of XML config files
3
Exercise 1: Installation and Setup
4
Exercise 2: Building and Deploying the WAR
5
Automated Test Framework
‣ KC has both ‘Unit’ and ‘Integration’ tests
‣ Integration tests require a test database
‣ Web tests are recorded with Selenium IDE and exported to Java
‣ Running the Maven ‘site’ goal will produce a report of passed/failed tests and code coverage
Exercise 3: Run a Unit Test
7
KC Functional Modules and Project Structure
‣ Application walk-through functional modules and documents
‣ Review package structure
‣ Review pom.xml
8
KC Architecture
‣ Heavily inherited from Rice
‣ Business Objects – Java POJO; encapsulate domain model
‣ OJB – ORM tool; map database tables to Business Objects
‣ Data dictionary – Rice component; describe BO fields and how to display/validate them at the UI level, and relationships between Bos
‣ JSP/tags – Reusable tags from Rice, and custom tags. JSPs composed of tags
‣ Struts – MVC framework
‣ Spring – IoC container, service bean factory, transaction management
9
KC Architecture 10
Exercise 4: Create a new Panel on Institutional Proposal Document
11
Audit-style Business Rules
‣ Can be ‘hard stops’ – prevent submission into routing – or warnings
‣ Don’t prevent saving – needed to support multi-tab documents
12
Exercise 5: Create a new Audit Rule
13
Custom Attributes
‣ Used by institutions to collect data that isn’t already collected, without requiring code changes
‣ Support validations and lookups
‣ Manageable at runtime using maintenance framework
14
Exercise 6: Create new Custom Attributes
15
Managing Local Customizations
‣ Managing implementation customizations can be difficult but maven can help
‣ War overlays merge dependant war project together
‣ Allows certain files to be “overrriden” enabling customizations
‣ Customizations will be “isolated” from the Kuali Coeus application. To put it another way, customizations can be placed in a completely different maven project and source tree. This makes customizations very “visible”.
‣ A custom overlay project gives an isolated place for unit/integration tests
16
Managing Local Customizations
‣ So this is all great but what is the downside?
‣ Overlays increase build time
‣ Overlays don’t work with all IDE tooling/maven plugins – it is getting better though!
‣ Overlays can make it harder to merge in changes coming from KC since you are not customizing actual KC files in the KC source tree. Even though merging is harder, customizations are more “visible”. This makes it is easier to see what files need to be considered on upgrade.
‣ See http://maven.apache.org/plugins/maven-war-plugin/overlays.html for more info.
17
Exercise 7: Maven WAR Overlay
18
Rice Client – Embedded Mode
‣ Embedded mode allows you to run KC with a central Rice server. This has the benefit of a central Doc Search, Action List, and KIM maintenance.
‣ It also allows some processing to be offloaded to the rice server, which provides different scaling characteristics. Embedded mode is currently the preferred deployment model.
19
Embedded Architecture 20
21
Rice Keystore
‣ For client applications to consume secured services hosted from a Rice server, you must generate a keystore. As an initial setup, you can use the keystore provided by Rice. There are three ways to get this keystore:
1. If you are doing a source code build of Rice, it is in the directory <source root>/security and it has a file name of rice.keystore.
2. 2. The keystore is also located in the server distribution under the security directory.
3. You can generate the keystore yourself.
22
Rice Keystore
‣ keystore.file - The location of the keystore
‣ keystore.alias - The alias used in creating the keystore above
‣ keystore.password - This is the password of the alias AND the keystore. This assumes that the keystore is set up so that these are the same.
23
Exercise 8: Configure KC for Embedded Mode against a
Standalone Rice Server
24
Adding a New Authentication Filter
‣ KC ships with a ‘dummy’ authentication filter
‣ New filters can be registered in kc-config.xml
‣ Can be integrated with KIM
25
Exercise 9: Add a New Authentication Filter
26
Questionnaire
‣ Dynamic set of questions that can display or not based on response to previous questions
‣ Managed at runtime using Maintenance framework
27
Exercise 10: Create and Maintain Questionnaire
28
Person Management
‣ A KC Person is composed of a Rice Person, and a KC Person Extended Attributes record which captures person data not available in Rice.
‣ Extended Attributes record is not required.
‣ KIM services can be overridden to retrieve person information from other institutional sources.
29
Exercise 11: Create a new Person Record
30
KIM: KC Type Services
‣ Unit – Authorize based on the Unit of the entity being acted upon
‣ UnitHierarchy – Authorize based on the Unit or parent Unit(s) of the entity being acted upon
‣ UnitHierarchy types can have descend flag on or off
31
KIM: KC Roles and Groups
‣ Out of the box groups are typically workflow groups
‣ Derived roles based on project roles defined on the document
‣ Administrative roles typically qualified by Unit number
‣ A few system-level administrative roles
‣ Document-level roles can be assigned within documents
32
Exercise 12: Create and Maintain Roles and Permissions using KIM
Screens
33
Populating KIM Tables
‣ KRIM_ROLE_T – Role table. All Roles must have a Type.
34
Populating KIM Tables
‣ KRIM_ROLE_PERM_T – Grant permissions to a Role
35
Populating KIM Tables
‣ KRIM_ROLE_MBR_T – Assign Roles to Principals. Member type code could be a Principal, a Group, or another Role.
36
Populating KIM Tables
‣ KRIM_ROLE_MBR_ATTR_DATA_T – Qualify the Role-member assignment. Required qualifications are based on the Role Type. If these are missing, the Role assignment won’t work!
‣ UnitHierarchy requires a Unit Number and descend flag.
37
Exercise 13: Create and Maintain Roles and Permissions using
Direct SQL
38
Leveraging KEW for Routing and Approvals
‣ In KC, business data and processes are encapsulated within a document (eg Proposal Development Document)
‣ The document workflow – routing, approvals, etc. – is implemented using the Rice module Kuali Enterprise Workflow (KEW)
‣ Kuali Identity Management (KIM) also provides hooks for workflow routing
39
KC Document Hierarchy 40
KC Document
Maintenance Document
Award Maintenance
Document
Compliance Maintenance
Document …
PropDev Document …
KEW Features
‣ KC leverages Postprocessor hooks to do custom processing when documents change route levels
‣ Search Attributes – document-specific attributes used for document search
‣ Document policies – configure behavior of specific document types
41
KEW Process Definition
‣ Route Path – The order in which route nodes are visited during the document workflow
‣ Route Nodes – Details about each node
‣ Route Path plus Route Nodes is referred to as the Process Definition
42
KEW Routing Components
‣ Route nodes – The stops on the route path. Many different types of nodes but we will look at 3: requests, role, dynamic.
‣ Rule Attributes – Tell KEW how to find data within the document used to make routing decisions. For example, here’s how to find the lead unit.
‣ Rule – Tell KEW what to do when certain conditions are met. For example, when the lead unit is BL-CHEM, route to this person for approval.
43
KEW Routing Components
‣ Rule Template
‣ Defines the rule attributes needed to evaluate the node – e.g., a Unit Number
‣ Links doc types, rules and rule attributes. Indirection layer that allows reuse of the various components, ie a rule attribute can be used by multiple document types.
44
Route Node Configuration
‣ activationType – Parallel or Serial. If the node generates multiple requests, should they all go out at once (parallel) or should they be staggered based on the priority defined in the rule (serial)
‣ mandatoryRoute – There should be at least one recipient at this node; if not, go into exception routing.
‣ finalApproval – This should be the last node that generates approval requests, if not, go into exception routing
‣ forceAction – If true, the user should approve again even if they approved earlier in the routing
45
Proposal Development Example
Initiator/Aggregator
submits into routing
Principal
Investigator
Preaward Specialist
Group
Departmental
Approvers
OSP Office
Approval
Request
Approva
l
Request Approval
Request
Delegation
Approval
Request Acknowledge for
Submission to
Sponsor
Proposal Development Example
‣ First, build the route path.
‣ Need to keep the split for proposal hierarchy. Will talk more about split nodes later.
‣ Start at initiated node – document is in initialized/saved state. Initiator will have a complete request.
‣ Define the next nodes until we join back up from the split.
47
Proposal Development Example
‣ Initial Node – Not yet submitted; places a complete request in Initiator’s Action List
‣ See route log screen
48
<start name="Initiated"> <activationType>P</activationType> <mandatoryRoute>false</mandatoryRoute> <finalApproval>false</finalApproval> </start>
Departmental Routing
‣ Rule-based requests node
‣ Again, we use Xpath to tell KEW how to find the data it needs to make a routing decision, then specify a rule for that data
‣ All linked by rule template
49
<requests name="DepartmentApproval"> <ruleTemplate>DepartmentApproval</ruleTemplate> <activationType>S</activationType> <finalApproval>false</finalApproval> </requests>
Departmental Routing
‣ The rule template links to the rule attribute which provides the unit number
50
<ruleTemplate> <name>DepartmentApproval</name> <description>Department Approval Routing Rule</description> <attributes> <attribute> <name>DepartmentApprovalAttribute</name> <required>false</required> </attribute> </attributes> </ruleTemplate>
Departmental Routing 51
<ruleAttribute> <name>DepartmentApprovalAttribute</name> <className>org.kuali.rice.kew.rule.xmlrouting.StandardGenericXMLRuleAttribute</className> … <type>RuleXmlAttribute</type> <serviceNamespace>KC</serviceNamespace> <routingConfig> <fieldDef name="leadUnitNumber" title="Lead Unit" workflowType="RULE"> <display><type>text</type></display> <validation required="false" /> <fieldEvaluation> <xpathexpression>wf:xstreamsafe('//document/developmentProposalList[1]/org.kuali.kra.proposaldevelopment.bo.DevelopmentProposal/ownedByUnitNumber')= wf:ruledata('leadUnitNumber')</xpathexpression> … </ruleAttribute>
Departmental Routing 52
<rule> <name>DepartmentApprovalRule</name> <documentType>ProposalDevelopmentDocument</documentType> <ruleTemplate>DepartmentApproval</ruleTemplate> <description>Department Approval Routing Rule for IN-CARD</description> <forceAction>false</forceAction> <ruleExtensions> <ruleExtension> <attribute>DepartmentApprovalAttribute</attribute> <ruleTemplate>DepartmentApproval</ruleTemplate> <ruleExtensionValues> <ruleExtensionValue> <key>leadUnitNumber</key> <value>IN-CARD</value> … </ruleExtensions> <responsibilities> <responsibility> <principalName>chew</principalName> <actionRequested>A</actionRequested> <priority>1</priority> </responsibility> </rule>
Proposal Development Example
‣ You can look at the XML for a specific document using the Document Operation screen
53
<documentContent><applicationContent><org.kuali.kra.workflow.KraDocumentXMLMaterializer> ... <developmentProposalList > <org.kuali.kra.proposaldevelopment.bo.DevelopmentProposal> <proposalNumber>10000</proposalNumber> ... </documentContent>
Departmental Routing
‣ The rule says that if the unit number is IN-CARD, send an action request to Inez Chew
‣ Could also be a group or role
‣ See rules editor screen
54
Exercise 14: Configure a New Basic Workflow
55
KEW Review: Responsibility-based Routing
‣ Route based on responsibilities, which are tied to Roles
‣ In KC we use derived and assigned Roles for routing
56
Proposal Persons Routing
‣ Route to PI / CO-PI’s / Key Investigators
‣ Based on KIM Role, not rules
‣ Will send to Roles with ProposalPersons responsibility for this Proposal
‣ See responsibility screen
57
<routeNodes> … <role name="ProposalPersons"> <qualifierResolver>ProposalPersonsXPathQualifierResolver</qualifierResolver> <activationType>P</activationType> <finalApproval>false</finalApproval> </role> … </routeNodes>
Proposal Persons Routing
‣ To resolve the role, KIM needs a proposal number qualifier.
‣ XPathQualifierResolver – Tell KEW how to find data in document XML.
58
<ruleAttribute> <name>ProposalPersons-XPathQualifierResolver</name> <className>org.kuali.rice.kew.role.XPathQualifierResolver</className> <resolverConfig> <qualifier name="proposal">
<xPathExpression>//document/developmentProposalList[1]/org.kuali.kra.proposaldevelopment.bo.DevelopmentProposal[1]/proposalNumber[1]</xPathExpression> </qualifier> </resolverConfig> </ruleAttribute>
Preaward Specialist Routing
‣ Role-based routing
‣ Specify NullQualifierResolver because this is not based on rules or document roles – based on KIM responsibility
‣ See Preaward Specialist role screen
59
<role name="PreawardSpecialistInitial">
<qualifierResolverClass>org.kuali.rice.kew.role.NullQualifierResolver</qualifierResolverClass> <activationType>P</activationType> <finalApproval>false</finalApproval> </role>
‣ Same as preaward specialist group, except here we have a delegation
‣ See Role screen
60
<role name="OSPOffice"> <qualifierResolverClass>org.kuali.rice.kew.role.NullQualifierResolver</qualifierResolverClass> <activationType>P</activationType> <finalApproval>false</finalApproval> </role>
Exercise 15: Responsibility-based Routing
61
KEW Hierarchy Provider Node
‣ For unit hierarchy routing – build an approval chain dynamically based on your KC unit hierarchy
‣ Implement the KEW HierarchyProvider interface – tell KEW how to build a DOM tree
‣ Replace the Department node with a dynamic node
62
Hierarchy Routing Node 63
<routeNodes> … <dynamic name="hierarchy"> <activationType>P</activationType>
<type>edu.iu.uits.kra.workflow.engine.node.hierarchyrouting.SimpleHierarchyRoutingNode</type> <ruleSelector>HierarchicalNamed</ruleSelector> </dynamic> … </routeNodes>
N-Depth Unit Hierarchy
Indiana
University
BL-BL-
Approver
UA-UA-
Approver
BL-ARSC-
Approver
BL-CHEM-
Approver
BL-BI-
Approver
UA-VPIT-
Approver
Hierarchy Approval Tree
edu.iu.uits.kra.workflow.engin.node.hierarchyrouting.SimpleHierarchyProvid
er
University Unit Hierarchy
Tree Proposal Approval Units
Hierarchy Provider
‣ NamedRuleSelector: Pick the rule for the given Unit based on a string matching pattern
<rule> <name>hierarchy-UA-VPIT-Approver</name> <documentType>ProposalDevelopmentDocument</documentType> <description>Unit Approver for UA-VPIT</description> <forceAction>true</forceAction> <responsibilities> <responsibility> <principalName>lsalander</principalName> <actionRequested>A</actionRequested> <priority>1</priority> </responsibility> </responsibilities> </rule>
Exercise 16: Dynamic Routing using the KEW Hierarchy Provider
67
Advanced KEW: Split and Join Nodes
‣ Split, Branch and Join nodes can be used to accomplish parallel/conditional routing
‣ Split nodes are composed of Branches
‣ Every split must have a corresponding Join
‣ Splits within splits are supported
68
Proposal Development Example 69
<split name = "isHierarchyChild"> <branch name = "False"> <requests name="OSPInitial" nextNode="ProposalPersons" /> .. </branch> <branch name = "True"> <!-- The document is a child in a hierarchy. This node will have the system user as an approver. If the parent moves to final approval, is rejected, or cancelled the system user will take the same action on the children. --> <requests name = "WaitForHierarchyDisposition" nextNode="Join"/> </branch> </split> <join name="Join"/>
Proposal Development Example 70
<routeNodes> … <split name="isHierarchyChild"> <type>org.kuali.kra.kew.SimpleBooleanSplitNode</type> </split> … <requests name="WaitForHierarchyDisposition"> <activationType>S</activationType> <ruleTemplate>HierarchyParentDispositionApproval</ruleTemplate> <mandatoryRoute>true</mandatoryRoute> <ignorePrevious>true</ignorePrevious> <finalApproval>false</finalApproval> </requests> <join name="Join"/>
Exercise 17: Workflow Branching using Split and Join Nodes
71
Further Learning
‣ Lots of good Rice documentation here: http://kuali.org/rice/documentation/1.0.3/
72
Exercise 18: Class-Driven Advanced Exploration
73
Exercise 19: Build a New Complex Workflow
74
75 75