Saturday, August 24, 2013

Extracting HTTP level information in Axis2

From the Aixs2MessageContext, we can get the HttpServletRequest object, which contains HTTP request header information,session details, cookies etc..

Sample

public class MessageStoreHandler extends AbstractHandler {

@Override
public InvocationResponse invoke(MessageContext msgcontext) throws AxisFault {
             extractHTTPInfo(msgcontext);
             return InvocationResponse.CONTINUE;
       }

       private void  extractHTTPInfo(MessageContext msgContext) {

HttpServletRequest obj = (HttpServletRequest)msgContext .
                                          getProperty("transport.http.servletRequest");
if (obj != null) {
System.out.println("Method :"+ obj.getMethod());
System.out.println("Content-type :" +obj.getContentType());
System.out.println("Content-length :"+obj.getContentLength());
System.out.println("Remote addtress"+obj.getSession().getLastAccessedTime());
}
}
}

Friday, August 9, 2013

Defining dynamic endpoint in wso2esb

In synapse(/wso2esb), when we define endpoints, we have to provide endpoint URL, which is  most of the time  hard coded. Those endpoint urls can not be changed dynamically at runtime.
But if user likes to send requests to an endpoint which address has to be constructed from incoming request/any other way, we can use Header mediator with Property mediator to achieve this.
For instance, if the End service name has to be picked from the request, we can use property mediator to pick and store the service name. Later use the Header mediator to set "To" header using the property mediator and forward the request to default endpoint.

Eg:
The sample request is as follows( it contains the service name , which is used to find the endpoint address)

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://services.samples" xmlns:xsd="http://services.samples/xsd">
   <soapenv:Header/>
   <soapenv:Body>
      <ser:getQuote>    
         <ser:request>    
            <xsd:symbol>MSFT </xsd:symbol>  
        <xsd:service>SimpleStockQuoteService</xsd:service>
         </ser:request>
     </ser:getQuote>
   </soapenv:Body>
</soapenv:Envelope>

If we send above request to the "testProxy", which will forward the request to http://localhost:9000/services/SimpleStockQuoteService endpoint, which can be constructed as mentioned above.

testProxy conf:

  <proxy name="testProxy"    transports="https http"
          startOnLoad="true"   trace="disable">
      <description/>
      <target>
         <endpoint>
            <default/>
         </endpoint>
         <inSequence>
            <property name="server"  value="http://localhost:9000/services/"
                      scope="default"  type="STRING"/>
            <property xmlns:m1="http://services.samples/xsd"
                      xmlns:m0="http://services.samples"
                      name="service"   expression="//m0:getQuote/m0:request/m1:service"
                      scope="default"   type="STRING"/>
            <header xmlns:m1="http://services.samples/xsd"
                    xmlns:m0="http://services.samples"   name="To"
                    expression="fn:concat(get-property('server'),get-property('service'))"/>
         </inSequence>
         <outSequence>
            <send/>
         </outSequence>
      </target>
   </proxy>


You can use xpath functions in the Header/Property mediator expressions.

Sunday, August 4, 2013

Writing a simple Axis2 handler

If we want to listen all the incoming/outgoing messages coming to/from the service, we can write an axis2 handler which can be placed in a phase, which is executed in order as defined in the axis2 configuration. The phase can contain more than one handler.
Message flow is categorized  as;

  • InFlow
  • OutFlow
  • InFaultFlow
  • OutFaultFlow
As name implies, the message flows indicate the request,response and their fault execution paths. In each flow there are phases defined and we can keep our handler in the right flow and right phase.

Sample code:

package org.test.sample;

import org.apache.axis2.handlers.AbstractHandler;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.context.MessageContext;


public class MessageHandler extends AbstractHandler {
private static final Log log = LogFactory.getLog(MessageHandler.class);

@Override
public InvocationResponse invoke(MessageContext msgcontext) throws AxisFault {
if (log.isDebugEnabled()) {
log.debug("Message Store handler is executing");
}
AxisService axService = msgcontext.getAxisService();
//TODO
return InvocationResponse.CONTINUE;
}


The message execution can be continued, aborted or suspended.

Once we created the jar out of this, we need to keep the jar in the classpath(ie:lib folder) and has to register the handler in the axis2 configuration.
We can register the handler programmatically as a module or  we can edit the axis2.xml file based on the requirement.

Editing axis2.xml

Add the following configuration in the suitable flow/phase.
< phaseOrder type="InFlow">
< phase name="Transport">
< handler name="MessageHandler" class="org.test.sample.MessageHandler">
......
< /phaseOrder>

Programmatically adding the module;

axis2Service.engageModule(axisCfg.getModule(testModule));