What is a Pre-Rule?
A pre-rule is a validation or rule check that can be performed prior to a business rule execution. Pre-rules often include important information requests that can dictate how the form should be processed. Pre-rules may also be used to notify the user of a potential problem with the form action being performed so they have the opportunity to resolve the problem prior to performing the form action step.
Technically, a pre-rule is a class implementing org.kuali.core.rule.PreRulesCheck
, which specifies a single method: boolean processPreRuleChecks(ActionForm, HttpServletRequest, PreRulesCheckEvent)
.
Why do we need pre-rules?
Pre-rules are used to modify document data prior to business rule validation. This is useful for setting default values to document fields prior to validation, for example. They are also able to ask confirmation questions of the user before continuing on with validation and, if validation is successful, routing.
When are pre-rules invoked?
By default, pre-rules are automatically invoked when approving, blanket approving, routing, or performing a route report on a document. They are typically invoked prior to business rule validation and document persistence/routing. For more information, consult KualiDocumentActionBase
.
Modifying control flow using pre-rules
As noted in the previous section, pre-rules are automatically invoked by the framework before executing document actions. Upon completion of the pre-rules check (i.e. calling PreRulesCheck.processPreRuleChecks(...)
), the following may occur (see KualiDocumentActionBase.preRulesCheck(...)
):
processPreRuleChecks(...)
returnstrue
: pre-rules checks succeeded and the action (e.g. routing) may continueprocessPreRuleChecks(...)
returnsfalse
: pre-rules checks failed and we may need to either not continue processing (i.e. go back to the original form), render some other action forward (i.e. another JSP page), or ask a question
How to Create and Add a Pre-Rule Check
Step 1 Creating a pre-rule class
org.kuali.module.chart.rules.ObjectCodePreRules
is a good example of how pre-rules work. Pre-rules classes extend org.kuali.core.rules.PreRulesContinuationBase
, or (far more rarely!) implement org.kuali.core.rules.PreRulesCheck
directly. If PreRulesContinuationBase.java
is extended, the only method that needs to be overridden is doRules()
which takes in a document and returns true if the pre-rule check completed successfully. If this method returns false, the current action will be halted and control determined by the state of the PreRulesCheckEvent
object. (See the PreRulesCheckEvent documentation below for more details.) Otherwise, the requested action continues.
Setting values in a document
This section will describe how to use pre-rules to set values on a document prior to validation. In this example, a document has a "userId" field, and if it's blank, the system will automatically fill in a defualt value.
Note that in this case, the doRules(Document) method returns true, indicating that business rules validation should occur with whatever values are set.
Asking a yes/no question
This section will describe how to use pre-rules to ask a user a question that requires a yes/no response when the pre-rules are invoked. In this example, a document has a "name" field on it, and the system will ask the user a question to confirm if he wants to submit with a blank name.
In the conditionallyAskQuestion(Document)
method, the following steps occur:
- We determine whether the condition that requires asking a question is true. In our example, whether the "name" field of the document is blank.
- If it's true, then we go into the
KualiConfigurationService
to retrieve the text of the question (e.g. "Are you sure you want to submit with a blank name?"). - We call the
askOrAnalyzeYesNoQuestion(String, String)
method. It does one of 3 things:- If the question has not yet been asked, it throws an exception. This exception is caught by the framework and it forwards to the question page.
- If the answer to the question is "yes", then this method returns true.
- If the answer to the question is "no", then this method returns false.
- If the
askOrAnalyzeYesNoQuestion(String, String)
returned a value (i.e. no exception), then we determine how to proceed. In the example, if the user answered "no", then we abort business rule validation and send the user back to the document. Another way of accomplishing this is to makedoRules{Document)
return false.
Step 2 Specify Pre-Rules class in Document data dictionary file.
Specifying a pre-rule implementation for transactional and maintenance documents are essentially identical. In the document's data dictionary, specify the prerules class name inside of a <preRulesCheckClass>
tag (see maintenance document and transactional document documentation).
PreRulesCheckEvent
Like other Events, this class is initially populated with the current Document object for the rules to examine. However, special properties exist in this event that indicate to the Action class how to handle the request if the rule check returns false (stop action request).
performQuestion
: boolean indicating that we should forward to the question framework for user input. If this is set, the following additional properties are examined to build the question:questionId
: Unique identifier for the question. Helpful if a series of questions or prompts need to occurquestionText
: Text that should appear on question screen. Note: the best practice is to store the text in to a application resources file (i.e. accessible using theKualiConfigurationService.getPropertyString(String)
method) and to retrieve the value prior to setting this property.questionType
: Indicates what type of question this is. E.g., Yes/No, OK/Cancel, ..questionCaller
: Caller identifier for the question framework for returning response. This is typically the name of the action that was being performed that's invoking the question.questionContext
: Any additional context the pre-rule class needs to have returned along with the user response
returnActionFoward
: the name Struts action forward mapping to forward to. Note this can be the basic mapping which would return the user back to the document, most likely with additional messages.