Forum Stats

  • 3,875,518 Users
  • 2,266,939 Discussions


SOA Messaging Reliability through JMS and Oracle Service Bus

Bob Rhubart-Oracle
Bob Rhubart-Oracle Member Posts: 692 Silver Badge
edited Apr 30, 2015 8:25AM in SOA Suite Discusssions

by Sebastian Lik-Keung Ma

This article describes the design of a reliable messaging solution for SOA integration projects. It uses concepts like canonical schemas, durable POJO (Plain Old Java Object) messages, publish-subscribe and error handling within the Oracle SOA, Oracle Service Bus and WebLogic JMS infrastructure.

The JMS Message

For consistency, the type of message we are publishing will be based on a canonical schema. Typically, you would have a JDeveloper project that stores the canonical schemas used by all your custom applications. These schemas could be version-controlled, e.g. by Subversion, as well as deployed to MDS as a SOA bundle. Sample JDeveloper project containing canonical schemas shown below.


Figure 1. JDeveloper project containing canonical schemas

In this article, we will use the employeeWorkSchedule schema as our message type.

<?xml version = '1.0' encoding = 'UTF-8'?>
<xsd:schema xmlns:xsd=""

    <xsd:import schemaLocation="common_v1_0.xsd" namespace="" />

    <xsd:element name="employeeWorkSchedule" type="empws:tEmployeeWorkSchedule"/>
        <xsd:documentation>Definition of an Employee Work Schedule message</xsd:documentation>
    <xsd:complexType name="tEmployeeWorkSchedule">
            <xsd:element ref="empws:employeeWorkScheduleInfo"/>
            <xsd:element ref="cmn:messageProperties"/>
            <xsd:element ref="cmn:standardResponse"/>
            <xsd:element ref="cmn:standardFault"/>

Publishing JMS message from ADF Java application

We publish our message to JMS from ADF applications. To simplify the process of using Java to construct message objects based on our XSD canonical schema, we use the JAXB (Java Architecture for XML Binding)

tool from JDeveloper.

As shown in Figure 2a below, select the XSD file, right-click and select “Generate JAXB 2.0 Content Model”.


Figure 2a. JDeveloper JAXB generator


Figure 2b. JDeveloper JAXB generator

The generated POJO classes can be stored and version-controlled in a separate JDeveloper project. See Figure 2b where the output source goes to a directory different from the schema file. This project will produce the JAR file to be referenced by other ADF applications. Figure 2b shows the generated POJO classes.


Figure 2c. Generated POJO classes

The ADF application that wants publish the canonical message will include the JAR file in its project properties. See Figure 3 below.


Figure 3. Referenced library JAR file containing the JAXB generated POJO classes

The Java codes in an ADF application can now construct the JMS message based on strongly-typed POJO classes, e.g. TEmployeeWorkSchedule and TEmployeeWorkScheduleInfo below.

import com.scm.soacommon.xsd.common.TMessageProperties;
import com.scm.soacommon.xsd.employeeworkschedule.ObjectFactory;
import com.scm.soacommon.xsd.employeeworkschedule.TEmployeeWorkSchedule;
import com.scm.soacommon.xsd.employeeworkschedule.TEmployeeWorkScheduleInfo;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class EmployeesImpl extends EntityImpl {
    private TEmployeeWorkSchedule constructEvent() {
        String msgId = UUID.randomUUID().toString();
        com.scm.soacommon.xsd.common.ObjectFactory cmnFactory =
            new com.scm.soacommon.xsd.common.ObjectFactory();
        ObjectFactory wsFactory = new ObjectFactory();

        TEmployeeWorkSchedule ws = wsFactory.createTEmployeeWorkSchedule();
        TEmployeeWorkScheduleInfo info = wsFactory.createTEmployeeWorkScheduleInfo();

        try {
                        new GregorianCalendar(
        } catch (DatatypeConfigurationException e) {

        TMessageProperties msgProps = cmnFactory.createTMessageProperties();

        return ws;

WebLogic JMS Topic

JMS Topic not only supports publish-subscribe messaging model, it also provides better reliability via message durability. This means that JMS only removes the message from its topic when all durable subscribers have received the message. As long one subscriber is down or unavailable, the message will remain in the topic or until the message expires. The expiration property (Expiration Time for Incomplete UOW Messages) can be configured in WebLogic Admin console. The default value of -1 indicates the message never expires.


Figure 4. To set message expiration value, click on the Advanced link.


Figure 5. Default message expiration value is -1, i.e. message never expires.

Setting a default Durable Subscriber

Messages, once consumed by all subscribers, will disappear from the JMS topic. For tracing and debugging purposes, you can create an additional subscriber in WebLogic Admin console. This subscriber will collect the consumed messages within WebLogic. See Figure 6 below.


Figure 6. Default durable subscriber created.

To examine a message, click on the Show Messages button.

A sample message detail is shown below.


Figure 7. Message detail

Note that the additional key-value property is set by the message publisher.

Design of SOA Messaging Reliability through JMS and OSB

The overall design of a reliable messaging solution in SOA is demonstrated in the diagram below.


Figure 8. Overall design of a reliable messaging solution in SOA

  1. ADF application publishes the message to its JMS Topic. It is important to comply that messages published within the boundary of all custom applications be based on canonical schemas.

    : The message publisher can set custom key-value message property so that subscribers can subscribe to message of interest only. See sample codes below.

    try {
         ObjectFactory wsFactory = new ObjectFactory();
         TEmployeeWorkSchedule ws = wsFactory.createTEmployeeWorkSchedule();
         TextMessage textMsg = session.createTextMessage();
         // adds a property for JMS message selector
         textMsg.setStringProperty("schema", ws.getClass().getName());     sender.send(textMsg);
    } catch (JMSException jmse) {

  2. An OSB Proxy Service subscribes to the JMS Topic. Retry threshold is set in JMS Redelivery Limit.

    : As long as the message publisher sets custom header properties for a message type, the Proxy Service can selectively subscribe to messages of interest only. This method is applicable if you have other Proxy Services that subscribe to the same JMS Topic for other message types.

  3. On receiving the message, the Proxy Services transforms canonical message to the 3rd Party message, then routes it to an OSB Business Service.
  4. The OSB Business Service then invokes the a 3rd Party Web Service.

  5. The Error Handler will be invoked for each failed invocation.

    Hint: Contrary to programming analogy, error in OSB is raised not after all retries have failed. It is important to understand that an error is raised to the Error Handler for each failure, including for each failed invocation by the Business Service.

  6. The Error Handler will determine the course of action to take. If retry threshold has exceeded, the Error Handler will re-publish the original ADF message to another JMS Topic to be “retried” by another Proxy Service.

  7. The number of JMS Topic-retry is dependent on individual application requirements.

  8. The final Proxy will determine the last action to take, i.e. when it has exhausted all retry attempts. Here, the final Proxy’s Error Handler invokes a SOA Composite. This composite simply contains a BPEL Logger that logs error messages to (ODL) Oracle Diagnostic Logging. ODL logs can be retrieved from Oracle Enterprise Manager and/or soa_server log files.

OSB Configuration

To configure OSB in Oracle SOA Suite 11g, you can use either the OSB web console or Oracle Enterprise Pack for Eclipse (OEPE). In our development environment, we use OEPE. To enable OSB Proxy Service as a JMS durable subscriber, the typical OSB configurations are described below as self-explanatory screenshots.


Figure 9. Conguration page - Service Type set to Messaging Service


Figure 10. Message Type Configuration page – Request Message Type set to XML with known canonical schema


Figure 11. Transport Configuration page – Get All Headers set to Yes

Figure 11, above, shows Get All Headers set to Yes. This is to ensure that all message headers, including custom message key-value properties, are received from the JMS Topic.


Figure 12. JMS Transport Configuration page – Message Selector and Durable Subscription settings

Figure 12, above, shows the setting of the Durable Subscriber to receive message of interest only via Message Selector.

Intricacies of Retries and Error Handling

This section details the scopes of the routing components inside the OSB Proxy Service. As shown in Figure 13 below, we have a “Route to Business Service” on one side and an “Error Handler” on the other.


Figure 13. OSB Proxy Service - Message Flow

Route scope

In the Routing node, you will set the OSB Business Service and operation to invoke.


Figure 14 Routing node – Business Service

We highlight the various actions inside the Routing node shown in Figure 13 above.

  1. Assigns original incoming message body to a variable – body_source. The value of this variable will be used in Error Handler scope


    Figure 15. Assigns original message body to variable

  2. Assigns custom message property value to a variable – jms_property_schema. The value of this variable contains the schema name used by subsequent JMS Subscriber’s message selector


    Figure 16. Assigns the value of a custom message property to variable

  3. Transforms incoming canonical message to outgoing 3rd party message. XQuery is used for the transformation. The outgoing message body will be replaced by the result of the transformation.


    Figure 17. Replace outgoing message with transformed message

Error Handler scope

Our Error Handler performs error-handling action only if invocation of Business Service failures exceeds a threshold.

    1. Checks if retry count exceeds threshold. There are three known retry mechanisms in OSB:

      Note: WebLogic Server supports the JMSXDeliveryCount message property, which specifies the number of message delivery attempts, where the first attempt is 1, the next attempt is 2, and so on. WebLogic Server makes a best effort to persist the delivery count, so that the delivery count does not reset back to 1 after a server reboot. (From WebLogic Admin Console documentation for JMS Redelivery Limit)

      With this note in mind, we are using the third mechanism for our solution. The “If” condition checks if retries exceeded a threshold of 3, or if errorCode is BEA-380001.


      Figure 18. Checking if JMSXDeliveryCount exceeded threshold

      If the “If” condition is true, the Error Handler will publish a message to another JMS Topic for further retries.

      • Setting retry count on Business Service: In this mechanism, the Proxy will send the request to Business Service and wait for a response. Business Service will retry the destination service in case of failures depending on the retry count and delay. When Business Service retries it will NOT send a value of retry count in any way to the destination service. The number of retries made by the Business Service will also not be known by the Proxy service. In this case, you do not have knowledge of the number of tries it took.
      • Setting retry count and retry delay as routing options in Proxy while calling the Business Service: This mechanism is similar to that above; Proxy will send request only once to Business Service, and Business Service will retry. The only difference is that Proxy will set the Business Service’s Retry Count and Delay dynamically instead of configured values in the Business Service configuration. In this case, $outbound variable will have the Retry Count variable and the value would be the one set at design time. This value will not change at any time during the processing of Proxy. That is, if you had set the retry count as 5 in the routing option, $outbound will have a value of retry count as 5. Even if Business Service got a success response in only 2 retries, the value will not change in $outbound of Proxy.
      • Adding a JMS queue in the flow before the Proxy Service and setting the retry count and delay on the JMS queue: In this mechanism, the JMS server controls the retry count and the Proxy itself is invoked multiple times according to setting of retry on JMS Queue.
    2. Replaces outgoing message with original incoming message. The Error Handler will send the original failed message to a retry JMS Topic. However, due to the stateless nature of OSB, the original message from the Route scope is unavailable. As a workaround, we have stored the original message in step a variable $body_source. Now we need only to replace the outgoing message with the original message content stored in $body_source


      Figure 19. Replace outgoing message with original content

    3. Sets custom key-value property to message header. Similary, if we want subsequent Subscriber to be able to receive only message of interest, here we set the custom key-value property for use as message selector.


      Figure 20. Set custom key-value message property in Transport Header


[1] Richards, Mark, Richard Monson-Haefel and David A. Chappell, Java Message Service (O’Reilly, 2009, 2nd ed.).

[2] Walmsley, Priscilla, XQuery (O’Reilly, 2007).

[3] Oracle Community FAQ  “OSB Logging re-try count value” (

About the Author

Sebastian Lik-Keung Ma ( @Sebastian Ma) has been a Software Engineer and Craftsman in Singapore and Germany, specializing in distributed software applications written in C++, Java and C#. He currently works as a SOA Practitioner and Software Development Manager in Singapore.

Note: This article has been reviewed by the relevant Oracle product team and found to be in compliance with standards and practices for the use of Oracle products.


  • Sorry, do I understand correctly that this solution is not using transactions in JMS?

    I'm not fully familiar with durable subscribers... Will the message get lost if between the moment it was read from the topic by the proxy and the moment it was sent to the subscriber, the JVM crashes?

    Vlad @

  • Sebastian Ma
    Sebastian Ma Member Posts: 3
    edited May 11, 2015 1:39AM

    JMS message delivery, JMS transacted messages and XA transactions are different but related concepts.

    JMS server will send Acknowledgement to the producer if the message is successfully persisted or throws exceptions to the producer if not.

    From JMS server's perpective, the acknowledgement sent to the producer is not tied to the delivery of the message to consumer(s).

    JMS server will not remove the message from its storage unless it receives Acknowledgement from its consumer.

    For durable subscribers, the JMS server does not consider a message fully delivered until it receives Acknowledgements from all recipients.

    Hope this helps.


    Vlad Dyuzhev
  • AnuragGSOA
    AnuragGSOA Member Posts: 71 Blue Ribbon

    JMS message delivery, JMS transacted messages and XA transactions are different but related concepts.

    JMS server will send Acknowledgement to the producer if the message is successfully persisted or throws exceptions to the producer if not.

    From JMS server's perpective, the acknowledgement sent to the producer is not tied to the delivery of the message to consumer(s).

    JMS server will not remove the message from its storage unless it receives Acknowledgement from its consumer.

    For durable subscribers, the JMS server does not consider a message fully delivered until it receives Acknowledgements from all recipients.

    Hope this helps.


    Hi, I had once used an approach for JMS Reliability using XA Transaction in for proxy service and business service in a single transaction line. That way, I had not used custom error handler. In such a scenario, suppose, Business service throws an error, then the message gets rolled back to the JMS queue, and based on number of retries configured for the Queue, the message is redirected to another Queue which was configured as an error queue for the service Queue. What you have defined is custom error handling for JMS reliability. That is also one good option. Though in case of Multiple proxy services call in sequence, PS-->PS-->BS, we would need to have XA transaction or Custom error handler for each PS. Please correct me if I have understood correctly. Regards, Anurag Gupta

  • Great Solution! Would you be able to share source code for the solution?

  • AnuragGSOA
    AnuragGSOA Member Posts: 71 Blue Ribbon

    Great Solution! Would you be able to share source code for the solution?

    are you asking me ?

  • Jang-Vijay Singh
    Jang-Vijay Singh Member Posts: 418 Bronze Badge

    Agreed this shows how to implement reliable messaging via a publish-subscribe pattern using JMS.

    Wouldn't using EDN (events published by ADF business components that can be subscribed by SOA and uses JMS behind the scenes as well) offer a more declarative approach for the same thing in ADF - especially since you appear to have the SOA suite on the consumer side as well. 

    (For non SOA/ADF consumers, one could simply write a mediator that consumes the event and calls the non SOA consumer).

    Just an option to consider when you have got ADF/SOA technology available..