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 :validation

the 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