Dirk Meilinger
Dirk Meilinger

Reputation: 78

Access node variables in ProcessEventListener

Fairly new to JBPM, using latest version of 6.2. I am trying to establish a process by which I can make a calls to a REST API for a legacy platform whenever certain (custom) task types are opened and again via an asynch process when they are completed at some point in the future.

At a high level the process should be something like:

Legacy App -> (REST) JBPM "StartProcess" -> (REST) Legacy App "Task A Created"

Legacy App -> (REST) JBPM "Complete Task A" -> (REST) Legacy App "Task A Completed" & Legacy App (REST) "Task B Created"

I have created and registered a ProcessEventListener and have created a hook in the AfterNodeTriggered event to make a call for nodes of a certain type. I have also created a custom WorkItem definition and added parameters which I can access in my registered WorkItemHandler. The issue I have is that I need my ProcessEventListener to retrieve a unique ID per instance (from the Legacy App) of my WorkItem and attach it to that WorkItem prior to the WorkItemHander being invoked. I can do this in the WorkItemHandler while completing the WorkItem by accessing the getParameter('key'), but I cannot determine how (or if this is possible) in a ProcessEventListener.

Can (and how do) I :

  1. Get access to parameters of a workItem (or a User Task) in a ProcessEventListener
  2. Determine the Node Type (e.g. MyCustomTask vs. "User Task") in the ProcessEventListener so that this service call is only invoked for MyCustomTask. I can get the Node 'event.getNodeInstance().getNode()' but I cannot tell what the node type is.
  3. Prevent my CustomTask from being created if there is any error on the remote service (roll back to the triggering node?).

I am fairly certain the answer is that I should be doing both of these requests in the WorkItemHandler using abortWorkItem() as necessary, but I cannot determine how I handle the corresponding asynch process as part of a WorkItemHandler solution.

Appreciate any feedback in advance!

Upvotes: 1

Views: 1029

Answers (1)

Ampie Barnard
Ampie Barnard

Reputation: 678

That is a lot of questions but I'll give it a go.

Yes, but only after its execution which does not address your requirement. But here it is nevertheless:

public void afterNodeTriggered(ProcessNodeTriggeredEvent event){
......
  WorkItemNodeInstance wini=(WorkItemNodeInstance)event.getNodeInstance();
  wini.getWorkItem().getParameters()
.....

Yes

WorkItemNode node = (WorkItemNode)event.getNodeInstance().getNode();
if(node.getWork().getName().equals("MyCustomTask"){
  .....
}else if(node.getWork().getName().equals("Human Task"){
  ......
}

Yes, but as mentioned before, the ProcessEventListener is perhaps not the ideal place. This is not for the faint-hearted but you can always provide your own implementation of the WorkItemNodeInstance somewhere in your setup code, BEFORE any process is started, like so:

NodeInstanceFactoryRegistry.INSTANCE.register( WorkItemNode.class,new CreateNewNodeFactory( MyCustomWorkItemNodeInstance.class ) );

Then you may want to override the internalTrigger method, which, depending on your requirements may look something like this:

public void internalTrigger(final NodeInstance from, String type) {
    try{
     /*my special custom code*/
        ....
        super.internalTrigger(from, type);
    }catch(MySpecialRemoteException e){
     /*my special custom exception handling*/
    }

Depending on your requirements you may also have to add a custom ProcessInstanceMarshaller to ensure persistent processes instantiate your NodeInstance and not the default one, so it does get tricky, but it is doable:

ProcessMarshallerRegistry.INSTANCE.register(RuleFlowProcess.RULEFLOW_TYPE, new MyRuleflowProcessInstanceMarshaller());

Upvotes: 1

Related Questions