Saturday, February 18, 2017

WebSocket Communication with WSO2 ESB 5.0.0

Why WebSocket Introduced?


The web has introduced with client-server communication option, which was built with the concept of client always request for data from the server, whenever it needs it. This have a performance issue that, whenever there is a need for data, the client page need to be refreshed or a new submit request need to be made.

To overcome this, there was a need for bi-directional communication, as a first step the AJAX came into picture. Through AJAX, JavaScript communicates directly with the server, through the JavaScript XMLHttpRequest object. This helps to retrieve the data without reloading the page or send a new page submission.

The problem encountered during the above is the HTTP headers and Cookies. Whenever we make an HTTP request a bunch of headers and cookie data are transferred to the server. This can add up to a reasonably large amount of data that needs to be transferred, which in turn increases latency.

This introduced the need for WebSocket. WebSockets provide a persistent connection between a client and server that both parties can use to start sending data at any time.



Configuring WSO2 ESB 5.0.0 to support WebSocket Communication


Below diagram illustrates, the basic flow of WebSocket communication through WSO2 ESB.


Setting up the WebSocket client and Server


Here, I have used the code got from
http://www.lookatsrc.com/source/io/netty/example/http/websocketx/client/WebSocketClient.java?a=io.netty:netty-all

You can find the project used in this sample at
https://drive.google.com/file/d/0B-VAIXmh-0yeTURNRE5yQmJTdjQ/view?usp=sharing

By running the WebSocketClient.java and WebSocketServer.java can start the client and the server for the communication.

Configuring the WSO2 ESB


Create the below sequences to use in this implementation.


Created Sequences as below:

<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="InDispatchSeq">
   <property name="OUT_ONLY" value="true"/>
   <log level="custom">
<property name="STATUS" value="----------------InDispatchSeq Invoked------------------"/>
</log>
   <send>
         <endpoint>
             <address uri="ws://localhost:8080/websocket"/>
         </endpoint>
     </send>
</sequence>



<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="InDispatchFaultSequence">
   <log level="custom">
      <property name="STATUS"
                value="---------------------InDispatchFaultSequence Invoked---------------------"/>
   </log>
</sequence>


<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="OutDispatchSeq">
   <log level="custom">
      <property name="STATUS"
                value="-----------------OutDispatchSeq Invoked----------------"/>
   </log>
   <respond/>
</sequence>



<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="OutDispatchFaultSequence">
   <log level="custom">
      <property name="STATUS"
                value="---------------------OutDispatchFaultSequence Invoked---------------------"/>
   </log>
</sequence>


Create an Inbound Endpoint as below:

<?xml version="1.0" encoding="UTF-8"?>
<inboundEndpoint xmlns="http://ws.apache.org/ns/synapse"
                 name="WebSocketInboundEndpoint"
                 sequence="InDispatchSeq"
                 onError="InDispatchFaultSequence"
                 protocol="ws"
                 suspend="false">
   <parameters>
      <parameter name="inbound.ws.port">9091</parameter>
      <parameter name="ws.client.side.broadcast.level">0</parameter>
      <parameter name="ws.outflow.dispatch.sequence">OutDispatchSeq</parameter>
      <parameter name="ws.outflow.dispatch.fault.sequence">OutDispatchFaultSequence</parameter>
   </parameters>
</inboundEndpoint>

Add the below to the axis2.xml:

<transportSender name="ws" class="org.wso2.carbon.websocket.transport.WebsocketTransportSender">
       <parameter name="ws.outflow.dispatch.sequence" locked="false">OutDispatchSeq</parameter>
       <parameter name="ws.outflow.dispatch.fault.sequence" locked="false">OutDispatchFaultSequence</parameter>       
</transportSender>


Changes Need to be done in WebSocket Java Client and Server


Point the WebSocket Client URL to the Inbound Endpoint's URL.

Check whether you referring the correct port of WebSocket Server.



Now we are ready to test the implementation.

Up the WebSocketClient.java and WebSocketServer.java and in WebSocketClient.java, type some text and enter.

You can observe the below results.



[2017-02-18 18:28:11,995]  INFO - CarbonAuthenticationUtil 'admin@carbon.super [-1234]' logged in at [2017-02-18 18:28:11,975+0530]
[2017-02-18 18:46:00,008]  INFO - LogMediator STATUS = ----------------InDispatchSeq Invoked------------------
[2017-02-18 18:46:00,025]  INFO - LogMediator STATUS = -----------------OutDispatchSeq Invoked----------------
[2017-02-18 18:46:15,044]  INFO - LogMediator STATUS = ----------------InDispatchSeq Invoked------------------
[2017-02-18 18:46:15,048]  INFO - LogMediator STATUS = -----------------OutDispatchSeq Invoked----------------


Here you may observed that even if we specify a log level="full", we can't log the message. To check this modified the sequence as below:

<?xml version="1.0" encoding="UTF-8"?>
<sequence name="InDispatchSeq" xmlns="http://ws.apache.org/ns/synapse">
    <property name="OUT_ONLY" value="true"/>
    <log level="custom">
        <property name="STATUS" value="----------------InDispatchSeq Invoked------------------"/>
    </log>
    <log level="full"/>
    <send>
        <endpoint>
            <address uri="ws://localhost:8080/websocket"/>
        </endpoint>
    </send>
</sequence>

The log will appear as below:

[2017-02-18 18:52:27,406]  INFO - LogMediator STATUS = ----------------InDispatchSeq Invoked------------------
[2017-02-18 18:52:27,437]  INFO - LogMediator To: , MessageID: urn:uuid:66025a65-065a-49e3-b415-1c81f0f4d791, Direction: request, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body/></soapenv:Envelope>
[2017-02-18 18:52:27,440]  INFO - LogMediator STATUS = -----------------OutDispatchSeq Invoked----------------


Will explain how to log the messages and do the modifications in my next blog.

References

[1] https://docs.wso2.com/display/ESB500/WebSocket+Transport
[2] https://docs.wso2.com/display/ESB500/Sending+a+Message+from+a+WebSocket+Client+to+a+WebSocket+Endpoint


3 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Hi Ajanthan,
    I modified this as below.
    Client connect using wss - wss://xx.xx.xx.xxx:9093/websocket
    And Inbound Endpoint as this example
    https://docs.wso2.com/display/ESB500/Secure+WebSocket+Inbound+Protocol
    So it gives "WebSocket Client disconnected!" Error.
    without wss this working fine.
    Is there any known reason or additional changes for that.

    Thank you.

    ReplyDelete
  3. where is the next post to log the message

    ReplyDelete