cancel
Showing results for 
Search instead for 
Did you mean: 

Interaction with external systems

afenske
Champ in-the-making
Champ in-the-making
Hello! I have a problem. I have an Activiti process. I want to interact with external system (method invocation from Eclipse RCP application). How can I do it? I try to use JMS, but i don't have any success with it.

Best regards,
Anton Fenske.
5 REPLIES 5

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
Just write a java service task…

jbarrez
Star Contributor
Star Contributor
Without any code or exceptions it's pretty hard to guess what goes wrong 🙂

sothach
Champ in-the-making
Champ in-the-making
I think what Anton is asking (correct me if I'm wrong), is what is the best design practice, to interface between an Activiti-managed process and an external system. 
Well, that is what I am trying to understand, anyway.
My scenario is this:
  • I have an adapter to an external system, that exposes a JMS input queue.

  • Requests will be read from the queue and sent to an external system (this is a Camel routed process).

  • The response will be written to the 'replyTo' queue provided in the request.
Now I understand that setting the BPMN task as 'async=true' will facilitate this.
Two options seems to be:
    1. Call a Java delegate that manually queues the request
    2. Delegate to a CamelBehaviour element to queue the request (best option, imo)
It also seems necessary to associate at least the activiti process instance ID with the message, to facilitate the later continuation?
What I haven't figured out is from where the runtimeService.signal(id) gets called from?
Does anyone have any samples of a similar design, or suggestions as to the best practice?

thanks, roy

webcyberrob
Champ in-the-making
Champ in-the-making
You raise an interesting point here…

IMHO - for the asyn integration using message queues or similar, I would use a send message task followed by a receive message task. In terms of best practice, I would not use the process instance Id as a correlation attribute, I would have each message use its own correlation attribute (a UUID comes to mind). Rationale; what if a process instance uses many messages and each message needs a distinct correlation ID…The consequence of this design pattern is something may need to maintain a mapping between correlation Id and process instance (database mapping table per chance?). Hence now the message handler on the reply queue just needs to lookup the process instance from the correlation id and call the signal process method.

Now this brings me to the interesting point. In the above 'pattern', should it be considered best practice to model the task(s) directly after a receive task as async? Rationale; The message processing thread (client thread) should not get tied up performing process instance processing…

R

sothach
Champ in-the-making
Champ in-the-making
I have got this working, took a bit to experimentation, but here's my solution, fwiw:

1. Java delegates read and write messages to/from a message queue, the 'process bus', using the businessKey passed between Activiti tasks as the message selector - each task blocks on the queue until the message appears.
2. A ServiceTask gets execution.getProcessInstanceId() and execution.getProcessDefinitionId() and sets these values in the JMS message properties, it also sets a property "ProcessState=WAITING" and places the request on the external system adapter's input queue
3. ServiceTask flows to a ReceiveTask, putting the process into a wait state
4. External system adapter eventually places its response back onto the main process bus (replyToSmiley Happy
5. A configured listener on the process bus, selecting on "ProcessState=WAITING" now handles this message, re-queuing it (with a different ProcessState), and extracts the process details from the message header and uses these to signal the process to continue:
String executionId = message.getStringProperty ( ProcessState.PROCESS_ID);
String processName = message.getStringProperty ( ProcessState.PROCESS_NAME);
String activeTask = runtimeService.getActiveActivityIds ( executionId).get ( 0);
Execution execution = runtimeService.createExecutionQuery()
    .processDefinitionId ( processName)
    .activityId(activeTask).singleResult();
runtimeService.signal(execution.getId());
  • No need for async=true, as it turned out (ReceiveTask covers that).

  • Knowledge of the Activiti API is kept out of the external system adapter.
Any options/suggestions/improvements, folks?