Showing posts with label WSO2ESB. Show all posts
Showing posts with label WSO2ESB. Show all posts

Friday, June 12, 2015

Register Axis2 MessageBuilder Programmatically

For each  Content-type, we define message builders and formatters in the axis2 configuration(axis2.xml). Those Builders and Formatters are global configuration. In some cases, we need to handle  certain messages belong to a certain content-type  in different manner.

For example, We configure text/xml content-type messages to be handled by a message builder implementaion in axis2 configuration. But, if same content-ype messages to be handled in different manner in a different message flow, we can register MessageBuilder/Formatter programmatically in that particular message flow. This will not affect the normal message building process for the same content -type messages in other flows.

Eg:
Registering PlainTextBuilder implementation to handle SOAP messages.

Builder messagebuilder = null;
Class c = Class.forName("org.apache.axis2.format.PlainTextBuilder");

Object obj = c.newInstance();
if (obj instanceof Builder) {
messagebuilder = (Builder) obj;
}
org.apache.axis2.context.MessageContext axis2MsgContext;
axis2MsgContext.getConfigurationContext().getAxisConfiguration().addMessageBuilder("text/xml", messagebuilder);

Monday, December 22, 2014

axiom.soap.SOAPProcessingException: Transport level information does not match with SOAP Message namespace URI

This is a common exception [1]we see when invoke services hosted in axis2 based servers.
It occurs due to the namespace mismatch in the request. Check the service'e version and the request's version.
eg: SOAP 1.2 message with content type text/xml, we get this error. Correct the namespace in the request.

[1]

ERROR - RelayUtils Error while building Passthrough stream
org.apache.axiom.soap.SOAPProcessingException: Transport level information does not match with SOAP Message namespace URI
at org.apache.axis2.builder.BuilderUtil.validateSOAPVersion(BuilderUtil.java:745)
at org.apache.axis2.builder.SOAPBuilder.processDocument(SOAPBuilder.java:58)
at org.apache.synapse.transport.passthru.util.DeferredMessageBuilder.getDocument(DeferredMessageBuilder.java:118)
at org.apache.synapse.transport.passthru.util.RelayUtils.builldMessage(RelayUtils.java:107)
at org.apache.synapse.transport.passthru.util.RelayUtils.buildMessage(RelayUtils.java:82)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:68)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:47)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:131)
at org.apache.synapse.core.axis2.ProxyServiceMessageReceiver.receive(ProxyServiceMessageReceiver.java:166)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
at org.apache.synapse.transport.passthru.ServerWorker.processEntityEnclosingRequest(ServerWorker.java:411)
at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:183)
at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:695)
[2014-12-22 00:53:36,500] ERROR - SequenceMediator Error while building message
org.apache.axis2.AxisFault: Error while building Passthrough stream
at org.apache.synapse.transport.passthru.util.RelayUtils.handleException(RelayUtils.java:236)
at org.apache.synapse.transport.passthru.util.RelayUtils.builldMessage(RelayUtils.java:111)
at org.apache.synapse.transport.passthru.util.RelayUtils.buildMessage(RelayUtils.java:82)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:68)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:47)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:131)
at org.apache.synapse.core.axis2.ProxyServiceMessageReceiver.receive(ProxyServiceMessageReceiver.java:166)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
at org.apache.synapse.transport.passthru.ServerWorker.processEntityEnclosingRequest(ServerWorker.java:411)
at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:183)
at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:695)
Caused by: org.apache.axiom.soap.SOAPProcessingException: Transport level information does not match with SOAP Message namespace URI
at org.apache.axis2.builder.BuilderUtil.validateSOAPVersion(BuilderUtil.java:745)
at org.apache.axis2.builder.SOAPBuilder.processDocument(SOAPBuilder.java:58)
at org.apache.synapse.transport.passthru.util.DeferredMessageBuilder.getDocument(DeferredMessageBuilder.java:118)
at org.apache.synapse.transport.passthru.util.RelayUtils.builldMessage(RelayUtils.java:107)

Saturday, November 29, 2014

Synapse Handler

Synapse handler is similar to axis2 handler , that can be used in RESTAPIs to handle incoming request and the responses.

Sample handler ;


package test;

import org.apache.synapse.MessageContext;
import org.apache.synapse.rest.AbstractHandler;

public class TestSynapseHandler extends AbstractHandler {
@Override
public boolean handleRequest(MessageContext messageContext) {
String idKey = "idKey";
String idValue = "abc";
messageContext.setProperty(idKey, idValue);
return true;
}

@Override
public boolean handleResponse(MessageContext messageContext) {
// TODO Response handling
return true;
}

}

Handler has to be registered in the RESTAPI configuration.

Sample configuration;

<api xmlns="http://ws.apache.org/ns/synapse" name="calAPI" context="/cal">
   <resource methods="GET">
      <nSequence>
         <send>
            <endpoint>
               <address uri="http://localhost:9763/services/calservice"/>
            </endpoint>
         </send>
      </inSequence>
      <outSequence>
         <send>
            <endpoint>
               <default/>
            </endpoint>
         </send>
      </outSequence>
   </resource>
<handlers>
        < handler class="test.TestSynapseHandler"/>
   </handlers>
</api>












Tuesday, October 21, 2014

Server did not recognize the value of HTTP Header SOAPAction



We face this issue[1] if we send different version of soap message to a soap service endpoint. Check the service endpoint is soap 1.1 or 1.2 and send the right message.


[1]System.Web.Services.Protocols.SoapException: Server did not recognize the value of HTTP Header SOAPAction: urn:process.
at System.Web.Services.Protocols.Soap11ServerProtocolHelper.RouteRequest()
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()

Monday, June 16, 2014

Environment Management in WSO2 ESB using WSO2GREG


In ESB, when environment changes( dev-->qa-->prod) , that affects the proxy service configuration. Proxy service configuration includes sequences,endpoints,local entries etc. For different environments, endpoint configuration might change.(ie: the service url which is given as address uri)

Sample endpoint configuration 

<endpoint xmlns="http://ws.apache.org/ns/synapse" name="TestEndpoint">
   <address uri="http://abc.com">
      <suspendOnFailure>
         <progressionFactor>1.0</progressionFactor>
      </suspendOnFailure>
      <markForSuspension>
         <retriesBeforeSuspension>0</retriesBeforeSuspension>
         <retryDelay>0</retryDelay>
      </markForSuspension>
   </address>
</endpoint>

When we develop  ESB/Synapse artifacts, we might not prefer to modify the configuration for different environments. Users just want to deploy the same artifact in all different environments. To make the deployment easy in all environments, we need a running WSO2 Governance Registry instance and we need to mount the config/governance registries of WSO2ESB to different target paths of WSO2 G-Reg. The paths will indicate the different environments.

Eg:
<mount path="/_system/config" overwrite="true">
    <instanceId>config</instanceId>
    <targetPath>/_system/config/environment/production</targetPath>
</mount>

We need to upload the endpoint configuration for different environments( with the correct endpoint url) directly to the registry in the relevant environment paths.

The following sample configurations are related to  one production ESB, one qa ESB and a common G-Reg instance. All three instances will ponit same external DB. eg: mysql


Configurations 

1.  WSO2 G-Reg


master-datasource.xml

Create a new data source to point an external database. Eg: mysql.

 <datasource>
            <name>WSO2_REG_DB</name>
            <description>The datasource used for ESB mount registries</description>
            <jndiConfig>
                <name>jdbc/esbserver_config</name>
            </jndiConfig>
            <definition type="RDBMS">
                <configuration>
                    <url>jdbc:mysql://localhost:3306/esb</url>
                    <username>root</username>
                    <password>root</password>
                    <driverClassName>com.mysql.jdbc.Driver</driverClassName>
                    <maxActive>50</maxActive>
                    <maxWait>60000</maxWait>
                    <testOnBorrow>true</testOnBorrow>
                    <validationQuery>SELECT 1</validationQuery>
                    <validationInterval>30000</validationInterval>
                </configuration>
            </definition>
        </datasource>

registry.xml

Use the created above datasource in the registry.xml

<!-- This defines the default database and its configuration of the registry -->

    <dbConfig name="wso2registry">
        <dataSource>jdbc/esbserver_config</dataSource>
    </dbConfig>

Copy the mysql jdbc driver in repository/components/lib folder and start the server. Make sure to create tables in the mysql database. You can find the relevant sql scripts in the CARBON_HOME\dbscripts folder.

We need to set different port offsets to all carbon servers in carbon.xml. For G-Reg, let’s keep the default value (ie: ‘0’)

2 WSO2ESB-QA

master-datasource.xml
Create a new data source to point the mysql database which is already created.


 <datasource>
            <name>WSO2_REG_DB</name>
            <description>The datasource used for ESB mount registries</description>
            <jndiConfig>
                <name>jdbc/esbserver_config</name>
            </jndiConfig>
            <definition type="RDBMS">
                <configuration>
                    <url>jdbc:mysql://localhost:3306/esb</url>
                    <username>root</username>
                    <password>root</password>
                    <driverClassName>com.mysql.jdbc.Driver</driverClassName>
                    <maxActive>50</maxActive>
                    <maxWait>60000</maxWait>
                    <testOnBorrow>true</testOnBorrow>
                    <validationQuery>SELECT 1</validationQuery>
                    <validationInterval>30000</validationInterval>
                </configuration>
            </definition>
        </datasource>

registry.xml

We need to mount the config registry to different target path to make sure QA ESB server talks to different config registry. Governance registry space of all nodes will be mounted to same location, since governance space is common for all nodes.

  <dbConfig name="config">
       <dataSource>jdbc/esbserver_config</dataSource>
    </dbConfig>
      <remoteInstance url="https://localhost:9443/registry">
        <id>config</id>
        <dbConfig>config</dbConfig>
        <readOnly>false</readOnly>
        <registryRoot>/</registryRoot>
        <enableCache>true</enableCache>
    </remoteInstance>
     <mount path="/_system/config" overwrite="true">
        <instanceId>config</instanceId>
        <targetPath>/_system/config/env/qa</targetPath>
    </mount>

     <dbConfig name="governance">
       <dataSource>jdbc/esbserver_config</dataSource>
    </dbConfig>
      <remoteInstance url="https://localhost:9443/registry">
        <id>governance</id>
        <dbConfig>governance</dbConfig>
        <readOnly>false</readOnly>
        <registryRoot>/</registryRoot>
        <enableCache>true</enableCache>
    </remoteInstance>
     <mount path="/_system/governance" overwrite="true">
        <instanceId>governance</instanceId>
        <targetPath>/_system/governance</targetPath>
    </mount>


Copy the mysql jdbc driver in repository/components/lib folder. Set different port offset in carbon.xml. For ESB_QA server, let’s keep it as ‘1’. Start the server.
Go to https://localhost:9444/carbon/ URL and check the registry browser, you will see the registries are mounted.

3 WSO2ESB-PROD

master-datasource.xml
Create a new data source to point the mysql database which is already created.

 <datasource>
            <name>WSO2_REG_DB</name>
            <description>The datasource used for ESB mount registries</description>
            <jndiConfig>
                <name>jdbc/esbserver_config</name>
            </jndiConfig>
            <definition type="RDBMS">
                <configuration>
                    <url>jdbc:mysql://localhost:3306/esb</url>
                    <username>root</username>
                    <password>root</password>
                    <driverClassName>com.mysql.jdbc.Driver</driverClassName>
                    <maxActive>50</maxActive>
                    <maxWait>60000</maxWait>
                    <testOnBorrow>true</testOnBorrow>
                    <validationQuery>SELECT 1</validationQuery>
                    <validationInterval>30000</validationInterval>
                </configuration>
            </definition>
        </datasource>


registry.xml
We need to mount the config registry to different target path to make sure PROD_
ESB server talks to different config registry. Governance registry of all nodes will be mounted to same location, since governance space is common for all nodes.


<dbConfig name="config">
       <dataSource>jdbc/esbserver_config</dataSource>
    </dbConfig>
      <remoteInstance url="https://localhost:9443/registry">
        <id>config</id>
        <dbConfig>config</dbConfig>
        <readOnly>false</readOnly>
        <registryRoot>/</registryRoot>
        <enableCache>true</enableCache>
    </remoteInstance>
     <mount path="/_system/config" overwrite="true">
        <instanceId>config</instanceId>
        <targetPath>/_system/config/env/prod</targetPath>
    </mount>

     <dbConfig name="governance">
       <dataSource>jdbc/esbserver_config</dataSource>
    </dbConfig>
      <remoteInstance url="https://localhost:9443/registry">
        <id>governance</id>
        <dbConfig>governance</dbConfig>
        <readOnly>false</readOnly>
        <registryRoot>/</registryRoot>
        <enableCache>true</enableCache>
    </remoteInstance>
     <mount path="/_system/governance" overwrite="true">
        <instanceId>governance</instanceId>
        <targetPath>/_system/governance</targetPath>
    </mount>


Copy the mysql jdbc driver in repository/components/lib folder. Set different port offset in carbon.xml. For ESB_PROD server, let’s keep it as ‘2’. Start the server.
Go to https://localhost:9445/carbon/ URL and check the registry browser, you will see the registries are mounted. 

4. Endpoint configuration

We need to directly upload the endpoint configuration to the registry.Go to G-reg management console and upload the endpoint configurations(xml file) for the QA and Production environment under relevant target paths.
Eg: Upload the testEndpoint.xml of the qa environment to /_system/config/env/qa path. Upload the
testEndpoint.xml of the production environment to /_system/config/env/prod path.

Sample endpoint conf for QA-ESB server


<endpoint xmlns="http://ws.apache.org/ns/synapse" name="TestEndpoint">
   <address uri="http://<QA SERVICE ENDPOINT URL>">
      <suspendOnFailure>
         <progressionFactor>1.0</progressionFactor>
      </suspendOnFailure>
      <markForSuspension>
         <retriesBeforeSuspension>0</retriesBeforeSuspension>
         <retryDelay>0</retryDelay>
      </markForSuspension>
   </address>
</endpoint>


Sample endpoint conf for PROD-ESB server


<endpoint xmlns="http://ws.apache.org/ns/synapse" name="TestEndpoint">
   <address uri="http://<PROD SERVICE ENDPOINT URL>">
      <suspendOnFailure>
         <progressionFactor>1.0</progressionFactor>
      </suspendOnFailure>
      <markForSuspension>
         <retriesBeforeSuspension>0</retriesBeforeSuspension>
         <retryDelay>0</retryDelay>
      </markForSuspension>
   </address>
</endpoint>


5. Proxy Configuration

When we create proxy configuration we should not directly provide any of the address url. Rather we need to point the registry key. This registry key will be same for all environments. That means we do not need to modify the proxy configuration when we deploy that to qa or production environment.
Eg:  < endpoint="conf:/testEndpoint">

Sample proxy configuration

<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="testEnvProxy"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target endpoint="conf:/testEndpoint"/>
   <description/>
</proxy>

Related post
Environment Management in WSO2 DSS using WSO2GREG

Monday, May 19, 2014

Processing large text file using smooks in wso2esb

Smooks  library supports large file processing which is used in ESB to process file which are in text/xml format.
Text files can be a CSV file or with a space delimiter or a fixed length file. To process large file, smooks write the output stream , which is a single line record, to a temporary file or a jms queue. After writing all files to the temporary location, we need to process all those records/files again. This is how we can avoid large memory growth/out of heap space issue which occurs when we try to process large file as in- memory process.

Following is a sample configuration to process fixed length large text file in wso2esb.

Proxy configuration

To pick and process the file form a file location , we could use VFS transport.

<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="cor_file_pull"
       transports="https,http,vfs"
       statistics="disable"
       trace="disable"
       startOnLoad="true"target>
     <inSequence>
  <property name="DISABLE_SMOOKS_RESULT_PAYLOAD"
                   value="true"
                   scope="default"
                   type="STRING"/>
          <smooks config-key="simple-smook">
            <input type="text"/>
           <output type="xml"/>
         </smooks>
       </inSequence>
      <outSequence/>
   </target>
   <parameter name="transport.vfs.Streaming">true&lt;/parameter>
   <parameter name="transport.PollInterval">10&lt;/parameter>
   <parameter name="transport.vfs.ActionAfterProcess">MOVE&lt;/parameter>
   <parameter name="transport.vfs.MoveAfterProcess">C:/Users/TOSH/Desktop/success</parameter>
   <parameter name="transport.vfs.FileURI">C:/Users/TOSH/Desktop/in&lt;/parameter>
   <parameter name="transport.vfs.MoveAfterFailure">C:/Users/TOSH/Desktop/failure</parameter>
   <parameter name="transport.vfs.Locking">disable&lt;/parameter>
   <parameter name="transport.vfs.FileNamePattern">^(cor).+</parameter>
   <parameter name="transport.vfs.ContentType">text/plain</parameter>
   <parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
   <description/>
</proxy>

Smooks configuration

simple-smook localentry

<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd" xmlns:fl="http://www.milyn.org/xsd/smooks/fixed-length-1.3.xsd" xmlns:file="http://www.milyn.org/xsd/smooks/file-routing-1.1.xsd">
<params>
            <param name="stream.filter.type">SAX </param>
           <param name="default.serialization.on">false </param>
         </params>

<fl:reader fields="RecordId[4],CorpName[60],FileNumber[9]" skipLines="0">
</fl:reader>
      <resource-config selector="record">
         <resource> org.milyn.delivery.DomModelCreator</resource>
     </resource-config>
      <file:outputStream openOnElement="record" resourceName="fileSplitStream">
         <file:fileNamePattern> ${.vars["record"].FileNumber}.xml</file:fileNamePattern>
         <file:destinationDirectoryPattern> C:\Users\TOSH\Desktop\processed</file:destinationDirectoryPattern>
         <file:highWaterMark mark="10000000"> </file:highWaterMark>
      </file:outputStream>
      <ftl:freemarker applyOnElement="record">
         <ftl:template> /repository/resources/smooks/record_as_xml.ftl</ftl:template>
         <ftl:use>
            <ftl:outputTo outputStreamResource="fileSplitStream"> </ftl:outputTo>
         </ftl:use>
      </ftl:freemarker>
   </smooks-resource-list>

Each record will   be written to the specified file location   "C:\Users\TOSH\Desktop\processed" with the name constructed through the parameter "  ${.vars["record"].FileNumber}.xml ".  Here it is a xml file, which will be named with a file number    record in the text file. We have to select a unique parameter to write the processed files else there will be file overwriting issue will be thrown in smooks.
To process large file we have to use 'SAX' filter type. DOM needs more memory and it will lead to out of memory issue.
In this sample, i have used DOM+SAX mixing model to keep the lower footprint of memory.
High  water mark provides the maximum file records need to be written. provide enough number based on the lines in the text file.
The property ;
 <property name="DISABLE_SMOOKS_RESULT_PAYLOAD"   value="true" scope="default"     type="STRING"/>

will be available in ESB 4.9.0. If you use lower version, you might need a patch to be applied to your system.

XML template file
record_as_xml.ftl
<#assign rec = .vars["record"]>
<p:insert_acc_data_file xmlns:p="http://ws.wso2.org/dataservice"><p:RecordId>${rec.RecordId}</p:RecordId>
<p:CorpName>${rec.CorpName}&lt;/p:CorpName>
<p:FileNumber>${rec.FileNumber}&lt;/p:FileNumber></p:insert_acc_data_file>

Based on above template the records will be formatted and will be written to the .

Using another vfs proxy, we can pick the entries written to the  'processed' file and do further processing.

Sunday, May 4, 2014

Executing FaultSequence for SOAPFaults in WSO2ESB

In WSO2ESB/Synapse, whenever mediation errors occur, user can execute faultsequence to find error details.
The fault sequence can be defined at a sequence level or at proxy service level. Mediation level issues and endpoint errors can be captured at faultsequence. But SOAPFault can not be captured at fault sequence, since ESB/Synapse will treat it as the response from the endpoint.
But from user's pont of view , those are service endpoint failures which need to be handled properly.
To handle the soapfaults, now we can use a property which forces to execute fault sequence whenever soapfault occurs.
We need to set  following property before sending the message to endpoint.;

<property name="FORCE_ERROR_ON_SOAP_FAULT" value="true"/>

Sample conf;

<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="testProxy"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
  <target faultSequence="myfaultSeq">
      <inSequence>
         <property name="FORCE_ERROR_ON_SOAP_FAULT" value="true"/>
      </inSequence>
      <outSequence>
         <send/>
      </outSequence>
      <endpoint>
         <address uri="http://localhost:9764/services/echo/"/>
     </endpoint>
   </target>
   <description/>
</proxy>
           

In the above sample , whenever we get soapfault, the 'myfaultSeq' will be executed.

Related Post: Sending mails for errors

Tuesday, April 15, 2014

Securevault support for credientials used in mediation configuration

Secure vault tool which  is available in carbon servers, helps to encrypt passwords which are configured in plain text in the configuration files. This tool can be directly used for the passwords which are configured in carbon.xml,  axis2.xml, datasources.xml etc..We can not use secure vault tool directly in the mediation configuration , where we might provide passwords to make secured connection  for any basic auth protected endpoints.
In the older versions of ESB/APIM, we provide basic auth header by setting the "Authorization" transport header,where password was in plain text.

Eg: 
&lt;property name="Authorization" expression="fn:concat('Basic ', base64Encode('<Username>:<Password>'))" scope="transport"/>

In the newer versions (AM 1.6.0 / ESB 4.8.0 onwards), user can store the encrypted password in registry and  the 'alias' can be used to refer the stored passwords.

Eg:

<property name="secPassword" expression="wso2:vault-lookup('securedDS.endpoint.password')"/>
  • securedDS.endpoint.password : - Password alias, which is stored in config registry under /repository/components/secure-vault
  • wso2:vault-lookup :- Is a custom xpath implementation for synapse to do lookups. To use this custom xpath, user needs to add following synapse property in the synapse.properties file.
synapse.xpath.func.extensions=org.wso2.carbon.mediation.security.vault.xpath.SecureVaultLookupXPathFunctionProvider 

In APIManager;
  •  If user needs to encrypt the password in the mediation configuration, he has to enable the <EnableSecureVault> property in the api-manager.xml, and needs to run the cipher tool before running the product. 
  • Cipher tool is available in the  /bin folder.
    • # ciphertool.bat/sh -Dconfigure
  • When user enables securevault option and  publishes an API via the publisher UI, created API configuration will have the securevault enabled password protection. User can check the alias configured in the API configuration and can map that with the configuration registry entry. Alias is created with the string merge of  publisherName+apiName+version;
 In ESB, user can use management console to create aliases.


Monday, March 24, 2014

Axiom.soap.SOAPProcessingException: First Element must contain the local name, Envelope.


I faced this issue [1] and struggled a bit to find the root cause of this issue in synapse. The error was not clear enough to find out what was the issue.
The fix was, we need to set  the 'SOAPAction' property before sending out the message.

<property name="SOAPAction" value="urn:select_address " scope="transport"/>

Axis2 dispatches the message based on ;
  • Request URI based
  • Request URI Operation based
  • SOAP Action based
  • SOAP MessageBody based etc..
If system could not find any of the option to dispatch the request to correct endpoint, axis2 will throw an error states "operation not found/ EPR not found error"  .
But here, the error stack is not descriptive  to find the actual missing configuration.

[1] ERROR - RelayUtils Error while building Passthrough stream
org.apache.axiom.soap.SOAPProcessingException: First Element must contain the local name, Envelope , but found faultstring
        at org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder.constructNode(StAXSOAPModelBuilder.java:305)
        at org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder.createOMElement(StAXSOAPModelBuilder.java:252)
        at org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder.createNextOMElement(StAXSOAPModelBuilder.java:234)
        at org.apache.axiom.om.impl.builder.StAXOMBuilder.next(StAXOMBuilder.java:249)
        at org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder.getSOAPEnvelope(StAXSOAPModelBuilder.java:204)
        at org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder.(StAXSOAPModelBuilder.java:154)
        at org.apache.axiom.om.impl.AbstractOMMetaFactory.createStAXSOAPModelBuilder(AbstractOMMetaFactory.java:73)
        at org.apache.axiom.om.impl.AbstractOMMetaFactory.createSOAPModelBuilder(AbstractOMMetaFactory.java:79)
        at org.apache.axiom.om.OMXMLBuilderFactory.createSOAPModelBuilder(OMXMLBuilderFactory.java:196)
        at org.apache.axis2.builder.SOAPBuilder.processDocument(SOAPBuilder.java:55)
        at org.apache.synapse.transport.passthru.util.DeferredMessageBuilder.getDocument(DeferredMessageBuilder.java:118)
        at org.apache.synapse.transport.passthru.util.RelayUtils.builldMessage(RelayUtils.java:107)
        at org.apache.synapse.transport.passthru.util.RelayUtils.buildMessage(RelayUtils.java:82)
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:68)

Saturday, February 15, 2014

Sending mails using mail transport in wso2esb

Scenario:

If any error occurs in a message mediation flow, Administrator has to send mail to manager.

Axis configuration

To send mails, we use mail transport. Enable the 'MailTransportSender' to send emails in specific scenarios.

@axis2.xml;

<transportSender name="mailto" class="org.apache.axis2.transport.mail.MailTransportSender">
        <parameter name="mail.smtp.host">smtp.gmail.com</parameter>
       <parameter name="mail.smtp.port">587</parameter>
       <parameter name="mail.smtp.starttls.enable">true</parameter>
       <parameter name="mail.smtp.auth">true</parameter>
       <parameter name="mail.smtp.user">admin@abc.com</parameter>
        <parameter name="mail.smtp.password">XXXXX</parameter>
       <parameter name="mail.smtp.from">Admin</parameter>
  </transportSender>

Proxy configuration


 <proxy xmlns="http://ws.apache.org/ns/synapse"
       name="FileProxy"
       transports="https,http,vfs"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
    <target faultSequence="sendErrMailSequence">

       <inSequence>
.................
</inSEquence>
</proxy>



To get  a mail content in HTML format, we need to add HTML message formatter in axis2.xml
<messageFormatter contentType="text/html" class="org.apache.axis2.transport.http.ApplicationXMLFormatter"/>


SendErrMailSequence  configuration


<sequence xmlns="http://ws.apache.org/ns/synapse" name="sendErrMailSequence">
   <property name="messageType" value="text/html" scope="axis2"/>
   <property name="ContentType" value="text/html" scope="axis2"/>
  <property name="Subject" value=" Error occured" scope="transport"/>
   <property name="OUT_ONLY" value="true"/>
 <payloadFactory media-type="xml">
            <format>
               <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                  <soapenv:Body>
                     <ErrorMessage xmlns=""> Please check endpoint errors</ErrorMessage>
                  </soapenv:Body>
               </soapenv:Envelope>
           </format>
         </payloadFactory>
   <send>
      <endpoint name="MailEpr">
         <address uri="mailto:manager@abc.com"/>
      </endpoint>
   </send>

</sequence>

Friday, February 14, 2014

XML to Text transformation using smooks mediator

Smooks mediator can be used to apply transformations. Inputs can be provided as text/xml and smooks transformation resource has to be passed as an external resource.
Here is the sample smooks mediator configuration and smooks configuration which can be used to read an xml element from the input and parse it to a preferred output xml format.

Smooks meditaor config;

<smooks config-key="smooks">
               <input type="xml" expression="//csv/arg0"/>
               <output type="text"/>
            </smooks>


Sample request;

<soapenv:Envelope xmlns:soapenv=http://schemas.xmlsoap.org/soap/envelope/ >
 <soapenv:Body>
  <csv>
   <arg>1000,20130926,UAE</arg0>
  </csv>
 </soapenv:Body>
</soapenv:Envelope>

Smooks configuration;

<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.0.xsd">
   <resource-config selector="org.xml.sax.driver">
    <resource>org.milyn.csv.CSVParser</resource>
    <param name="fields" type="string-list">RecordID,FileNumber,CorporationName</param>
  </resource-config>
</smooks-resource-list>

Output;
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ax:text xmlns:ax="http://ws.apache.org/commons/ns/payload">
<csv-set>
<csv-record number="1">
<RecordID>1000</RecordID>
<FileNumber>00238374</FileNumber>
<CorporationName>UAE</CorporationName>
</csv-record>
</csv-set>
</ax:text>
</soapenv:Body>
</soapenv:Envelope>

Saturday, September 14, 2013

Content-Type Header and Axis2

I see some issues when set the "Content-Type" Header  in synapse. Aixs2 doesn't obey the "Content-Type" header, when the message conatins  different messageType.

Before sending a soap message to an endpoint in synapse, if we set the "Content-Type" as text/plain, axis2 sends out  the message with text/xml content-type. But if we set messageType property as text/plain, then content-type header of the outgoing message is set to "text/plain".  This is bit confusing as in the documentation, i find that, "messageType" property is used to select correct MessageFormatter.
There are three properties ,that are related to message-type,content-type which can be set in aixs2/transport scopes.

As in the documentations,
<property name="messageType" value="text/plain" scope="axis2" type="STRING"/>
can be used to select right Messageformatter.

<property name="ContentType" value="text/plain" scope="axis2" type="STRING"/>
can be used to select right MessageBuilders

To set the Content-Type transport header,we can use following property.
 <property name="Content-Type" value="text/plain" scope="transport" type="STRING"/>

But the issue is,
When i do following setting in synapse, aixs2 sends out the message with text/xml content-type.

<inSequence>
      <property name="Content-Type" value="text/plain" scope="transport" type="STRING"/>
         <send>
            <endpoint>
                   <address uri="http://localhost:9000/services/SimpleStockQuoteService"/>
            </endpoint>
       </send>

After setting the "messageType" property only i see the correct content-type is set.

Thursday, September 5, 2013

HTTP Basic Auth and WS-Security username/password authentication

Basic-auth and ws-security username/password authentication both are different and independent.

Basic auth is used in HTTP where user name and password will be encoded and passed  with the request as a HTTP header.
Eg:  HTTP header block will have " Authorization: Basic YWRtaW46YWRtaW4="  header element.

Username and password will be  encoded using base64 and which is used in  authorization header.
Eg: base64(username:password) --> base64(admin:admin)

Most of the webservice clients have option to provide basic auth header. In SOAPUI, at "Authentication" tab, we can provide username and password. If we switch to "Raw" format of the request, all the HTTP headers are visible and we can see the Basic Auth header is set.
When we use Basic Auth, the username and password setting is on the HTTP headers. Not in the SOAP message. SOAP message goes with HTTP body.

We can secure webservices using ws-security username/password authentication mechanism that is a simple mechanism to secure services. It enforces user to provide UsernameToken security header in the SOAP requests.

Sample request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://services.samples">
   <soapenv:Header>
      <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="Timestamp-10">
         <wsu:Created>t2013-09-05T16:44:03.872Z</wsu:Created>
         <wsu:Expires>2013-09-05T16:49:03.872Z</wsu:Expires>
     </wsu:Timestamp>
     <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-9">
       <wsse:Username>admin</wsse:Username>
       <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"&gtadmin</wsse:Password>
       </wsse:UsernameToken>
     </wsse:Security>
   </soapenv:Header>
   <soapenv:Body>
      <ser:getSimpleQuote>  
         <ser:symbol>IBM</ser:symbol>
      </ser:getSimpleQuote>
    </soapenv:Body>
</soapenv:Envelope>

If we check above sample request, the ws-security header is set as part of SOAP message.

WSO2  service hosting servers provide ws-username token security option. If we secure a service using user name token option, (that is, ws-security username/password authentication) we should pass ws-security headers as mentioned above.

But there is POXSecurity handler is available in the platform which converts HTTP-Basic Auth header to ws-security usernametoken header. So, if we enable UserName token security option for a service , we can send HTTP_basic auth header to execute the service.

Or else, we have to send request, with ws-security headers as mentioned in above sample request.

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.

Wednesday, June 19, 2013

Class Endpoints:Sample

In my older post , I mentioned that Class endpoint(ie: custom endpoints) feature is available in later versions of synapse, which is branched in WSO2 svn location.
Since, there are number of usecases to implement the class endpoint, i thought to write a simple sample using class endpoints.

Sample
All message sending logic is handled in the Axis2MEPClient.java class in synapse core. For instance, if we want to have our custom client which to do its own message sending  logic,we could write this type of endpoints.

In the following sample, i have defined an Custom Class Endpoint(ie:UAddressEndpoint) which extends the Synapse.AbstarctEndpoint class to define its own endpoint logic.

I read a parameter (this parameter ,we provide from endpoint configuration) from registry , where i saved my custom endpoint configuration . From that endpoint configuration i read  all endpoint related parameters, and use that as an Endpoint and have a separate   logic to send out message,

package org.wso2.carbon.endpoint.uep;

import org.apache.axis2.AxisFault;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.MessageContext;
import org.apache.synapse.endpoints.AbstractEndpoint;
import org.wso2.carbon.endpoint.uep.util.UEndpointUtil;
import org.wso2.carbon.unifiedendpoint.core.UnifiedEndpoint;

/**
 * ESB specific UAddressEndpoint class,extended from synapse Abstractendpoint.
 * 
 */
public class UAddressEndpoint extends AbstractEndpoint {

/**
* The registry location of the uep configuration,where it is stored
* Eg:conf:/repositoryuepTestEP.xml
*/
private String uepConfigurationPath;

private static final Log log = LogFactory.getLog(UAddressEndpoint.class);

public UAddressEndpoint() {

}

/**
* Getter and Setter of the parameter which we define at the classendpoint
* configuration.
* eg:
* name="uepConfigurationPath">conf:/repositoryuepTestEP.xml

         * @param uepConfiguration
*/
public void setUepConfigurationPath(String uepConfigurationPath) {
this.uepConfigurationPath = uepConfigurationPath;
}

public String getUepConfigurationPath() {

return uepConfigurationPath;
}

/**
* Override the AbstractEndpoint.send(). Use the UEP handler to
* get endpoint specific
* Configurations

*/
public void send(MessageContext synMessageContext) {
if (log.isDebugEnabled()) {
log.debug("Executing UAddressEndpoint Sender ");
}

try {

UAddressEndpointDefinition addressEPDefinition = new UAddressEndpointDefinition();
UEndpointUtil uepUtil = new UEndpointUtil();

UnifiedEndpoint unifiedEndpoint = uepUtil.getUnifiedEndpoint(uepConfigurationPath);

addressEPDefinition.setEndpointDefinition(unifiedEndpoint);
UEndpointAxis2MEPClient.send(unifiedEndpoint, getDefinition(), synMessageContext);
} catch (AxisFault e) {
log.error("Error in executing the message", e);
}
}

}

In the above sample,if you notice that I have my own class(ie: UEndpointAxis2MEPClient) to handle the message sending logic.

If we want to use this type of class endpoint, in synapse configuration we have to define our custom endpoint like this;

<endpoint name="CustomEndpoint">
                    <class name="org.wso2.carbon.endpoint.uep.UAddressEndpoin">
                                 <parameter name="uepConfigurationPath">conf:/repositoryuepTestEP.xml</parameter>
                    </class>
</endpoint>

Monday, June 17, 2013

Retrieving Axis2MessageContext from SynapseMessagecontext

Some times, we need to access Axis2 MessageContext in the sequence flow, using a custom class mediator.
Here is how you can access it;

public boolean mediate(MessageContext synapseMessageContext) {

org.apache.axis2.context.MessageContext axis2MsgContext;
axis2MsgContext = ((Axis2MessageContext) synapseMessageContext).getAxis2MessageContext();
 ..................
}

Tuesday, March 12, 2013

Accessing various information of a message in a mediation flow in WSO2ESB

Property mediator helps us to access various information of a message ,which passes through ESB. Within a sequence , we could use property mediator to get info about a message.
We can assign a value to a property as a string value or using xpath expression. Two actions are defined for property mediator.
  • Set
  • Remove
eg:
 <property name="MESSAGE" value="Executing in sequence"/>
 <property xmlns:m="http://sample.com"   name="test"   expression="//m:getQuote/m:symbol"
                   scope="default"  type="STRING"/>

We can use supported xpath functions,such as mathematical/logical operations and other predefined functions can be used to assign values in the property mediator.

eg: 

<property xmlns:ns="http://org.apache.synapse/xsd"   name="testProp"
                expression="fn:concat('hello','world')"   scope="default"/>

We can use  built in get-property() xpath function to read properties,which are available in the synapse messagecontext.
Eg: If a property "SYSTEM_TIME" available in the synapse message context; 

<property xmlns:ns="http://org.apache.synapse/xsd"   name="systemtime"
                expression="get-property('SYATEM_TIME')"   scope="default"/>


We can use property mediator to set values in different scopes, which can be accessed in those specific scope. There are 4 scopes,which are;
  • synapse/default : This property will be available in both insequence and outsequence.
  • axis2 : This property will be available in the particular sequence. can be retrieved from Axsi2Messagecontext.
  • transport:  This scope is used to set a property in the transport header.
  • axis2-client: Like "axis2" scope, but can be  retrieved form the Axis2Messagecontext.options.
eg:

<property name="myProp" value="abc" scope="default" type="STRING"/>
<property name="myProp" value="abc" scope="transport" type="STRING"/>
<property name="myProp" value="abc" scope="axis2" type="STRING"/> 
<property name="myProp" value="abc" scope="axis2-client" type="STRING"/>

When we retrieve properties from a specific scope;
eg:
 <property xmlns:ns="http://org.apache.synapse/xsd"    name="remotehost"
                    expression="get-property('axis2', 'REMOTE_HOST')"/>

There are some predefined xpath properties , which we can use directly to retrieve some common properties.
  • $axis2: Used to get the property at the axis2 scope.
 eg :
 <property name="MessageType is" expression="$axis2:messageType"/>
  • $trp: Used to get transport header properties.
eg:
 <property name="axis2Prop" expression="$trp:Content-Type"/>
  • $ctx : Used to get synapse scope properties;
eg:
 If we have a property named as "myProp" in synapse scope, which can be retrieved in the following manner;
 <property name="testProp" expression="$ctx:myProp"/>
  • $url : Used to retrieve parameters defined in the url
  eg:
For a request url; http:// localhost:8280/getSimpleQuote?symbol=IBM

<property name="symbol" expression="$url:symbol"/>
The above will retrieve the symbol value; ie:IBM

Friday, February 15, 2013

Accessing registry resources from class mediator in wso2esb

In the mediation process, users might need to access the registry resources, which are stored in the governance/config registries in wso2esb.
In the normal sequence flow, we could point the resources as registry keys in the mediators. But if we want to access them in a class mediator, where we may need to do custom process on the resource, we could retrieve the "WSO2Registry" instance from the  "SynapseConfiguration" and from the registry instance we could access different resources which are stored in the different registries.

Likewise if we have a 'LocalEntry' defined in the synapse configuration we could retrieve it from the "LocalRegistry". LocalEntries  are elements, used to declare registry entries that are local to the ESB instance. They are static resources and has high priority than a resource with the same name  hosted in embedded wso2registry.

Here is a sample class mediator, which can be used to retrieve a LocalEntry and resources hosted in governance/config registry.
import org.apache.synapse.MessageContext;
import org.apache.synapse.config.Entry;
import org.apache.synapse.mediators.AbstractMediator;
import org.apache.synapse.registry.Registry;
public class CustomRegistryRetriveMediator extends AbstractMediator {
   
    public boolean mediate(MessageContext synapseMsgContext) {

        // if localentry "
testLocalentry" defined in synapse econfig
        Entry localEntryObj = (Entry) synapseMsgContext.getConfiguration()
                .getLocalRegistry().get("testLocalentry");
        System.out.println(" value: " + localEntryObj.getValue());
        System.out.println(" Filename : " + localEntryObj.getFileName());

        // goverance/config registry
        Registry regInstance = synapseMsgContext.getConfiguration()
                .getRegistry();                       
        Object obj=regInstance.getResource(new Entry("gov:/test1.txt"),null);       
        Object obj2=regInstance.getResource(new Entry("conf:/test2.txt"),null);   
       
        return true;
    }
}

Monday, November 26, 2012

Configuring wso2esb to pass messages through proxy server

Organizations may expose the services over a proxy server for several purposes. In such a case, when user configures ESB, he has to provide proxy server configurations.
In axis2 configuration , at the transport sender configuration two properties has to be provided.
  • http.proxyHost : Proxy server's IP
  • http.proxyPort : Prosy server's port
eg :
 <transportSender name="http" class="org.apache.synapse.transport.nhttp.HttpCoreNIOSender">
        <parameter name="non-blocking" locked="false">true&lt;/parameter>
        <parameter name="http.proxyHost" locked="false">192.168.0.26  </parameter>
        <parameter name="http.proxyPort" locked="false">3128</parameter>
 </transportSender>
And a property (POST_TO_URI) has to be set in the synapse configuration to make ESB's out going URL a complete URL.

eg:
<inSequence>
    <property name="POST_TO_URI" value="true" scope="axis2"/>
    <send>
        <endpoint>
            <address uri="http://192.168.0.26:9000/services/SimpleStockQuoteService"/>
        </endpoint>
    </send>
</inSequence>
Depends on the proxy server's behaviour we may need to set some additional properties.
  • DISABLE_CHUNKING : If the proxy server doesn't support HTTP chunking. 
<property name="DISABLE_CHUNKING" value="true" scope="axis2"/>
  • FORCE_HTTP_1.0 : If proxy server supports only HTTP/1.0 messages.
<property name="FORCE_HTTP_1.0" value="true" scope="axis2"/>
 These properties can be applied to WSO2API Manager as well, since WSO2ESB is used as the gateway for APIManager.

Wednesday, October 3, 2012

REST Support in WSO2ESB - Handling JSON messages

In mobile applications we mostly use JSON messages, since they are easy to process. XML messages need more computational power to build the message.

 To process json messages, we need to enable the required message builder and formatter in the axis2 configuration.

 <messageFormatter  contentType="application/json" class="org.apache.axis2.json. JSONMessageFormatter"/>  

 <messageBuilder contentType="application/json"  class="org.apache.axis2.json. JSONBuilder"/>

Lets look at a sample scenario, where we need to 'GET' a json message from the backend service.
In this sample, we try to retrieve an user details which is stored in a database. To retrieve user details, we may define a simple "select" operation as a data-service.
Say, our data service runs at following endpoint;

http://localhost:9764/services/GetUserDetailsService.

As a second step,we need to define a suitable API for this..
Lets consider the "GET"  will be the only verb we are going to handle.
<api name="getusers" context="/public/user">
      <resource methods="GET"
                url-mapping="/*"
                inSequence="get-users-in-seq"
                faultSequence="fault"/>
   </api>

In the "get-users-in-seq" we might need to call our backend data service to retrieve user details.

 <sequence name="get-users-in-seq">  
      <property xmlns:ns="http://org.apache.synapse/xsd"
                name="userid"
                expression="substring-after(get-property('To'),'/public/user/')"/>
      <payloadFactory>
         <format>
           <p:getUserInfo xmlns:p="http://ws.wso2.org/dataservice">
               <p:Id>$1</p:Id>
            </p:getUserInfo>
        </format>
         <args>
            <arg xmlns:ns="http://org.apache.synapse/xsd"
                 expression="substring-after(get-property('To'),'/public/user/')"/>
         </args>
      </payloadFactory>
      <property name="SOAPAction" value="urn:getUserInfo" scope="transport"/>
      <send receive="recevingGetUserSeq">
         <endpoint>
            <address uri="http://localhost:9764/services/GetUserDetailsService"
                     format="soap11"/>
         </endpoint>
      </send>
   </sequence>
In the above sequence,

We construct the soap message using payloadfactory mediator, in a form which is expected by the backend data-service and send that to backend service. (note that, you can identify the SOAP message format, if you create a soapui project with the dataservice's wsdl.)

Backend service now will return the soap response, which we need to convert back as a json message and need to send back to the client.

   <sequence name="ecevingGetUserSeq">
         <xslt key="gov:/transformations/getUserTransform.xslt">
         <property xmlns:ns="http://org.apache.synapse/xsd"
                   name="userId"
                   expression="get-property('userid')"/>
      </xslt>
      <property name="messageType" value="application/json" scope="axis2"/>
      <send/>
   </sequence>
Here we use a XSLT script, which will formulate the expected json format which client expects.(ie: it will pick relevant info from the soap response and will construct a json message out of it)
Note that, we need to set the  "MessgeType"  property to "application/json", else axis2 wont pick the right message formatter.

We can execute this API with the following curl command to extract the user "Alice's" details.

   curl -v http://localhost:8280/public/user/Alice

Related post;
REST support in WSO2ESB - Introduction