Technical Articles
EIPinCPI – Transactional Client
Previous – Messaging Mapper | Index | Next – Polling Consumer
This week, we’ll study a pattern known as Transactional Client.
When do I use this pattern?
A Transactional Client is used to ensure that the state of the system is consistent. For example, a transactional client will only dequeue a message when it has successfully processed the message. This means that if the consumer of a message is crashed or does not commit the changes pertaining to the message before crashing, the message is not dequeued. Therefore, the message can simply be consumed when the consumer comes back online.
In CPI, this is the default behaviour for Message Consumers. I’ll be demonstrating that using JMS Sender Adapter.
Transactional Client in CPI
Unlike other patterns in Message Endpoints category, this pattern can be demonstrated in CPI. I have created two integration flow. One Integration flow simply puts the message in the queue. Whereas, the other integration flow consumes the message, however, sleeps for 60 seconds before completing the message processing successfully.
Integration Flow – Enqueue Message
Enqueue Message
This integration flow starts immediately upon deployment using Timer Start Event, sets the message using Content Modifier, and enqueues the message using JMS Receiver Adapter.
The Create Message Content Modifier sets the body as:
<Message>Hello World!</Message>
The configuration of the JMS Receiver Adapter is as follows:
Property | Value |
Queue Name | Messages |
Retention Threshold for Alerting (in d) | 2 |
Expiration Period (in d) | 90 |
Encrypt Stored Message | Ticked |
Transfer Exchange Properties | Unticked |
Integration Flow – Transactional Client
Transactional Client
This integration flow acts as a Transactional Client. Until the message is successfully processed, i.e., the message reaches the End step, the message will not be dequeued.
The JMS Sender Adapter is configured as follows:
Property | Value |
Queue Name | Messages |
Number of Concurrent Processes | 1 |
Retry Interval (in min) | 1 |
Exponential Backoff | Ticked |
Maximum Retry Interval (in min) | 60 |
Dead-Letter Queue | Ticked |
The Pause Groovy Script simply sleeps before returning the message as it is:
import com.sap.gateway.ip.core.customdev.util.Message
def Message processData(Message message) {
sleep(60000)
return message
}
Execution
For demonstrating, I’ll deploy the Enqueue Message integration flow first. As soon as the integration flow is deployed, the message can be seen in the queue.
Enqueued Message
Now, I’ll deploy the Transactional Client. Transaction Client consumes the message and sleeps for 60 seconds.
The monitoring shows us that Transaction Client is processing the message:
Processing the Message
While the message is being processed, the message still exists in the queue.
The message is not Dequeued yet
However, once the message processing is Successfully Completed, the message is dequeued.
Completed Message
Empty Queue
The message was only dequeued after the Transactional Client notified that the message has been successfully processed. A non-transactional client would take the message out of the queue and if the message processing fails the message is unrecoverable.
Conclusion
A Transactional Client ensures consistency of the involved systems by ensuring the message is not dequeued until the transaction is committed. In CPI, JMS Sender Adapter demonstrates the behaviour of a Transactional Client.
References/Further Readings
- Transactional Client Pattern in Enterprise Integration Patterns
- How to configure Transaction Handling in Integration Flow
- CPI Components
Hope this helps,
Bala
Previous – Messaging Mapper | Index | Next – Polling Consumer