Fundamentals about parallel executions via JMS queues
Most implementations that will be executed on a Netweaver system like message-driven beans (MDBs) or stateless session beans (EJBs) will be executed in a single thread. That is ok for simple and low performance tasks, but in case of high volume or high performance intensive operations it would be helpfully to split such tasks into small peaces that will be executed seperately.
Inside of this article I will show you the theoretical fundamentals about parallel executions via JMS queues inside of a Netweaver system.
An example for this appraoch can be found inside the blog article Resume error suspended BPM processes via job implementation
- real parallel execution in a JEE conform approach
- parallel execution on multiple server instance/server nodes in a clustered environement
- possibility of high performance in high volume situations
- monitoring of results in case of success, error or exceptions
The idea to fulfill the requirements is the usage of several JMS queues that can be used for a specific execution.
For this it is helpfully to have a set of three JMS queues:
- one queue to trigger the parallel execution,
- one queue to get response message from the message consumer and
- one queue for error in case of JMS issues.
Besides the JMS queues a message producer (like EJBs or MDBs -> e.g. in case of a job implementation or another Java implementations) and a message consumer (MDBs) are necessary to realize this approach.
The following figure should visualize this interaction in a comprehensible way:
Hint: I recommend to create this set of 3 queues with unique queue names for every task that you plan to realize. For sure if you have 5 tasks to realize than you will have 15 queues at the end, but in case of monitoring or detail analysis it is much easier to look into seperate queues than into 3 queues that habdles all message and where you don’t see with message is for which task.
One of the important steps at the beginning of this interaction is the implementation of the JMS message producer. This part has to determine the items that have to be executed in parallel. This implementation can be a stateless session bean (EJB), a message-driven beans (MDB) or any other Java implementation that can be triggered by an user interaction (WebDynproJava, SAPUI5, etc.) or by external system via REST- or WebService- calls.
This determination/selection must be done in one single thread implementation otherwise your implementation would try to handle the same item/object in different multi-threads and you will get issues later regarding access, update or deletion of items (based on your task/requirement) during execution.
After this determination/selection the message producer should split this huge working set into smaller peaces that can be executed in parallel because they are real separated from each other.
After splitting these items the message producer will send the created JMS messages into a trigger queue.
Hint: I recommend to create messages with configurable content sizes. With such a parameter it is easier to control the payload and the number of messages that will be created at runtime and you can maintain it easier than hard coded sizes
After sending the JMS messages the producer cannot be terminated or finished. The reason is that the message producer has to wait for the responses of the message consumer by receiving messages via response queue or issue via error queue.
To prevent that the message produces wait until Judgement day this waiting time slot should be limited to a maximum waiting timeout (e.g. current start time + x minutes in the future).
The queues itself storing trigger, response or error messages.
Attention: In case you try to schedule the execution of one tasks via a job in parallel it is recommended to send a unique id inside of the trigger message. This unique identifier can be set inside the response message for the JMS field correlation id. When this field is filled the corresponding message producer can select only the message that are relevant for him.
On the side for the message consumer should be used a MDB implementation that listen to the trigger queue. In case a message was send the consumer MDB receives the message automatically and can begin the execution. During the execution the MDB has to store the results for every item execution into a list or a map. This is necessary than before the MDB execution will be finished the MDB has to send a response message via response queue back to the message producer. Via this message the producer will be informed about success or failure of the item execution. After sending this response message the MDB can be finished.
The last step in this interaction is again on producer side. After receiving response messages and/or error messages the produce should preparing these details into a more readable format.
For job implementaion it is very easy to store such content into the job log. In case of EJBs or other implementations it can be stored into a seperate log file, database tabel or into default trace. Please don’t ignore these step during the implementation otherwise it is very hard to identify and to monitor behaviours or exception in your runtime systems. In case of an user interaction it is recommend to give the end user a feedback via notifications or success/error messages. Nothing is more frustrating that a function who don#t give you a feedback.
This approach is not only a theoretical construct of an implementation pattern. I have used this approach inside of different job implementaions in my projects.
The advantage and the experience inside of a productive runtime systems shows that the execution is really parallel and in case of high volume items the execution is much faster than in a single thread implementation that interates via a loop over through all items.
E.g. one of my jobs checks substitution rules in a BPM system and if one of the involved substituting or substituted participants are deleted inside the identity management than the substituion rule has to be removed automatically by the system and not via BPM support tool and/or an administrator interaction. The execution time for this job has shown that with this parallel approach the execution time is less than 2 minutes for more than 23000 substitution rules. Beforehand it was much higher (between 30 and 45 minutes).