2015/10/01
1 Oct, 2015

[Article] How to Enable WSO2 API Manager to Work as a JMS Producer

  • Nadeesha Gamage
  • Lead Solutions Engineer - WSO2

Applies To

WSO2 API Manager 1.9.0
WSO2 Enterprise Service Bus 4.8.1
Apache ActiveMQ 5.8.0


Table of contents

  1. Introduction
  2. When should you use API manager as a JMS producer?
  3. Which pattern to use?
  4. Summary


Introduction

The scenario depicted here is for a simple JMS scenario which works as a dead letter channel. For scenarios that require extensive JMS integration it is recommended to use WSO2 Enterprise Integrator instead of the WSO2 API Manager.

Even though an API manager is primarily focussed on exposing RESTful services to API consumers both within and outside the organization, there may be edge cases where an organization requires the capability to advertise, expose, manage, secure and monitor an endpoint that needs to produce a message to a JMS queue. APIs are primarily seen as sources to acquire information from a backend service, but in this case, the API acts as a data feeder to a JMS message queue. In this article, we look at two possible patterns in exposing a message queue via WSO2 API Manager. Both patterns have their own pros and cons and a suitable pattern should be chosen based on the requirements of your organization.


When should you use API manager as a JMS producer?

An API manager is primarily used as a way of exposing internal business capabilities to external consumers in a managed and secured way. Some cases may arise where the organization wants to collect information from different applications/users through APIs. These can be business information or even information that may relate to the IoT space. For example, if you take a business scenario, you may have a mobile application that wants to push information pertaining to the location of a user to a backend service. The mobile application would use a RESTful API to post information to the backend. However, the backend service may not have the required capacity to process messages at the same speed they are pushed by the applications. In this case, using a message queue would be an ideal solution whereby the message queue would act as a buffer to which the API Manager can push all information and the backend service can dequeue information out of the queue at its own pace. Given below are two possible patterns that can allow the API manager to work as a JMS producer.


Pattern 1: WSO2 API Manager as a JMS Producer

Figure 1

In this pattern, WSO2 API Manager will directly connect to a JMS message queue. WSO2 API Manager would expose a RESTful API that is secured via OAuth 2.0, which can be consumed by any application that invokes the API with a valid OAuth 2.0 token. It is also possible to integrate WSO2 API Manager with WSO2 Data Analytics Server to publish statistics on API invocations that allow the exposed JMS endpoint to be monitored. This exposed API can be advertised in the API Store, and its lifecycle can be managed and versioned through the API Publisher UI. Let’s look at how you can configure the API manager to work as a JMS consumer. For this particular scenario, we have used ActiveMQ as a JMS message queue.

  1. Enable JMS sender in the API manager – Uncomment the following text in <AM_HOME>\repository\conf\axis2\axis2.xml
    <transportSender name="jms" class="org.apache.axis2.transport.jms.JMSSender"/>


    You don’t have to enable JMS transport receiver as we are only going to send messages to a JMS queue.
  2. Copy the required client library files - You need to copy the required client library files to <AM_HOME>\repository\components\lib folder. For ActiveMQ these client libraries can be found in <ActiveMQ_HOME>\lib folder. If you are using
    • ActiveMQ 5.8.0 and above
      activemq-broker-5.8.0.jar
      activemq-client-5.8.0.jar
      geronimo-jms_1.1_spec-1.1.1.jar
      geronimo-j2ee-management_1.1_spec-1.0.1.jar
      hawtbuf-1.9.jar
    • Earlier version of ActiveMQ
      activemq-core-5.5.1.jar
      geronimo-j2ee-management_1.0_spec-1.0.jar
      geronimo-jms_1.1_spec-1.1.1.jar
  3. Once the above steps are done start WSO2 API Manager and Apache ActiveMQ.
  4. Create a mediation extension for WSO2 API Manager - We need to create a mediation extension in the API manager. This mediation extension would set the API to asynchronous behavior where the API manager would not wait for a response from the backend for this particular API. Since the API manager works as a JMS producer, it will simply push the message to the message queue and terminate the connection without needing to wait for a response. In order for the API manager to work in asynchronous behavior, two message properties need to be set before sending the message to the backend message queue. These properties would be inside a message sequence that would be attached to the API as a mediation extension. Let’s create the following sequence and add it to the registry of WSO2 API Manager.
  5. <sequence xmlns="http://ws.apache.org/ns/synapse"  name="outOnly">  
    <property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
    <property name="OUT_ONLY" value="true"/>
    </sequence>
    

    Refer to this blog1 for more information on how to add a mediation extension to an API exposed via WSO2 API Manager.

  6. Create an API with the JMS backend endpoint – Let’s now create an API within the API manager. You can follow the regular process when creating the API. As shown below, make sure you enable ‘POST’ HTTP verb when defining the resources.

    Figure 2

Once this has been done, let’s add the JMS URL as the production endpoint. Select the endpoint type as ‘Address Endpoint’ from the endpoint type drop-down menu. The production URL would be the actual JMS endpoint. The JMS URL for an ActiveMQ message queue should something like this:

jms:/DataFeed?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616&transport.jms.DestinationType=queue

In this case, the queue name is ‘DataFeed’, and Queue URL is localhost with port number 61616. Once this is entered let’s move to the next stage in the API creation process. Here, let’s add the mediation extension we created in the previous step. Click on the ‘Message Mediation Policies’ checkbox and select the ‘outOnly’ sequence from the ‘In Flow’ sequence list as shown below.

Figure 3

Once this is done, select an applicable throttling tier and create the API. After creating, you could publish this API to the API Store. This API can now be subscribed from the API Store. Use a REST client and send a post request with a message payload to this particular API. You will need to include the OAuth token in the message as an authorization header to invoke this particular API. When this API is invoked you would see that the API manager accepts the request and no-response is sent back to the API consumer. At the same time, the API manager would push the message to the message queue. The message can now be dequeued and consumed by another component within the organization.


Pattern 2: WSO2 API Manager as a JMS Producer Using WSO2 ESB

Figure 4

This pattern is an extension of what we discussed in Pattern 1. In this case, the ESB would work as a JMS producer and expose a RESTful API to WSO2 API Manager. The API manager would secure this API and provide other API management features, such as the ability to monitor, advertise, and manage the lifecycle of the API. The notable difference here is that WSO2 API Manager would act purely as an API façade layer while WSO2 ESB would do the required protocol mediation from HTTP/REST to JMS. This pattern allows a clear separation between the API management layer and the message mediation layer and is encouraged to be used if you are interested in separation of concerns within your deployment. Given below are the steps required to configure this scenario.

  1. Enable JMS sender in the Axis 2 configuration of the ESB. This can be found in the <ESB_HOME>\repository\conf\axis2\axis2.xml file.
  2. Copy the client libraries of ActiveMQ to the <ESB_HOME>\repository\components\lib folder (you will find more details on this in the above pattern).
  3. Let’s start the API manager, ESB, and ActiveMQ. If both API manager and ESB are going to run on the same server, you will need to set a port offset to one of the products to avoid a port conflict. Port offset can be set from the <Carbon_home>\repository\conf\carbon.xml file.
  4. Same as in the above pattern, we will need to create a mediation extension for the API manager. This mediation extension would set the API to asynchronous behavior where the API manager will send the message and close the connection without waiting for a response. Refer to Step 3 of the above pattern on how to create the required ‘outOnly’ mediation extension for the API manager.
  5. Let’s create a REST API in the ESB. When creating a REST API make sure you create it as a POST resource method. You can create a RESTful API from WSO2 Developer Studio or by using either the design view or the source view of the ESB. ESB configuration is provided below. Note that the ESB will also have two message properties to inform the ESB that this request will be an outOnly request.
    <api name="MQService" context="/MQService">
          <resource methods="POST">
             <inSequence>
                <property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
                <property name="OUT_ONLY" value="true"/>
                <send>
               	<endpoint>
                  	<address uri="jms:/SimpleStockQuoteService?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616&transport.jms.DestinationType=queue"
                               format="soap11"/>
               	</endpoint>
                </send>
             </inSequence>
          </resource>
    </api>
    
  6. Expose the API created in the ESB via WSO2 API Manager. Create an API in the API manager, ensure that you enable POST HTTP verb and add the ESB API URL as the backend endpoint in the API manager. You will also need to attach the mediation sequence that you created in Step 4 to your API to ensure that the API manager closes the connection after sending the message to the ESB.
  7. Once the above has been completed you can invoke this API from the API manager, and the message will be routed to the ESB and then passed to the JMS message queue.


Which pattern should you use?

Both patterns have its pros and cons, hence the answer depends on what you need to achieve and how you want to achieve it. Nevertheless, Pattern 2, which uses an ESB instance to do the protocol negotiation, would be a more architecturally cleaner approach when compared to pattern 1. However, Pattern 1 is a leaner approach and would be ideal for a scenario where you want to do this integration solely using an API manager.


Summary

This article looked at how WSO2 API Manager can work as a JMS producer for applications to push data to a backend message queue. We discussed two possible patterns that can be used to do this and the configuration required to do this integration. There’s no clear winner in terms of which pattern is better and would purely depend on your enterprise requirements. Broadly, it would depend on whether you’re looking for a more architecturally refined approach or a leaner one that’s ideal when using only WSO2 API Manager to carry out this integration.


References

[1] https://nadeesha678.wordpress.com/2015/09/09/api-manager-for-message-mediation/

[2] https://docs.wso2.com/display/ESB481/Configure+with+ActiveMQ

 

About Author

  • Nadeesha Gamage
  • Lead Solutions Engineer
  • WSO2