Page ID and namespace are not decided yet - fix the internal links below before publishing.
An approval process decides whether a request (assignment of a role, change of an assigned role, recertification, …) has to be approved and by whom. It binds three things together: the event that triggers it, the workflow definition that describes the approval graph, and an optional condition that narrows down when it applies.
Since IdM 16 the product uses its own workflow engine (agenda Workflows) instead of Activiti. IdM 16.1 adds a set of workflow definitions and approval processes that are delivered with the product, so that an upgraded instance keeps approving role requests the way it did before the engine was replaced.
| Version | Compatible with product | Notes |
|---|---|---|
| 16.1.0 | 16.1.0 | Workflows delivered with the product, default approval processes, read only system workflows, copy of a workflow, unique code of a definition |
| 16.0.0 | 16.0.0 | New workflow engine, agenda Workflows, versioning of a definition |
Compatible with the product from the version stated above.
IdmBusinessProcess) - configuration record that says "when event X happens, run workflow Y". It carries the triggering workflow event type, the workflow, an optional named condition, the order and a disabled flag.@since 16.1.0 Three workflow definitions ship inside the product and are deployed on every application start:
| Code | What it does |
|---|---|
| `system-workflow-approve-by-manager/guarantor` | Approved by the manager of the applicant or by the guarantor |
| `system-workflow-approve-by-manager/guarantor–role-criticality-1+` | The same, but only for roles with criticality 1 and higher. Used by the default approval processes |
| `system-workflow-approve-by-role-guarantor` | Approved by the guarantor of the requested role |
A workflow delivered with the product is managed by the application. It cannot be changed and it cannot be deleted - not through the user interface, not over REST and not by an import. The editor opens it in a read only mode: no palette, no Save, the fields are greyed out, a node cannot be moved or deleted. Clicking a node still shows its properties, read only.
systemWorkflow property is read only on REST, so it cannot be sent from a client, and an import never grants it either. The only write path that marks a workflow as delivered with the product is the deployment described below. The deployment compares the shipped content with what is in the database and acts per workflow:
| Situation in the database | Result of the start |
|---|---|
| The workflow is missing | It is created |
| It is there and unchanged | Nothing is written |
| Its content differs | It is repaired back to the shipped content |
| It was deleted | It is created again |
| It is archived and no current version exists | The archived version is restored as the current one |
| Another workflow occupies the shipped identifier | The start fails, an administrator has to resolve it |
| Two current workflows share the shipped code | A warning is logged and the workflow is skipped |
An unchanged workflow is deliberately not saved again: a save of a definition that has instances creates a new version (see below), so writing on every start would produce a new version per restart. The comparison uses the content of the graph - its natural keys, node attribute values and edges. The layout is not part of it, so moving a node in the editor is not a content change.
The deployment runs as an initialization processor (core-init-system-workflow-processor). An enabled initialization processor that fails prevents the application from starting - that is the standard behaviour and it is intentional here: an instance without the shipped workflows would silently approve nothing. Data situations the processor recognises (an ambiguous code) are answered with a warning instead.
If starting without the shipped workflows is preferred, disable the processor in the configuration:
# Deployment of the workflows delivered with the product idm.sec.core.processor.core-init-system-workflow-processor.enabled=true
A definition that has no instance is updated in place. A definition that has an instance is versioned by copy on write:
Archived versions therefore share the code with the current one by design. Deleting a definition that has instances archives it as well, it does not remove it.
@since 16.1.0 The code of a current (not archived) workflow definition is unique. Everything that resolves a workflow by its code - the deployment above, the default approval processes, pairing of an import - expects exactly one row, and before 16.1 two current definitions could share a code even through the user interface.
The rule is enforced twice: by a partial unique index in the database (ux\_wfe\_definition\_code, only over rows that are not archived) and by a validation in the service, so a client gets a readable error (WORKFLOW\_CODE\_NOT\_UNIQUE) instead of a constraint violation.
A definition without a code is allowed and is not checked - the graph can be built before the code is filled in.
@since 16.1.0 The bulk action Duplicate workflow in the agenda Workflows creates an independent copy of the selected definitions, including the whole graph. The copy:
A definition can be exported and imported through the standard export and import batches. Two things are specific to this agenda:
An import cannot change a workflow delivered with the product and cannot grant that flag either. An import of an unchanged shipped workflow is a no operation.
Approval processes live in the agenda Business processes. Each one binds a triggering event to a workflow.
@since 16.1.0 After an upgrade the product creates the approval configuration an instance had before the engine was replaced:
| Code | Triggering event | Workflow used |
|---|---|---|
| `system-process-assign-role` | Assignment of a role | Approve by manager or guarantor, role criticality 1 and higher |
| `system-process-change-assigned-role` | Change of an assigned role | The same |
| `system-process-recertificate-role` | Recertification of an assigned role (module rec) | The same |
A process is created only when it is missing. An existing configuration is never changed, so an administrator can replace the default or switch it off.
Approval processes are started in the order given by the order column, and the first process that reaches a concept of the request claims it - a later process is not started for the same concept. The processes delivered with the product therefore use the order `1000`, so that a process created by an administrator (order `0` unless it is filled in) always wins.
An approval process can carry a named condition that decides whether the process applies at all (for example only for identities with a given form projection). The condition belongs to its process: it is created with it and @since 16.1.0 removed with it, including its extended attributes.
@since 16.1.0 The code of an approval process is unique. The database has enforced it since the agenda was introduced, but a reused code ended as an internal error - now it is refused with BUSINESS\_PROCESS\_CODE\_NOT\_UNIQUE.
When the triggering event of a process is not known to the application - typically after a module was uninstalled - the process is ignored, a warning is logged and the requests of other events are not affected. The same holds for a process whose workflow no longer exists.
In the application profile (application.properties) - overloadable via ConfigurationService.
# Product initialization data. The default approval processes are init data, so they are # not created when this is switched off. The shipped workflows are deployed regardless - # they are an artifact, like scripts and notification templates. # @since 16.1.0 idm.pri.core.init.data.enabled=true # Deployment of the workflows delivered with the product # @since 16.1.0 idm.sec.core.processor.core-init-system-workflow-processor.enabled=true # Creation of the default approval processes # @since 16.1.0 idm.sec.core.processor.core-init-business-process-processor.enabled=true
idm.sec.core.wf.approval.* and idm.sec.core.wf.role.approval.* does not configure the approval of IdM 16. | Service | Method | What it is for |
|---|---|---|
WfeDefinitionService | upsert(dto) | Standard save of the whole aggregate. Refuses a change of a workflow delivered with the product, validates the uniqueness of the code, versions the definition when it has instances |
WfeDefinitionService | deploySystemWorkflow(dto) | The only write path that marks a workflow as delivered with the product. Used by the deployment |
WfeDefinitionService | duplicate(id) | Independent copy, see Copying a workflow |
IdmBusinessProcessService | supports, shouldBeStarted | Decides whether a process applies to an event and whether it claims a concept |
WorkflowEventTypeManager | findByCode(code) | Resolves the triggering event. Returns an empty Optional for an unknown code instead of failing |
| Code | Status | When |
|---|---|---|
SYSTEM\_WORKFLOW\_DELETE\_FAILED | 400 | Delete of a workflow delivered with the product |
SYSTEM\_WORKFLOW\_UPDATE\_FAILED | 400 | Change of a workflow delivered with the product outside the deployment |
SYSTEM\_WORKFLOW\_CODE\_CHANGE\_FAILED | 400 | Change of the code of a workflow delivered with the product |
SYSTEM\_WORKFLOW\_ID\_OCCUPIED | 400 | Another workflow occupies the identifier of a shipped one. Raised during the deployment, so it prevents the start |
WORKFLOW\_CODE\_NOT\_UNIQUE | 400 | Another current definition already uses the code |
BUSINESS\_PROCESS\_CODE\_NOT\_UNIQUE | 400 | Another approval process already uses the code |
WfeDefinitionContentSignature expresses the content of a definition by its natural keys, so two definitions can be compared regardless of their identifiers. The layout is deliberately outside the signature.InitSystemWorkflowProcessor deploys the shipped batch, InitBusinessProcessProcessor creates the default approval. A module that ships its own default approval follows the second one (see the module rec) and reuses IdmBusinessProcessService.DEFAULT\_APPROVAL\_WORKFLOW\_CODE and DEFAULT\_APPROVAL\_PROCESS\_ORDER.| Service | Method | What it is for |
|---|---|---|
WfeDefinitionService | upsert(dto) | Standard save of the whole aggregate. Refuses a change of a workflow delivered with the product, validates the uniqueness of the code, versions the definition when it has instances |
WfeDefinitionService | deploySystemWorkflow(dto) | The only write path that marks a workflow as delivered with the product. Used by the deployment |
WfeDefinitionService | duplicate(id) | Independent copy, see Copying a workflow |
IdmBusinessProcessService | supports, shouldBeStarted | Decides whether a process applies to an event and whether it claims a concept |
WorkflowEventTypeManager | findByCode(code) | Resolves the triggering event. Returns an empty Optional for an unknown code instead of failing |
| Code | Status | When |
|---|---|---|
SYSTEM\_WORKFLOW\_DELETE\_FAILED | 400 | Delete of a workflow delivered with the product |
SYSTEM\_WORKFLOW\_UPDATE\_FAILED | 400 | Change of a workflow delivered with the product outside the deployment |
SYSTEM\_WORKFLOW\_CODE\_CHANGE\_FAILED | 400 | Change of the code of a workflow delivered with the product |
SYSTEM\_WORKFLOW\_ID\_OCCUPIED | 400 | Another workflow occupies the identifier of a shipped one. Raised during the deployment, so it prevents the start |
WORKFLOW\_CODE\_NOT\_UNIQUE | 400 | Another current definition already uses the code |
BUSINESS\_PROCESS\_CODE\_NOT\_UNIQUE | 400 | Another approval process already uses the code |
WfeDefinitionContentSignature expresses the content of a definition by its natural keys, so two definitions can be compared regardless of their identifiers. The layout is deliberately outside the signature.InitSystemWorkflowProcessor deploys the shipped batch, InitBusinessProcessProcessor creates the default approval. A module that ships its own default approval follows the second one (see the module rec) and reuses IdmBusinessProcessService.DEFAULT\_APPROVAL\_WORKFLOW\_CODE and DEFAULT\_APPROVAL\_PROCESS\_ORDER.IdmNamedConditionService publishes a delete event and the row is removed by IdmNamedConditionDeleteProcessor. Without such a processor a delete is a silent no operation - no exception and nothing deleted.systemWorkflow is serialized but never deserialized, so reading a response back into the DTO always yields `false`. Assert such a property against the raw json.