Implement two-way communication among ESB components

The In-Out message exchange pattern facilitates component-to-component interaction

The Java Business Integration specification (JBI) defines a standard for building system integration applications using Web Services Description Language (WSDL) and XML-based messaging. JBI therefore aims to standardize the business-to-business integration space that was, until JBI, served by non-standardized products. Now, clients can use a JBI-compliant enterprise service bus (ESB) built by a vendor as a bundle of services that can integrate seamlessly with other services (even if developed by other vendors), as long as they adhere to the JBI specification—an impossibility before the JBI.

In this article, we look at how component-to-component interactions happen in a JBI-compliant way over an ESB, using the Loan Broker example bundled with the open source ESB ServiceMix.

A little JBI background

The primary focus of the JBI specification is to define standards in the following areas:

  1. API and architecture for business-component-to-business-component interaction
  2. Defined deployment descriptors and package mechanisms for business components and service units
  3. Monitoring and management of the lifecycle of services deployed on an enterprise service bus

JBI introduces the concept of a normalized message router (NMR), which is the backbone of all communication that happens within the ESB. As per the JBI-defined architecture, the ESB can be viewed as a conglomeration of distributed services that interact with each other to provide services to external clients. The JBI also defines a set of message exchange patterns (MEPs) based on which services (provided through components) can communicate with each other over the NMR.

In this article, we look at how the In-Out MEP is used in ServiceMix's Loan Broker example to let components communicate with each other over the NMR.

Figure 1 is an excerpt from the JBI Specification regarding the In-Out MEP.

Figure 1. In-Out MEP (as shown in the JBI Specification). Click on thumbnail to view full-sized image.

As shown in Figure 1:

  • Consumer initiates with message
  • Provider responds with message or fault
  • Consumer responds with status

Each message exchange sequence therefore has components playing the role of either consumer or producer:

  • The consumer initiates the message exchange by creating a message exchange object.
  • Consumer then sends an "in" message over the NMR.
  • Provider receives the message, processes the message, and sends the "out" message (or a "fault" message) over the NMR.
  • Consumer receives the "out" message, processes it, and ends the message exchange sequence by setting the status to "done."

Understanding the Loan Broker use-case

The Loan Broker example is an ESB implementation for the use-case described in Enterprise Integration Patterns. I suggest you read and understand the use-case as stated in this book before going forward with this article.

Here is the abstract of the use-case:

  1. The use-case begins with the user submitting a request for a loan quote to a loan broker
  2. The loan broker forwards the request to a credit agency for verification
  3. Credit agency responds with the credit rating based on the user's credit history
  4. The loan broker now submits a request for the loan quote to the lender gateway
  5. The lender gateway returns the list of qualifying banks
  6. The loan broker now sends a request to all of the qualifying banks for quotes
  7. Each bank responds with its quote for the loan
  8. The loan broker picks the best quote for the user and sends the response back to the user

About the example

The source for the Loan Broker example can be found in the [service mix install directory]\examples\loan-broker folder. The source of the Loan Broker example comes with two servicemix.xml files. The servicemix.xml file under the service mix install directory is used to start ServiceMix without any components, service, or default service units.

The other servicemix.xml file can be found under the [loan broker install directory]\examples\loan-broker\src\su folder. This file is used to install components at runtime. All components discussed later are installed based on the configurations specified in this servicemix.xml file.

The example uses the following business components, the source of which can be found under the examples in [loan broker install directory]\loan-broker\src\components\loanbroker:

  1. LoanBroker: This component serves as a hub for all the communication that happens with other components. It receives the client-supplied message from the source queue through the binding component (JmsServiceComponent). This is the component that implements the business logic to derive the best possible quote for the client. It interfaces with other components and provides the result to the client.
  2. CreditAgency: A transformation component that provides credit agency rating information based on the request from the LoanBroker.
  3. LenderGateway: A transformation component that provides as a response the list of banks that can be considered for loan processing.
  4. Bank: Transformation component that provides the rate of interest for the loan.

Other than these components, there is a ServiceMix-provided Java Message Service component, JmsServiceComponent, that is used to interface with the source and destination message queues.

Understanding the Loan Broker message flow

Figure 2 shows all the interactions that happen in the process of implementing the use-case. Each interaction is abstracted in the JBI-specified message exchange object, and each of these message exchanges is explained in the following sections.

Figure 2. Message exchanges in loan broker

The use-case begins with the client (JmsClient.java) adding a message for a loan request into the source (demo.org.servicemix.source) queue.

The following component-to-component interactions happen in the process of returning a loan quote:

  1. Client-to-JmsServiceComponent interaction
  2. JmsServiceComponent-to-LoanBroker interaction
  3. LoanBroker-to-CreditAgency interaction
  4. LoanBroker-to-LenderGateway interaction
  5. LoanBroker-to-Bank interaction
  6. LoanBroker-to-JmsServiceComponent interaction
  7. JmsServiceComponent-to-client interaction

I now discuss each of these interactions to illustrate the roles played by the components:

  • Client to JmsServiceComponent:
    1. In this interaction, JmsServiceComponent listens to the source queue and picks up the message that was added by the client.
    2. Here is the excerpt from the servicemix.xml file used to configure the JMSServiceComponent to pick up messages from the source queue:

       <sm: component>
            <bean class="org.apache.servicemix.components.jms.JmsServiceComponent">
            <property name="template">
               <bean class="org.springframework.jms.core.JmsTemplate">
                  <property name="connectionFactory" ref="jmsFactory" />
                  <property name="defaultDestinationName" value="demo.org.servicemix.source" />
                  <property name="pubSubDomain" value="false" />
               </bean>
            </property> 
            </bean>
            </sm: component>
      
  • JmsServiceComponent to LoanBroker component:
    1. In this message exchange, the JmsServiceComponent is the consumer and the LoanBroker is the provider.
    2. The JmsServiceComponent creates an instance of MessageExchange and sends the message to the LoanBroker component based on the configuration of the servicemix.xml file.
    3. The LoanBroker's onMessageExchange() method is invoked when the component receives the message sent by the JmsServiceComponent over the NMR.
    4. The processInputRequest() method is invoked. Here is what happens in this method:

      • An Aggregation object is created using the Social Security Number (SSN), amount, and duration as specified in the client request message.
      • The "in" message exchange as received by the LoanBroker is stored as a reference in the Aggregation object.
    5. An InOutExchange object is created with a destination provider component set as a CreditAgency component. Here is the code excerpt of the LoanBroker.java used to create the InOutExchange object:

       InOut inout = createInOutExchange(new QName(Constants.LOANBROKER_NS,
         Constants.CREDITAGENCY_SERVICE), null, null); 
      
    6. The message exchange object created is used to communicate with the CreditAgency component as described below.
  • LoanBroker to CreditAgency:

    1. In this message exchange sequence, the LoanBroker plays the role of a consumer and the CreditAgency plays the role of a producer.
    2. The LoanBroker completes the following processing before sending out the message:

      • The correlation ID is set as a property for the message exchange object.
      • The SSN is set as a property of the normalized message's "in" message.
    3. The "in" message for message exchange is now sent over the NMR using the send method. The send (inout) method is used to send the message over the NMR.
    4. The CreditAgency's transform() method is invoked when the component receives the message from the NMR.
    5. The CreditAgency sets the credit rating information as properties in the "out" message.
    6. Once the method returns, the "out" message is sent back to the consumer (LoanBroker).
    7. Once the "out" message is received by the LoanBroker over the NMR, processCreditAgencyResponse() is called.
    8. The LoanBroker extracts the credit information from the messageExchange and saves it in the Aggregation object.
    9. The status of this message exchange is set to "done" by calling the done (message) method.
    10. Once the message exchange between LoanBroker and CreditAgency is set to "done," the message between the LoanBroker component and LenderGateway begins as described below.
  • LoanBroker to LenderGateway:

    1. In this message exchange sequence, LoanBroker is the consumer and the LenderGateway is the provider.
    2. As stated earlier, processCreditAgencyResponse() is called to process the "out" message received from the CreditAgency.
    3. Here, another In-Out message exchange is created for interfacing with the LenderGateway.
    4. As stated in Step 2 of the LoanBroker to CreditAgency exchange, the credit rating information received from the credit agency along with other information, such as correlation ID, is added to the MessageExchange as properties.
    5. The destination of the message exchange is set to the LenderGateway, and the message is sent over the NMR using the send method.
    6. The LenderGateway receives the message over the NMR and the transform() method is invoked.
    7. The LenderGateway sets the list of short-listed banks as a part of the "out" message:
       (out.setProperty(Constants.PROPERTY_RECIPIENTS, recipients);)
      
    8. The "out" message is sent back to the consumer (LoanBroker) when the transform() method returns.
    9. The LoanBroker receives the "out" message when the onMessageExchange() method is invoked, which then invokes the processLenderGatewayResponse() method.
    10. The LoanBroker extracts the list of recipient banks from the "out" message.
    11. The LoanBroker then ends this message exchange sequence by calling the done() method on the message exchange, thus setting the status to "done."
    12. The LoanBroker now interfaces with the banks as described below.
  • LoanBroker to Bank:

    1. In this message exchange sequence, the role of the LoanBroker is that of a consumer and Bank is that of a provider.
    2. As stated in Step 9 above, the processLenderGatewayResponse() is invoked by LoanBroker to process the "out" message.
    3. Here, message exchanges are created for each bank that has been sent in the recipient array of the "out" message.
    4. Note that all bank names have been configured to refer to the same component (Bank.java) in servicemix.xml.
    5. All the message exchanges are populated with information, such as correlation ID, SSN, amount, and duration, on the same lines as stated in the above exchanges and sent to the Bank component over the NMR.
    6. The Bank component receives the "in" message from the NMR and sets the rate in the "out" message as a property.
    7. The LoanBroker receives the "out" message and invokes the processLoanQuote() method.
    8. Here, the rate information received on the "out" message is extracted.
    9. The message exchange is complete when the done() method is called.
  • LoanBroker to JmsServiceComponent:

    1. Upon receiving the loan quotes from all the short-listed banks, the LoanBroker decides the best quote for the client:

       ( for (Iterator iter = ag.quotes.iterator(); iter.hasNext();) { 
      q = (LoanQuote) iter.next(); 
      if (best == null || q.rate.doubleValue() <> best = q; 
      } 
      }) 
      
    2. The LoanBroker sets the bank quote as a property in the message created by the JmsServiceComponent.
    3. The LoanBroker sends the "out" message over the NMR by calling send() on MessageExchange.
    4. The JmsServiceComponent receives the "out" message and ends the message exchange by setting the status to "complete."
  • JmsServiceComponent to Client:

    1. Upon receiving the "out" message from the NMR, the JmsServiceComponent adds the result to the output demo.org.servicemix.output queue.

The Loan Broker example shows us how multiple components interact with each other in a distributed manner to provide services. The pluggable component nature of a JBI-compliant ESB has enabled us to implement business logic as a set of distributed components that communicate with each other using message exchanges.

1 2 Page 1
Page 1 of 2