Skip to Content
Technical Articles

Cloud Integration – Configure Asynchronous Messaging with Retry Using JMS Adapter

This blog describes options for configuring asynchronous one-way message processing using the new JMS adapter, which is now available for customers. It describes the setup, configuration, size limits and monitoring of your scenario. The JMS adapter is available for SAP Cloud Integration customers with an Enterprise Edition license since 24-June-2017 release (2.29*).

Asynchronous Messaging with Retry Using the JMS Adapter

In many cases integration scenarios have to be decoupled asynchronously between sender and receiver message processing to ensure that a retry is done from the integration system rather than the sender system. This can be achieved, for example, by using JMS queues to temporarily store the messages in the Cloud Integration system if the receiver system cannot be reached, and retry them from there. Follow the steps described below to activate the message broker and to setup the scenario. Use the monitoring tools described to check the processing and view the stored messages in the queue monitor.

Prerequisite: Broker Provisioning

To be able to use JMS queues for storing messages you first need to activate the message broker for your cloud integration tenant. If you have an Enterprise Edition license you can do this for your tenant in Cloud Integration Provisioning via Provision Broker. You can see then the active message broker and its details. You can now start using the JMS adapter to configure your scenario.

This is described in detail in blog ‘Activating and Managing Enterprise Messaging Capabilities’.

Setup Scenario With Asynchronous Decoupling

To configure the decoupling of inbound and outbound message processing you need to configure two processes:, one process to receive the inbound message and store it in the JMS queue and a second process to trigger the message from the JMS queue to the receiver backend. The blog describes the configuration using two separate integration flows.

Configure the Integration Flow Receiving the Message

The first integration flow will be configured to receive the message via any inbound adapter. In this sample setup we use the HTTP adapter.

Configure the JMS Receiver Channel

Create the integration flow with the inbound channel required by your scenario, and use the JMS adapter as the outbound adapter. You only have to configure the Queue Name for the JMS queue that will be used to store the messages. It is Important to set an Expiration Period that suits your scenario. The default value is 90 days’, which means that after 90 days any messages, that were not delivered within this period will be deleted from the queue.

With the 10-December 2017 release, you will have the option to configure, if exchange properties are forwarded to the JMS queue. Before, the properties were always forwarded along with the message, which caused severe issues in some scenarios. The default value of the option will be that properties are not forwarded, because this could lead to runtime issues if the properties are too large. In detail the size restrictions are described in the Blog ‘JMS Resource and Size Limits’.

This option is available in adapter version 1.1.

Configure Transaction Handling

You need to configure the correct transaction manager in the integration process for transactional end-to-end processing. Our process does not contain any JDBC resources (data store, variables, aggregator), and only one direct JMS Receiver without splitter or sequential multicast; so we don’t need a specific transaction handler. Select the integration process and switch to the Processing tab. In Transaction Handling drop down select Not Required.

More details about the different transaction handling options and existing limitations are described in the blog ‘How to Configure Transaction Handling in Integration Flow’.

Deploy the Integration Flow

Now you can deploy the integration flow. During deployment, the specified queue will be created automatically in the message broker. You can check that the queue has been created in the Queue Monitor available in the operations view in the Manage Storages section. The monitor is described in more detail in the Monitoring section below.

If a message broker has not yet been provisioned, the deployment will end with an error. In Manage Integration Content the error details for your integration flow tell you that no messaging host is available.

Configure the Integration Flow Doing the Retry

To consume the messages from the JMS queue, you configure a second integration flow with a JMS sender channel and the outbound adapter needed for your scenario. In this sample configuration we use the HTTP adapter.

Configure the JMS Sender Channel

Create the integration flow with the outbound channel required by your scenario, and use the JMS adapter as the inbound adapter. You only have to configure the Queue Name for the JMS queue that you want to poll the messages from. Use the same queue name used in the receiving integration flow.

Number of Concurrent Processes is set to 1 per default and should only be increased if more parallel processing is needed. Because the JMS resources are limited, you need to keep the number of parallel processes as low as possible. Especially if large messages are processed in the scenario, increasing the parallelism may lead to out of memory problems.

In the JMS sender channel you also have to configure the retry handling. Set the Retry Interval as required for your scenario (, the default value is 1 minute). We also recommend using Exponential Backoff, which means that the retry interval is doubled after each unsuccessful retry. By using this setting you can avoid calling the receiver backend every minute if it is unavailable for a longer time period. The Maximum Retry Interval defines the maximum time between two retries if exponential backoff is used. The recommendation is to either keep the 60 minutes or even increase it if this is acceptable by the scenario.

Note, that the JMS sender does not guarantee the order in which the messages are consumed. If several processes are configured to consume messages and/or multiple worker nodes process messages, the messages are processed in parallel. Furthermore, in case the message is in retry because of an error it is taken out from processing until the retry interval is reached.

With 22-July-2017 release the option to configure a dead letter queue is introduced. This is described in detail in blog How to configure Dead Letter Handling in JMS Adapter.

Configure Transaction Handling

If you are using JMS Sender, it is not necessary to set the transaction handling to Required for JMS, because the retry handling works independently of the selected transaction handler. You should select the transaction manager as required by the scenario that you have configured in the integration flow.

In the simple example shown, no JDBC or JMS resources are used, that need a transaction handler, so we select Not Required.

There are some limitations on configuring transaction handling configuration and on which flow steps can be used in which combinations. This is described in detail in the blog ‘How to configure Transaction Handling in Integration Flow‘.

Optional: Explicit Retry Configuration

In the JMS sender channel, you can configure the time intervals between retries, but you cannot configure that processing will end after a specific number of retries. If required, you can configure this in an exception subprocess that calls a local process for retry handling using the header SAPJMSRetries set by the JMS sender adapter.

Note that the header SAPJMSRetriesmay not indicate the exact number of retries in clusters with multiple worker nodes. It may happen that a retry is triggered on multiple worker nodes shortly one after the other before the message is moved to the error queue and the counter in the header is increased.

To configure this, add a Local Integration Process to the integration flow. In this process you configure the specific retry handling. In this sample, we check the number of retries executed and after 6 unsuccessful retries, we end the processing and trigger a mail to alert someone to the problem.

In the local integration process configure a Router after the start event, add an Error End Event and configure the router as shown in the picture. The header SAPJMSRetries set by the JMS adapter is used to decide if the message processing continues or if it ends and a mail is triggered. If message processing is to continue, an error is raised by the process so that the message stays in the JMS queue and goes into retry status.

We set the transaction handling to From Calling Process in the local process, and as there are neither JMS nor JDBC transacted resources configured in the local process, we take over the Not Required setting from main process.

Furthermore, you need to add an Exception Subprocess in the main process, and add a Local Process Call, where you select the configured local process, within the exception subprocess. Add a Receiver for the mail to be sent. Connect the Message End Event of the exception subprocess to the receiver using a Mail adapter receiver channel. In this channel, you configure the mail address the mail is to be sent to and the details to be sent.

With this configuration the message will be removed from the JMS queue after 5 unsuccessful retries, so that no further retries are executed. A mail is triggered to notify the appropriate person to take manual action.

If you use the explicit retry configuration, you are free to configure retries as required for your scenario. For example, you can notify someone after 3 retries but not stop the processing until 10 retries have been made, to allow enough time for manual actions. Or, you can send the message after 3 retries via an alternative receiver channel.

Deploy the Integration Flow

You can now deploy the integration flow. This completes the scenario configuration in SAP Cloud Integration and you can start processing messages. Test the configuration by sending a test message via the configured inbound adapter and check that it is received by the receiver backend.

JMS Resource and Size Limits

The connected JMS messaging instance, that is used in the asynchronous messaging scenario has limited resources. The Enterprise License sets a limit on the queues, storage and connections that you can use in the messaging instance. The limits are described in more detail in the blog ‘JMS Resource and Size Limits‘.

Performance Optimization Options

If a higher throughput is required for your scenario and you identify JMS as the bottleneck, the following options for performance increase are possible:

  • Do not use intermediate JMS queues in one end-to-end scenario. The recommendation is to use one queue after the message is received from the sender system and one directly before the message is sent to the receiver system. Depending on the scenario, one JMS queue could be sufficient as well.
  • Increase the number of parallel processes in the JMS sender channel to make sure more messages are consumed in parallel. But keep an eye on the JMS resources, see blog ‘JMS Resource and Size Limits‘.
  • Switch off Encryption in the JMS receiver channel. For scenarios without sensitive data this option could be used to increase performance.
  • Do not use the Dead-Letter Queue. The option to switch off the dead-letter queue you should only use if you can make sure that no out-of-memory errors can occur, for example because of large messags. If you have only small messages and don’t see a risk for out-of-memory situations in your scenario switching off the Dead-Letter Queue could increase the performance. More details can be found in the blog How to configure Dead Letter Handling in JMS Adapter.
  • Use the correct transaction handling. It is for example important to use a JMS transaction handler if JMS sender and JMS receiver channels are used in the same integration process. More details can be found in the blog ‘How to configure Transaction Handling in Integration Flow‘.


To check the processing in detail, you can use the monitoring tools provided by Cloud Integration.

Integration Flow Monitoring

In the operations view, in the section Manage Integration Content, you can find the deployed integration flows and their status. Check that the flows have the status Started.

Poll Status (available with the 16-Feb-2020 update)

In the Status Details area you may find the status and the details about the current consumption:


Message Monitoring

Message processing can be checked in detail in the section Monitor Message Processing. Select the message you sent and check the processing status. There should be two message processing logs, one for the inbound messaging that saves the message to the JMS queue, and one for processing the message from the queue and sending it to the receiver system.

Those two messages are correlated via a Correlation ID. With the 8th-July-2018 update of Cloud Integration, this Correlation ID is shown in the Properties of a message processing log. You can also search for all messages having the same Correlation ID using the ID search field at the top of the monitor:

In the event of a failure when sending to the receiver system the outbound message will go into status Retry. The message will then be retried as configured in the JMS sender channel. The detailed error information and the retries are available under the link Message Processing Log.

Queue Monitor

If there are problems during processing and your message does not arrive at the receiver backend, the message status is Retry and the messages can be checked in the Queue Monitor in the section Manage Storages in the Operations view. This monitor shows all queues existing in your tenant, with their stored messages. Select your queue to check the messages contained in the queue.

You can see the number of retries that have already been executed and the time of the next retry. You can also trigger an immediate retry of the message or delete specific messages if you no longer want them to be processed.

If a message broker has not yet been provisioned, the Queue Monitor tile is not shown.

Queue Deletion

If you do no longer need a specific queue, (for example if you un-deploy the integration flow), you have to delete the queue manually in the Queue Monitor. Unused queues, that do not contain messages will be deleted automatically after the May-13-2018 update. Queues containing messages cannot be deleted automatically because this could cause inconsistencies, as the messages in the queue may still have to be processed.

To find unused queues in the monitor you may use the checks described in the blog ‘Checks in JMS Message Queue Monitor’.

You must be Logged on to comment or reply to a post.
  • Thanks  for the detailed blog Mandy . This had been a long pending feature on SCI. However, hope SAP implemented the EO and EOIO QoS out of the box rather than customers to develop their own scenarios.

  • Thank you for this blog.  It is very helpful.  I am just starting to attempt to use JMS queues.  How do you recommend setting up the JMS queues?  One per message type or one per Sender?  We receive multiple transaction types from a Sender with an end point for each message type.  Would you recommend creating a queue for each message type/end point or for the Sender?  If at the Sender, how would the actual processing IFLOW look?

    These messages are being sent to our On-Premise ECC system.  I'm looking into JMS queues as a means of reprocessing transactions that we receive while our On-Premise ECC system is down for maintenance.  


      Hello Beverely,

      in general both is possible, you could route the messages based on some routing condition (based on payload) into different queues, or put all in one queue directly after receiving and do routing based on message type later. I would recommend second, because so you save the messages directly after receiving and have the retry point there. Also, you only have a limited number of queues available, see .



  • Thank you for your response.  Please understand that I am new to Cloud Integration with no PI experience.  I am stuck on two points.

    #1 - We receive multiple transaction types from a 3rd party.  Let's say Orders, Shipments, and Receipts.  We currently have one IFLOW for each transaction.  Upon receiving each, we assign the SAP application ID, save a copy of the payload, perform mapping and send the transaction to our On-Premise ECC system.  So IFLOW 1 sends to ECC address#1, IFLOW 2 sends to ECC address#2, etc.  Each IFLOW also contains an Exception sub-process to send an email notification in case of failure.   Is it best to send the data to the JMS queue before any of the current IFLOW processes, or to send the data to the JMS queue rather than directly to ECC On-Premise?

    #2 If I use just one JMS Queue for all 3 transactions, how do I read the transaction name (ns1) to determine the routing?


    Thank you for your time and any assistance that you are able to provide.


      Hello Beverely,

      as already said, both is possible:

      1. use the existing flows and just do async decoupling in each of them
      2. create one receiving flow with a JMS receiver channel and put all messages in one JMS queue and have a second flow polling the messages out, routing the messages based on a routing condition (e.g. via XPath in router flow step - more info can be found in online help) to the different receivers

      Advantages for first option:
      - you can keep the existing flows and just introduce decoupling in all the flows
      - flows/scenarios are independent
      -- flows can be updated independently
      -- higher throughput possible

      Advantages for second option:
      - one central processing flow, may be easier to maintain in futur
      - only one queue, may be an aspect if you need several scenarios with JMS, as only 28 queues are allowed in enterprise edition

      Best regards,



      to get details about the mpl id you can use the header: SAP_MessageProcessingLogID (${header.SAP_MessageProcessingLogID}).



  • Good morning, Mandy

    From my tests, it appears that the value in  SAP_MessageProcessingLogID is the same as the value in the MessageGUID, which I am including in the email error notification within my JMS IFLOW

    MessageGuid         = AFqeyBdhY5MyWg1p2NPhanK5eVtS


    I would like to also include the ID for the originating message (the IFLOW that used a JMS queue as the receiver) so that the receiver of the email error notification can easily find the originating message:

    LocalPredecessors [

    Is this possible?

    Thank you!




      Hi, ok got it wrong.

      There is no simple way to get the ID of the first message. What you can get is the Correlation ID that correlates the inbound and outbound message. With header SAP_MplCorrelationId you can get this ID. Using this ID you can then search in message monitor to get all messages belonging to this correlation ID. Note that this search is not possible in UI yet (only via the monitoring APIs), but will come in UI in one of the next takt updates.





        the search via correlation ID will be available with the next update. Details see above in the monitoring chapter.

        Best regards,


  • Good Morning.   Is it possible to configure the JMS Queues so that the retry option is FIFO?  It would be good if there is a way to control the order that the transactions are retried to insure that they post into ECC in the order that they were originally received.


    Thank you!

      • Hi Mandy,

        Is this a feature which will be on the roadmap and available soon? I have a customer at the moment, which has subscribed for the Enterprise Edition in order to get the JMS Queues and they are missing this feature to meet business requirements.

        Would be good to have the possibility to guarantee the order for the JMS queue, especially in error case. Would be good to stop the queue processing if a message can not be processed.



  • Hi Mandy,

    I have configured a similar scenario as explained by you in the above blog. The Inbound message is in json format and the message is successfully coming to CPI but in the outbound configuration it is failing and going to retry. The error is as below:

    Error Details: java.lang.IllegalStateException: Exchange property SAP_AuthHeaderName must not be null

    I have also tried by using a content modifier in the outbound scenario and specified Action: Create, Name: ACCEPT, Type: Constant & Value: application/json



      this error is thrown by the receiver HTTP adapter. I'm not really sure what you are trying to configure. Are you using principal propagation in the HTTP receiver? This requires the specific property SAP_AuthHeaderName. The property is set by the sender adapter. If you want to store the properties along with the message in the JMS queue you need to select the flag 'Transfer Exchange Properties' in the JMS receiver channel.

      But using principal propagation with an asynchronous decoupling is not really the best to do because the PP token is valid only for a short time interval (usually 30 minutes). This means if the message goes into retry for whatever reason the retries will never be successful after 30 minutes.



  • Hi Mandy,

    Is it possible at all to after a number of retries leave the message in the queue with a status "Blocked", as per the Dead Letter queue, to prevent the message from being retried again unless explicitly actioned by and end user in the queue monitor?




      No, this is not possible. If you want to end the processing after a specific number of retries you could use specific retry configuration using an exception-subprocess and store such messages in a different dedicated queue. But keeping in the same queue would mean you continue retry processing.



  • Hi Mandy,

    We would like to configure Solution Manager for capturing the errors in SAP CPI and sending alerts as detailed below:

    Do you happen to know if IFlows in status Retry are captured by Solution Manager and therefore alerts are triggered?

    Thanks for your time.




  • SAP Solution Manager does not support alerting on metrics for messages in RETRY status. Only metrics for messages in status FAILED and ESCALATED are supported.

    To cover your requirement you have to use Focused Run for SAP Solution Manager. Please refer to the SAP Support Portal for more information.

  • Hi,


    I have a problem when configuring the retry handling. My aim is to stop the retries after couple of tries. But it seems that the header property SAPJMSRetries is not available in runtime because the retry just continues even though there is the routing condition ${header.SAPJMSRetries} > ‘3’ set.

    So my question is that has this broken down during some update to the CPI or has the header name changed or why this condition is not working? I did some debugging by setting the SAPJMSRetries value to exchange property to see if its there or not and the property does not get any value.

    So can you please verify if using that header value still works for you or not?

    And is it on the road map that we could set the max retry count directly in the JMS sender adapter instead of building this functionality manually?


    • Hello,

      nothing changed in the header name. I just tested this on my cluster and there it is still working as expected. So, it looks to me that there is an issue with your configuration.

      I would propose you activate the trace for your processing and check the value of the header. Check which way the processing takes during execution, this can be easily seen in the trace visualization.

      How does your process look like? Is it really ending the processing with a message end event?

      best regards,



  • Hi,

    Thanks for your reply.

    It has been defined as Non-XML expression. I actually might know now what was the issue. Issue must have been that the header property value is lost after some external calls are made.  So I assigned the value to an exchange property in the first content modifier and then used that property in the router.

    One weird thing is still that why in the log I can see several calls although there really is only two calls made:

    So when I check the retry count from the number 9 trace it is 2. So what are the other entries? Trace for them looks like this:



    • Hi,

      this can easily be answered. Those additional runs are:

      • The very short run is triggered by our internal JMS adapter implementation moving the message from processing to the error queue, because the message is parked in the error queue until the next retry is to be run.
      • Additionally there may be additional retries triggered for different worker nodes before the message is moved to the error queue. (this can be checked based on the process ID)

      Real retries based on the configured retry interval is what you find in the JMSRetries Header.

      For your picture above this means for the runs from bottom to top:

      • Run1: first execution on process bc68481
      • Run2: retry triggered on second worker node (a90b9f8)
      • Run3: move message to error queue, executed on first worker because this worker node knows that the message was already tried (this info is kept in memory in the worker node)
      • Run4: first real retry on a90b9f8
      • Run5: retry triggered on second worker node (bc68481)
      • Run6: move message to error queue, executed on worker node a90b9f8 because this worker node knows that the message was already tried
      • Run7: second real retry on bc68481
      • Run8: retry triggered on second worker node (a90b9f8)
      • Run9: move message to error queue, executed on worker bc68481 because this worker node knows that the message was already tried (this info is kept in memory in the worker node)

      I agree that is not so easy to understand this technical details. Unfortunately it is currently not possible to hide those 'technical' runs. We will improve this in future.

      Best regards,


  • Hi Mandy,

    I might have scenario after message written to JMS, and then during retry processing, message payload changed and need to overwrite on the same (JMS Id) message in queue.

    Is overwrite possible?




  • Hi Mandy,

    I am writing the message to JMS queue using JMS receiver adapter.(iflow1)

    And also want to subscribe in two different iFlow2 & iflow3 using the same queue name (JMS sender adapter), when I do that only one iflow2 receives the message or iflow3 receives the message, but I want to subscribe in both iflow and expect a copy of the message.

    In simple terms like publishing to a topic and subscribing in different queue.

    But in CPI it is not behaving like, only one flow receives the message.

    Will I able to achieve my requirement using the JMS queue or should I need to create queue as described in the Jonathan blog (

    Please suggest me ...


    • Hello,

      this does not work, from a queue only one consume can consume a message and as soon as it is completed it is deleted.

      The JMS queues are really queues, no topics you can subscribe to. For this you would need to use another messaging system and use the AMQP adapter. You can then have a topic in the messaging system with multiple queues subscribed to this topic and for each queue you can have an integration flow consuming from this queue.

      Best regards


  • Hi, Mandy!

    I am processing a customer creation and update scenario.

    What happens is that at a certain moment an error occurs in the message and it goes to the error queue. Subsequently, before the error message is reprocessed, an update for that client arrives and processes successfully. Then it processes the queue error message and overwrites the customer data for the old data.

    Is there a possibility in the message processing that I check if this client has already been processed in a message that arrived after the error message started to be processed?



    Heber Olivar

    • Hello,

      if I understand the requirement right, it is about kind of in order processing. This is not available with the JMS adapter.

      You would have to build something on top and maybe use some variable to store a timestamp or similar. But there is no feature available out of the box.

      Best regards,


  • Hi Mandy,

    I don’t understand why SAP named it as JMS queue, it is really misleading customers and developers as well. When you say JMS, as basic it has to support Topic and queue, whereas here it supports just the queue not topic. Atleast if it had full queue functionality that would be great but here in case of error in the receiving system then complete queue functionality collapse and get into retry mode and the message is getting retried at retry interval in the mean time any new message comes then it overtakes other hanging message in queue and delivers to the subscribing queue/target in this case complete FIFO is lost which is the very basic functionality of queue(I don’t understand in what basis this is named as queue) EOIO/EO........ I hope SAP came with better naming for this feature instead of queue this should be called as BOX.

    Best Regards,

    R D Shankar

  • Hi Mandy,

    We have implemented similar retry mechanism for Sender AS2 Adapter. Also, configured AS2 settings similar to JMS.

    But, retry doesn’t stop after specified limit.

    Retries keep happening after 1, 2, 4, 8,…2n  minute intervals.


    In trace mode, I can find that it always follows “default” route not the “MaxNumberofRetriesReached”.

    Can you please guide on how to stop after two retries?



    Rutuja Surve

    • Please execute the flow via tracing and check the header you use to configure the retry count. Check how it is set. Seems either the header is not set correctly or there is an issue in your configuration.

      Best regards


      • Thank you for your response.

        I tried enabling trace mode, but unable to find SAPJMSRetries Header value. Please check the one I have found out inside Router's log content.

        Could you please suggest possible way to check this header value?


        Thanks & Regards,

        Rutuja Surve


        • Hello,

          I'm not the expert in AS2 adapter, but would in general expect it works the same way as JMS or XI. One thing you could try is to enter the header in the Allowed Header list in the integration flow runtime configuration.

          Else I would suggest to open a ticket on LOD-HCI-PI-RT-B2B

          Thank you,