Powered By Blogger

Feb 10, 2014

Implementing a REST API to accpet JSON requests and to connect to a SOAP back end via WSO2 Developer Studio

In this blog post I am going to describe a scenario where a user can order books online from an online bookstore. For implementing, as prerequisites you need to download and install WSO2 products (Developer Studio, ESB, AS) and also below mentioned third party tools and libraries.
  • Apache ActiveMQ
    • activemq-broker-5.9.0.jar
    • activemq-client-5.9.0.jar
    • geronimo-j2ee-management_1.1_spec-1.0.1.jar
    • geronimo-jms_1.1_spec-1.1.1.jar
Main Processes

1. Configure Servers
2. Modeling Ordering Service
3. Modeling Request Process using REST API
4. Deploy the artifacts
5. Test the scenario

Configure Servers

WS02 ESB : 
  • Leave the offset parameter as it is to ‘0’. ($CARBON_HOME/repository/conf/carbon.xml)

  • Enable ESB to talk over a message queue by copying  the ActiveMQ libraries to the $ESB_HOME/repository/components/lib.
  • Enable the JMS transport on the ESB by uncommenting the following two sections in the ESB's configuration file.($ESB_HOME/repository/conf/axis2/axis2.xml)
<transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener">/transportReceiver>

AND

<transportSender name="jms"   class="org.apache.axis2.transport.jms.JMSSender"/>

WSO2 AS :

  • Set offset parameter to ‘2’.
  • To enable the Application Server to talk over a message queue follow the same step did for ESB previously.
  • To enable the JMS transport on the App Server follow the same step did for ESB previously.

Modeling Ordering Service


  • Go to Developer Studio dashboard and select Axis2service project. Then select option Create new Axis2 Service with the project name 'UserAxis2ServiceProject'

  • Then create a service called BookRequest. 




  • Then go to the source view and copy and paste the below code

public class BookRequest {



private String userID;

private String requestID;

private String bookName;
private String request;

public void setUserRequest(String userID, String requestID,
String bookName) {
this.userID = userID;
this.requestID = requestID;
this.bookName = bookName;
}

public String getUserRequest() {
return request;

}

}


  • Then right click on the created Axis2 Project and New-> Axis2 Service Class and then create a new Axis2 Class name ‘CreateBookRequest’. Then go to the source view and copy and paste the below code
public class CreateBookRequest { public Request createrequest(String userID, String requestID, String bookName) { BookRequest request = new BookRequest(); request.setUserRequest(userID, requestID, bookName); return request; } }




  • JMS transport should enable since this service will communicate via JMS transport, add the below code to services.xml under /src.main.resources/META-INF.  
<transports>

<transport>jms</transport>

</transports>


Modeling Request Process using REST API

  • Go to Developer Studio dashboard and then click on ESB Config project and select option create new ESB Config project with the name UserESB.
  • Then right click on that and select New-> REST API and then create a new REST API called 'UserAPI'


  • Then go to the source view and copy and paste the below code.

<api xmlns="http://ws.apache.org/ns/synapse" name="UserAPI" context="/users">
   
<resource methods="POST" uri-template="/request/json" inSequence="MakeRequestSequence">
        <outSequence/>
        <faultSequence/>
    </resource>
   
</api>







  • Then right click on the ESB project and select New -> Endpoint and create an endpoint named 'OrderingServiceEP '.  The source view should be like

<endpoint xmlns="http://ws.apache.org/ns/synapse" name="OrderingServiceEP">
    <address uri="jms:/CreateBookRequest?transport.jms.DestinationType=queue&amp;transport.jms.ContentTypeProperty=Content-Type&amp;java.naming.provider.url=tcp://localhost:61616&amp;java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&amp;transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory"/>
</endpoint>




  • Then right click on the ESB project and select New -> Sequence and create a new sequence called MakeRequestSequence.

  • Go to the source view and copy paste the below code


<sequence xmlns="http://ws.apache.org/ns/synapse" name="MakeRequestSequence">

    <log level="full">
        <property name="text" value="** Customer Book Requesting Process **"/>
    </log>
    <property name="messageType" value="application/json" scope="axis2" type="STRING"/>
    <header name="To" scope="default" action="remove"/>
    <property name="UserID" expression="//jsonObject/request/title/userID/text()" scope="default" type="STRING"/>
    <property name="RequestID" expression="//jsonObject/request/title/requestID/text()" scope="default" type="STRING"/>
    <property name="BookName" expression="//jsonObject/request/title/bookName/text()" scope="default" type="STRING"/>
    
    <iterate xmlns:m="http://schemas.xmlsoap.org/soap/envelope/" continueParent="true" id="iter1" expression="//jsonObject/request/title">
        <target>
            <sequence>
                <property name="UserID" expression="//userID/text()" scope="default" type="STRING"/>
                <property name="RequestID" expression="//requestID/text()" scope="default" type="STRING"/>
                <property name="BookName" expression="//bookName/text()" scope="default" type="STRING"/>
            </sequence>
        </target>
    </iterate>

    <log level="custom" separator=",">
        <property name="MessageFlow" value="======================= Before Sending User Request to OrderingService : ======================="/>
    </log>
    <payloadFactory media-type="xml" description="">
        <format>
            <p:createrequest xmlns:p="http://customer.axis.org">
                <p:userID>$1</p:userID>
                <p:requestID>$2</p:requestID>
                <p:bookName>$3</p:bookName>
            </p:createrequest>
        </format>
        <args>
            <arg evaluator="xml" expression="//jsonObject/request/title/userID/text()"/>
            <arg evaluator="xml" expression="//jsonObject/request/title/requestID/text()"/>
            <arg evaluator="xml" expression="//jsonObject/request/title/bookName/text()"/>
        </args>
    </payloadFactory>
    <log level="custom">
        <property name="text" value="** User Request to be sent ........ **"/>
        <property name="UserID" expression="$ctx:UserID"/>
        <property name="RequestID" expression="$ctx:RequestID"/>
        <property name="BookName" expression="$ctx:BookName"/>
    </log>
    <log level="custom" separator=",">
        <property name="MessageFlow" value="======================= Sending Request To OrderingService======================="/>
    </log>
    <log level="full" separator=","/>
    <send>
        <endpoint key="OrderingServiceEP"/>
    </send>
</sequence>


  • If I explain the content of this sequence, first Property Mediators have been used to grab the request which comes as JSON 
eg: <property name="UserID" expression="//jsonObject/request/title/userID/text()" scope="default" type="STRING"/>

  • Then Iterator Mediator has been used to iterate throughout the message and extract relevant information 
eg:  <iterate xmlns:m="http://schemas.xmlsoap.org/soap/envelope/" continueParent="true" id="iter1" expression="//jsonObject/request/title">

        <target>
            <sequence>
                <property name="UserID" expression="//userID/text()" scope="default" type="STRING"/>
                <property name="RequestID" expression="//requestID/text()" scope="default" type="STRING"/>
                <property name="BookName" expression="//bookName/text()" scope="default" type="STRING"/>
            </sequence>
        </target>
    </iterate>

  • Then Payload Factory Mediator has been used in such away its payload matches with the format which back end service accepts requests. It's 'args' used to assign actual values got from the user request which can be assigned to variables in the format
eg: <payloadFactory media-type="xml" description="">
        <format>
            <p:createrequest xmlns:p="http://customer.axis.org">
                <p:userID>$1</p:userID>
                <p:requestID>$2</p:requestID>
                <p:bookName>$3</p:bookName>
            </p:createrequest>
        </format>
        <args>
            <arg evaluator="xml" expression="//jsonObject/request/title/userID/text()"/>
            <arg evaluator="xml" expression="//jsonObject/request/title/requestID/text()"/>
            <arg evaluator="xml" expression="//jsonObject/request/title/bookName/text()"/>
        </args>
    </payloadFactory>

  • The design of the sequence is as follows

Deploy the artifacts
  • Go to Developer Studio dashboard and select Composite Application Project and the give the name as 'UserCApp' and dependencies as stated below
    • UserAPI
    • UserAxis2ServiceProject
    • MakeRequestSequence
    • OrderingServiceEP

  • Then Right click on the UserCApp and select 'Export Composite Application Project' then give a name and destination. Now you have the .car file
  • Then start the WSO2 AS by navigate to $CARBON_HOME/bin and type the command wso2server.sh (Linux) or wso2server.bat (Windows)
  • Then deploy the created .car file on the server.
  • Then start WSO2 ESB and deploy the .car file
Test the scenario

  • Send the below REST CLIENT JSON Request


curl -i -H "Content-Type: application/json" -X POST -d '{"request" : {"title":{"userID":"2", "requestID":"200", "bookName": "HarryPotter"}}}' http://10.100.5.22:8280/userss/request/json

  • See the logs in ESB console

No comments:

Post a Comment