customizing kuali a technical perspective n.
Skip this Video
Download Presentation
Customizing Kuali: A Technical Perspective

Loading in 2 Seconds...

play fullscreen
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

Download Now 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)