How to develop your own approval processes - case 3: using general change processor

Last modified 18 Nov 2021 19:01 +01:00
OUTDATED
This page is outdated, it contains information that was not updated in a long time. The described functionality may or may not work. Do not rely on information provided on this page.

In this document we will explain how to create your own approval process with the help of the GeneralChangeProcessor.

Let’s assume you want to have any change on a given resource approved by a responsible person. For simplicity, the first version of the approval process will not enable the person to modify the change request, just to approve or reject it.

Scenarios for general change processor

General change processor works with a list of scenarios, whereas each scenario consists of the following:

  1. name: A human-readable name of the scenario.

  2. activationCondition: A condition controlling whether this scenario applies, i.e. whether a defined approval process should be started.

  3. processName: A name of the approval process. When the above condition is met, this process is started. It has to evaluate the situation, seek user’s (or users') approval(s), modifying the situation if necessary.

In our case, the scenario (in the context of whole workflow configuration) will look like this:

<workflow>
    <changeProcessors>
        <generalChangeProcessor>
            <c:generalChangeProcessorConfiguration xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-2a">
                <c:scenario>
                    <c:name>Approving changes on the resource Dummy Green</c:name>
                    <c:activationCondition>
                        <c:script><c:code>
                            context.getState() == com.evolveum.midpoint.model.api.context.ModelState.SECONDARY &amp;&amp;
                            context.findProjectionContext(new com.evolveum.midpoint.common.refinery.ResourceShadowDiscriminator("10000000-0000-0000-0000-000000000404", null)) != null
                        </c:code></c:script>
                    </c:activationCondition>
                    <c:processName>ApprovingDummyGreenResourceChangesProcess</c:processName>
                </c:scenario>
            </c:generalChangeProcessorConfiguration>
        </generalChangeProcessor>
    </changeProcessors>
</workflow>

The activationCondition is an expression that can use one predefined variable: context. This variable is the ModelContext valid at a given time instant. The above condition evaluates to true if the clockwork is in the secondary phase and if there is any projection context related to resource Dummy Green (described by its OID 10000000-0000-0000-0000-000000000404). In that case, the ApprovingDummyGreenResourceChangesProcess is started.

Note that there can be more such scenarios in the configuration. The change processor evaluates each activation condition and kicks off the first scenario whose condition is true. Other scenarios are then ignored.

BPMN processes

BPMN processes managed by GeneralChangeProcessor are "smart" ones (for the time being), having the following obligatory variable:

  • modelContext (input/output). This variable is filled-in at the start of the process by midPoint. It contains actual ModelContext of the model operation. Because workflow process instance variables are "long-lived", and generally must be robust enough to survive midPoint upgrades, we store it in a special way: as XML text, wrapped in JaxbValueContainer.

Other variables, as described here, will be also present in the process instance. And, of course, you can (and probably will) create and use any other variables that you find necessary.

The following code excerpt shows how to work with the modelContext variable:

util.revive(modelContext)                     // set prismContext for the modelContext JaxbValueContainer
modelContextType = modelContext.getValue()    // get the "prismified" value of modelContext (LensContextType - JAXB form of PrismContainer)
modelContextUnwrapped = util.midpoint().unwrapModelContext(modelContextType)  // get the original value of modelContext (ModelContext)
Was this page helpful?
YES NO
Thanks for your feedback