JBPM, workflows, migration
Jbpm story
- jbpm 6 used since dx 7.0, causing a huge reset of jbpm tables from jahia 6.6 to dx 7.O
- we have core services on top of Jbpm, WorkflowService.
- jbpm have a lot of DB tables, you can see them in the jahia DB, so it's hard to fix something in it without break everything
- we have a tool interface to manage workflows but it' not always enougth for debugging
customer 1
- customer make a mistake they migrate a 7.0 to 7.1.2.1 with some workflow not finished.
- the issue was locate in our Service WorkflowService,
we translate every jbpm classes in our classes, and we try to transform worflow peoples in jahia groups, or jahia users.
- But in 7.1 the groups have been refactor so the key to access a group is not the between 7.0 and 7.1.2.1
- The workflow after migration was buggy, and the core API totally unusable because every function crash Exceptions trying to transform jpbm object in our object
Resolution
Two possible solutions:
- remove the buggy worflows from DB, or using jbpm service since DX core API is not usable, and clean up
- flush all jbpm tables and flush everythings related to workflow in jahia.
first solution
- identify the buggy worflows:
select * from jbpm_people_assignm_pot_owners;| 3929 | 1666 | Webmaster-MMA:4 |
|---|---|---|
| 3930 | 1666 | Webmaster-MMA:4 |
| 3931 | 1666 | administrators:0 |
| 3932 | 1741 | /sites/mmafr/groups/site-administrators |
| 3933 | 1741 | /sites/mmafr/groups/Webmaster-MMA |
| 3934 | 1741 | /groups/administrators |
- workflow with id <= 1666 are 7.0 worflow, we need to cancel all this worflows if there are still active
first solution
- search for all workflows active under 1666 as process id:
select * from jbpm_task where id <= 1666 && status != "Completed"
&& status != "Exited" && process_id like "%step-publication%";This query retrieved a lot of entries, make it hard to do it manually, because there is a lot to clean for each entry:
- abort the workflow using jbpm service
- unlock the nodes for publication
- remove the task node under the users
... we could do it with a groovy script, but write the script to query the DB for getting informations is time consuming.
first solution
- for each workflow we can get all his informations
select * from jbpm_variable_instance_log where process_instance_id = 1666;| nodeids | [764034ca-edf0-41f5-a2a2-385a237d56f4, ca239614-2552-4634-ac46-8fcda1b86526] |
|---|---|
| workspace | default |
| nodePath | /sites/ACMESPACE/home/main/article-1 |
| user | /users/root |
| locale | en |
Useful informations on the object we have to flush
first solution
When a workflow is started on a node to be published, the node is locked for the publication to avoid publish it again during the workflow.
foidentify locked nodes you can do (JCR SQL2):
SELECT * FROM [jmix:lockable] as l where l.[j:lockTypes] LIKE '%publication-process%'j:lockTypes:
[raw: length=34] publication-process-8 :validation
[raw: length=34] publication-process-9 :validationthe nodes retrieved have properties like:
Showing the processes locking the node
first solution
Clean up phase, unlock the nodes:
QueryWrapper q = session.getWorkspace().getQueryManager().
createQuery("SELECT * FROM [jmix:lockable] as l where l.[j:lockTypes]
LIKE '%publication-process%'", Query.JCR_SQL2);
JCRNodeIteratorWrapper ni = q.execute().getNodes();
for (JCRNodeWrapper node : ni) {
node.clearAllLocks();
if(node.hasProperty("j:processId")) {
node.getProperty("j:processId").remove();
}
}solution
Clean up phase, Abort a worflow and remove the associate node:
JCRTemplate.getInstance().doExecuteWithSystemSession(new JCRCallback<Object>() {
@Override
public Object doInJCR(JCRSessionWrapper session)
throws RepositoryException {
QueryWrapper q = session.getWorkspace().getQueryManager().
createQuery("select * from [jnt:workflowTask]
where [taskId]='" + PROCESS_ID + "'", Query.JCR_SQL2);
JCRNodeIteratorWrapper ni = q.execute().getNodes();
for (JCRNodeWrapper wrapper : ni) {
wrapper.remove();
}
session.save();
return false;
}
});
WorkflowService.getInstance().getProviders().get("jBPM").abortProcess(PROCESS_ID); final solution
But at end we choose the easy solution ... doom everything related to worflows on the instance.
- execute the jbpm-schema.sql from fix apllyer
- remove all workflow nodes
- unlock all the nodes locked by publication
Workflow tips:
- each DX workflow have an entry in the jbpm_task table, with the type, the status and the process id.
- each DX workflow have multiple entries in the table jbpm_variable_instance_log where the infos on the workflow are stored, nodes published, locale, workspace, etc ...
select * from jbpm_task where id <= 1666 && status != "Completed"
&& status != "Exited" && process_id like "%step-publication%"; select * from jbpm_variable_instance_log where process_instance_id = 1666;Workflow tips:
- each DX publication workflow is locking the corresponding node
- A node an be manually unlocked by calling Publication Service:
j:lockTypes: [raw: length=34] publication-process-4 :validation JCRPublicationService.getInstance().unlockForPublication(Arrays.asList
("764034ca-edf0-41f5-a2a2-385a237d56f4"), "default", "publication-process-4"); - Or by removing all the locks on the node:
node.clearAllLocks();Find all the locked node for publication query:
"SELECT * FROM [jmix:lockable] as l where l.[j:lockTypes] LIKE '%publication-process%'"Workflow tips:
- each DX workflow have a dedicated node in the JCR, it's handle by the Core API WorkflowService
- This nodes are used to display the task availables and there states in the user dashboard "my Tasks" UI
"select * from [jnt:workflowTask] where [taskId]='" + PROCESS_ID + "'"Workflow tips:
- Custom workflow can be implemented and registered from modules using spring configuration.
Default module is actually in charge of publication workflows:
/default/src/main/resources/org.jahia...defaultmodule/1-step-publication.bpm2
Spring def:
<bean class="org.jahia.services.workflow.WorklowTypeRegistration">
<property name="type" value="publish"/>
<property name="definition" value="1-step-publication"/>
<property name="canBeUsedForDefault" value="true"/>
<property name="defaultPriority" value="1"/>
<property name="permissions" >
<map>
<entry key="start" value="publication-start"/>
<entry key="review" value="publication-review"/>
</map>
</property>
<property name="forms">
<map>
<entry key="start" value="jnt:simpleWorkflow"/>
<entry key="review" value="jnt:simpleWorkflow"/>
</map>
</property>
</bean>Workflow tips:
The WorkflowService API is in charge of transforming JBPM objects in Dx objects (with nodes, users, groups, etc.)
If for some reason WorkflowService API can't be used, you can interact directly with JBPM service, for exemple abort a process with core API is not working with this call:
WorkflowService.getInstance().getProviders().get("jBPM").abortProcess(PROCESS_ID); WorkflowService.getInstance().abortProcess(PROCESS_ID); You can try a direct call on JBPM service instead:
Workflow tips:
- The tools can help you abort a workflow, but it's using the Workflow core API behind
- Don't hesitate to look in the db to understand what are the states of workflows and datas
Jbpm talk for support team
By Kevan Jahanshahi
Jbpm talk for support team
- 1,126