Customizing kuali a technical perspective
1 / 73

Customizing Kuali: A Technical Perspective - PowerPoint PPT Presentation

  • Uploaded on

Customizing Kuali: A Technical Perspective. Naser Alavi (Michigan State University) Warren Liang (University of California, Irvine). Customizing Kuali. Outline: System Parameters Business Rules Authorization class Pre-Rules. Customizing Kuali.

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
Download Presentation

PowerPoint Slideshow about ' Customizing Kuali: A Technical Perspective' - lilac

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Customizing kuali a technical perspective

Customizing Kuali:A Technical Perspective

Naser Alavi (Michigan State University)

Warren Liang (University of California, Irvine)

Customizing kuali
Customizing Kuali


  • System Parameters

  • Business Rules

  • Authorization class

  • Pre-Rules

Customizing kuali1
Customizing Kuali

  • Which aspects of Kuali are we customizing in this presentation?

    • Customizing business rules

    • Customizing authorization

    • Customizing system parameters

System parameters rules
System Parameters/Rules


  • Externalizing constants out of code

  • They may be maintained by a non-developer via a maintenance document.

  • The code must be programmed to access the constant value(s) by its unique key.

System parameters use cases
System Parameters Use Cases

Where they may be used:

  • Business rule checks

  • Any place where runtime changes to values displayed within the application will be needed without a restart of the application server

System parameters
System Parameters

The System Parameters can be used in the following manners:

  • Key-value constants

    • (key=DEBIT, value=D)

  • Key-value group constants

    • (key=VALID_OBJECT_CODES_FOR_XYZ, value=5000;5001;3400;2300)

System parameters use cases1
System Parameters Use Cases

Where they may not / should not be used:

  • System configuration values that can’t be represented as constants/literals in the code

  • Core constants that will not change no matter what the installation

  • Spring XML configuration files - you cannot have XML files use this mechanism

  • OJB XML configuration or descriptor files - you cannot have XML files use this mechanism

System parameters table
System Parameters Table

  • A single parameter record has a composite key made up of:

    • Parameter Name

    • Parameter Security Grouping

  • This composite key helps to categorize our constants.

    • As an enhancement for next phase to further modularize these parameters a new “Module Code” field will be added to this table

Using system parameters
Using System Parameters

  • Using the System Parameters for Key-Value Constants:

    String MANDATORY_TRANSFER = kualiConfigurationService

    .getApplicationParameter("TransactionProcessingEDocs", "Chart.SubObjectCode.MandatoryTransfer");

    if (financialSubObjectCode.equals(MANDATORY_TRANSFER)) {


Using system parameters1
Using System Parameters

  • Using the System Parameters for Key-Value Lists of Constants (array of values)

    String[] VALID_OBJ_SUB_TYPES_FOR_TOF = SpringServiceLocator.getKualiConfigurationService()



    if(ArrayUtils.contains(VALID_OBJ_SUB_TYPES_FOR_TOF, accountingLine.getFinancialSubObjectCode())) { ...

System parameter security class table
System Parameter Security Class/Table

  • The following class represents a security grouping which is identified by its security group name.

  • Each security grouping has a workgroup associated with it for authorization purposes.

System parameter security class table1
System Parameter Security Class/Table

publicclass FinancialSystemParameterSecurity extends PersistableBusinessObjectBase {

// script name is the security group

private String financialSystemScriptName;

private String workgroupName;

private String financialSystemScriptDescription;

private List financialSystemParameters;

System parameter attributes
System Parameter Attributes

  • The following class represents a KFS parameter with an associated text value.

  • This text value can be interpreted as a single value or a semicolon delimited list of values

  • The parameter name and the security group name make up the primary key for this business object

  • The security group name is the link to the System Parameter Security Table

System parameter attributes1
System Parameter Attributes

publicclass FinancialSystemParameter extends PersistableBusinessObjectBase {

private String financialSystemScriptName;

private String financialSystemParameterName;

private String financialSystemParameterText;

private String financialSystemParameterDescription;


private FinancialSystemParameterSecurity financialSystemParameterSecurity;

Business rules
Business Rules

  • Maintained by Business Rules Tables

  • Allows Functional Users to maintain and create business rules (to some extent).

  • Allows institutions to customize out of the box business rules based on their codes and policies.

Business rules1
Business Rules

  • Uses KualiParameterRule object for evaluating business rules

  • This object holds the underlying rule record values and provides a conveniencemethod for the evaluation of the rule

  • You can retrieve the values of a rule record as a KualiParameterRule by using the KualiConfigurationService method:

    KualiParameterRule getApplicationParameterRule(String scriptName, String parameter)

Sample code using business rule in taxnumberservice
Sample Code Using Business Rule inTaxNumberService


*Splitsthesetoftaxnumberformatswhicharereturned * fromtheruleserviceasasemicolon-delimitedString

* into aStringarray.




public String[] parseSSNFormats() {

if(taxNumberFormats == null) {

taxNumberFormats = SpringServiceLocator.getKualiConfigurationService().getApplicationRule("PurapAdminGroup","PURAP.TAX_NUMBER_FORMATS");


String taxFormats = taxNumberFormats.getRuleText();

return taxFormats.split(";");


Sample code using business rule in taxnumberservice1
Sample Code Using Business Rule inTaxNumberService

publicboolean isValidTaxNumber( String taxNbr, String taxType ) {

String[] ssnFormats = parseSSNFormats();

String[] feinFormats = parseFEINFormats();

Integer defaultTaxNbrDigits =

new Integer (SpringServiceLocator




if (taxNbr.length() != defaultTaxNbrDigits

|| !isStringAllNumbers(taxNbr)) {



Business rule attributes
Business Rule Attributes


publicclass BusinessRule extends PersistableBusinessObjectBase {

private String ruleGroupName;

private String ruleName;

private String ruleText;

private String ruleDescription;

private String ruleOperatorCode;



BusinessRuleSecurity ruleGroup;

System parameters rules1
System Parameters/Rules


  • Create and populate workgroup that should have maintenance permission

  • Create corresponding security group

  • Create parameter (value to control runtime system behavior) or rule (definition of legal/illegal values)

Customizing kuali2
Customizing Kuali


  • System Parameters

  • Business Rules

  • Authorization class

  • Pre-Rules

Putting it all together
Putting It All Together

  • Defining a Transactional Document

    • Payment Request Doc DD XML

    • Payment Request Rule

    • Payment Request Authorizer

    • Payment Request Pre-Rule (using question framework)

    • Demo New Payment Request Document functionality and sample code

Plugging business rules class
Plugging Business Rules Class

  • “Pluggable” business rules

    • Specify business rule implementation in document’s data dictionary file

    • Registering your business rule class with a document type.

    • The fully qualified classname of the business rule class must be specified with the <businessRuleClass> tag in the document's data dictionary file.

Plugging business rules class1
Plugging Business Rules Class

Example, KualiPaymentRequestDocument.xml:







Plugging business rules class2
Plugging Business Rules Class

  • “Pluggable” business rules

    • Normally used to detect errors on a form

    • Since these are written in Java, it is much more expressive than just matching

    • Has access to all Kuali services

    • The rules framework creates a copy of the document so that any changes made during rule application will not affect the document when it is persisted.


  • DocumentRuleBase implements common checks that should be run after every event, and rule implementations should extend this class

  • Instead of overriding the methods defined by the *DocumentRule interfaces, override the processCustom* methods defined in this class (e.g. to define new save rules, override processCustomSaveDocumentBusinessRules instead of processSaveDocument)

Associating rules with events save example
Associating Rules with Events(Save Example)

package org.kuali.core.rule;




publicinterface SaveDocumentRule extends BusinessRule {





publicboolean processSaveDocument(Document document);


Associating rules with events and using common services
Associating Rules with Events and Using Common Services




publicabstractclass DocumentRuleBase implements SaveDocumentRule, RouteDocumentRule, ApproveDocumentRule, AddNoteRule, AddAdHocRoutePersonRule, AdHocRouteWorkgroupRule {

privatestatic UniversalUserService universalUserService;

privatestatic KualiModuleService kualiModuleService;

privatestatic DictionaryValidationService dictionaryValidationService;

privatestatic KualiWorkflowInfo workflowInfoService;

privatestatic KualiConfigurationService kualiConfigurationService;

Documentrulebase rule implementation
DocumentRuleBase Rule Implementation


SaveDocumentRule, … {

publicboolean processSaveDocument(Document document) {

boolean isValid = true;

isValid &= isDocumentOverviewValid(document);

if (isValid) {

isValid &=



return isValid;


protectedboolean processCustomSaveDocumentBusinessRules

(Document document) {




Documentrule sample
DocumentRule Sample

publicclass PaymentRequestDocumentRule extends AccountsPayableDocumentRuleBase {




(Document document) {


paymentRequestDocument =

(PaymentRequestDocument) document;




Documentrule sample1
DocumentRule Sample

publicclass PaymentRequestDocumentRule extends AccountsPayableDocumentRuleBase {



publicboolean processValidation(PurchasingAccountsPayableDocument purapDocument) {

boolean valid = super.processValidation(purapDocument);

valid &= processInvoiceValidation((PaymentRequestDocument)purapDocument);

valid &= processPurchaseOrderIDValidation((PaymentRequestDocument)purapDocument);

valid &= processPaymentRequestDateValidation((PaymentRequestDocument)purapDocument);

return valid;


Customizing kuali3
Customizing Kuali


  • System Parameters

  • Business Rules

  • Authorization class

  • Pre-Rules

Plugging authorizer class
Plugging Authorizer Class

  • Modifying Authorizations for a Document Type

    • Payment Request Document

      • Initiators in Doc DD XML

      • Complex Rules in Document Authorizer Class

      • Approvals in Workflow

Plugging authorizer class1
Plugging Authorizer Class

Authorization DD File Code Sample:








<authorization action="initiate">








Document authorizer
Document Authorizer

  • The document authorizer framework:

    • Determines a user can initiate a document

    • How document fields are rendered

    • What buttons are displayed

Code modules for paymentrequest
Code Modules for PaymentRequest

The functionality demoed was accomplished through codes in:

  • PaymentRequestDocumentAuthorizer

  • PaymentRequestDocumentRule (already discussed)

  • PaymentRequestAction


Overrode these methods:

  • hasInitiateAuthorization

    • Simple true/false value

  • getEditMode

    • A map of mode -> value mappings. The JSP layer uses these mappings to determine how it should render the document

  • getDocumentActionFlags

    • Returns an object with numerous boolean flags, indicating whether a button may be rendered



publicboolean hasInitiateAuthorization(Document document, UniversalUser user) {

String authorizedWorkgroup = SpringServiceLocator.getKualiConfigurationService().getApplicationParameterValue(PurapRuleConstants.PURAP_ADMIN_GROUP, PurapRuleConstants.PURAP_DOCUMENT_PO_ACTIONS);

try {

return SpringServiceLocator.getKualiGroupService().getByGroupName(authorizedWorkgroup).hasMember(user);


catch (GroupNotFoundException e) {

thrownew RuntimeException("Workgroup " + authorizedWorkgroup + " not found",e);





public Map getEditMode(Document document, UniversalUser user, List sourceAccountingLines, List targetAccountingLines) {

Map editModeMap = super.getEditMode(document, user, sourceAccountingLines, targetAccountingLines);

PaymentRequestDocument paymentRequestDocument = (PaymentRequestDocument)document;

if (StringUtils.equals(paymentRequestDocument.getStatusCode(),PurapConstants.PaymentRequestStatuses.INITIATE)){

editModeMap.put(PurapAuthorizationConstants.PaymentRequestEditMode.DISPLAY_INIT_TAB, "TRUE");

} else {

editModeMap.put(PurapAuthorizationConstants.PaymentRequestEditMode.DISPLAY_INIT_TAB, "FALSE");


return editModeMap;



The JSP uses the values in the edit mode map to determine how to render the document.

Example from PaymentRequest.jsp

<c:if test="${not KualiForm.editingMode['displayInitTab']}" >

<kul:documentOverview editingMode="${KualiForm.editingMode}" includePostingYear="true“ />


<c:if test="${KualiForm.editingMode['displayInitTab']}" >

<purap:paymentRequestInit documentAttributes="${DataDictionary.KualiPaymentRequestDocument.attributes}“ />




public DocumentActionFlags getDocumentActionFlags(Document document, UniversalUser user) {

DocumentActionFlags flags =

super.getDocumentActionFlags(document, user);

KualiWorkflowDocument workflowDocument =


PaymentRequestDocument paymentRequestDocument =


if (StringUtils.equals(paymentRequestDocument

.getStatusCode(), INITIATE)){




} else {



return flags;


Payment request duplication scenario
Payment Request Duplication Scenario

  • Needed to check for Payment Request duplication before even validating business rules

  • In case of duplication give the user a warning and the option of override the warning and continue or to cancel

  • We used the question framework for this

  • Demo this in action in Payment Request

  • Demo the code (paymentRequestAction.continuePREQ())


public ActionForward continuePREQ(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {

PaymentRequestForm preqForm = (PaymentRequestForm) form;

PaymentRequestDocument paymentRequestDocument = (PaymentRequestDocument) preqForm.getDocument();

Map editMode = preqForm.getEditingMode();

Object question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME);

PaymentRequestService paymentRequestService = SpringServiceLocator.getPaymentRequestService();

HashMap<String, String> duplicateMessages = paymentRequestService.paymentRequestDuplicateMessages(paymentRequestDocument);

Paymentrequestaction continued
PaymentRequestAction (Continued)

if (!duplicateMessages.isEmpty()){

if (question == null) {

// ask question if not already asked

returnthis.performQuestionWithoutInput(mapping, form, request, response, PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION, duplicateMessages.get(PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION) , KFSConstants.CONFIRMATION_QUESTION, KFSConstants.ROUTE_METHOD, "");


Object buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON);

if ((PurapConstants.PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) {

// if no button clicked just reload the doc in the

// INITIATE status and let the user to change the

// input values


return mapping.findForward(KFSConstants.MAPPING_BASIC);



Customizing kuali4
Customizing Kuali


  • System Parameters

  • Business Rules

  • Authorization class

  • Pre-Rules

Pre rules use cases
Pre-Rules Use Cases

  • Pre-Rules allow

    • Modification of values after form submission (e.g. auto-fill values, possibly based on other values on the form)

    • Switching to another page after clicking the button (e.g. go to a confirmation page)

Pre rules configuration
Pre-Rules Configuration

  • Pre-rules for documents are configured in the data dictionary by specifying a class name for the implementation

  • Example: in UniversalUserMaintenanceDocument.xml




Prerulescheck interface
PreRulesCheck Interface

publicinterface PreRulesCheck {









publicboolean processPreRuleChecks(ActionForm form, HttpServletRequest request, PreRulesCheckEvent event);



  • This class simplifies requesting clarifying user input prior to applying business rules.

  • It mostly shields the classes that extend it from being aware of the web layer, even though the input is collected via a series of one or more request/response cycles.


publicabstractclass PreRulesContinuationBase implements PreRulesCheck {

protected String question;

protected String buttonClicked;

protected PreRulesCheckEvent event;

protected KualiForm form;

publicabstractboolean doRules(Document document);


publicbooleanprocessPreRuleChecks(ActionForm form, HttpServletRequest request, PreRulesCheckEvent event) {

try {

result = doRules(event.getDocument());


catch (IsAskingException e) {



if (isAborting) {



return result;


Putting prerules in action
Putting PreRules* in Action

  • Pre-rules are invoked automatically by the framework before routing, approving, and blanket approving a document.

  • Can also force the invocation of a pre-rule by overriding the Struts action handler of the document.

Example 1 adding a pre rule check
Example 1: Adding a pre-rule check

public class BudgetParametersAction extends BudgetAction {

public ActionForward deletePeriodLine(ActionMapping mapping,

ActionForm form, HttpServletRequest request,

HttpServletResponse response) throws Exception {

// do some processing

ActionForward preRulesForward = preRulesCheck(mapping, form,

request, response);

if (preRulesForward != null) {

return preRulesForward;


return mapping.findForward(KFSConstants.MAPPING_BASIC);


Example 2 universaluserprerules
Example 2: UniversalUserPreRules

publicclass UniversalUserPreRules extends PreRulesContinuationBase {

publicboolean doRules(Document document) {

MaintenanceDocument maintenanceDocument = (MaintenanceDocument) document;

UniversalUser newUser = (UniversalUser) maintenanceDocument.getNewMaintainableObject().getBusinessObject();

Field nameField = FieldUtils.getPropertyField( UniversalUser.class, PropertyConstants.PERSON_NAME, false );

ControlDefinition controlDef = KNSServiceLocator.getDataDictionaryService().getAttributeControlDefinition(UniversalUser.class, PropertyConstants.PERSON_NAME );

Example 2 universaluserprerules continued
Example 2: UniversalUserPreRules (continued)

if ( controlDef.isHidden() || nameField.isReadOnly() || StringUtils.isBlank( newUser.getPersonName() ) ){

if ( !StringUtils.isBlank( newUser.getPersonFirstName() ) && !StringUtils.isBlank( newUser.getPersonLastName() ) ){

if ( !StringUtils.isBlank( newUser.getPersonMiddleName() ) ) {

newUser.setPersonName( newUser.getPersonLastName()+"," +newUser.getPersonFirstName() + " " + newUser.getPersonMiddleName() );

} else {

newUser.setPersonName( newUser.getPersonLastName()+"," +newUser.getPersonFirstName() );




boolean success = true;

List<KualiModule> modules = KNSServiceLocator.getKualiModuleService().getInstalledModules();

PreRulesContinuationBase rule = null;

for ( KualiModule module : modules ) {

rule = (PreRulesContinuationBase) module.getModuleUserPreRules();

if ( rule != null ) {

success &= rule.doRules( document );



Pre rule scenario sample 3
Pre-Rule Scenario Sample 3

  • Pre-Rules could be used to derive values based on other values, or

  • Setting a default value where needed and the user didn’t enter any value

    • See next sample code

Example 3 set unconditional defaults
Example 3: Set Unconditional Defaults

publicclass DelegateChangePreRules implements PreRulesCheck {


privatevoid setUnconditionalDefaults(DelegateChangeContainer newDelegateChangeContainer) {

for (DelegateChangeDocument newDelegateChange : newDelegateChangeContainer.getDelegateChanges()) {

// FROM amount defaults to zero

if (newDelegateChange.getApprovalFromThisAmount()==null) {

newDelegateChange.setApprovalFromThisAmount(new KualiDecimal(0));


// TO amount defaults to zero

if (newDelegateChange.getApprovalToThisAmount()==null) {

newDelegateChange.setApprovalToThisAmount(new KualiDecimal(0));





  • System parameters

    • Provides on-the-fly configuration of certain components

  • Business Rules

    • Provides business rules based on matching values


  • “Pluggable” business rules

    • Java-based implementation of rules that are more complicated than simple matching

  • Pre-rules

    • Allows modification of form values prior to processing

    • Allows “redirection” to a different page



  • System parameters/ business rules

  • Pluggable business rules

  • Pre-rules

  • Kuali Nervous System (KNS)