Tuesday, June 6, 2017

Configuring timeout intervals in WSO2 ESB.

WSO2 ESB has several timeout settings and you have to consider following order when setting timeouts:

Socket Timeout > max (Global endpoint timeout, Timeout of individual endpoints)

endpoint timeout :

You could define timeouts on the endpoint configuration such that it will affect only that particular endpoint. This will be a better option if you need to configure timeouts per endpoint for different Back End services. You can also define the action upon the timeout. Below example configuration will set the endpoint to timeout in 120 seconds and then execute the fault handler.

<timeout>

    <duration>120000</duration>

    <responseAction>fault</responseAction>

</timeout>

synapse.global_timeout_interval property could be configured in the following way:

1. The open ESB_HOME /repository/conf/synapse.properties file.

2. Add synapse.global_timeout_interval property if it is not defined already (The default value is 120 seconds).

synapse.global_timeout_interval=120000

3. Save the file and restart the ESB.

Follow below steps to set http.socket.timeout property:

1. Open <esb_home>/repository/conf/passthru-http.properties file.

2. Add http.socket.timeout property if it not defined already.

http.socket.timeout=150000

3. Save the file and restart the ESB.

Monday, May 22, 2017

How to configure scheduled task as a cron style entry in WSO2 ESB.

This article explains, how to add a CRON job to run a scheduled task for once a week. This particular example demonstrates a scheduled task to run on every Tuesday at 10:27 AM.

Please find below the CRON style to run the scheduled task every Tuesday at 10:27 AM:
0 27 10 ? * TUE *

Please find below the Task configuration which uses the above CRON style:

<task name="sampleTask"
         class="org.apache.synapse.startup.tasks.MessageInjector"
         group="synapse.simple.quartz">
      <trigger cron="0 27 10 ? * TUE *"/>
      <property xmlns:task="http://www.wso2.org/products/wso2commons/tasks" name="message">
         <test xmlns="">heloooooooo</test>
      </property>
      <property xmlns:task="http://www.wso2.org/products/wso2commons/tasks"
                name="proxyName"
                value="testProxy"/>
      <property xmlns:task="http://www.wso2.org/products/wso2commons/tasks"
                name="soapAction"
                value="soap11"/>
</task>

We received below logs for above task configuration:

[2017-05-23 10:27:00,004]  INFO - LogMediator To: , WSAction: soap11, SOAPAction: soap11, MessageID: urn:uuid:9689e4b5-5b8c-47bb-9cf8-c953fd5130cc, Direction: request, Envelope: <?xml version="1.0" encoding="utf-8"?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><soapenv:Body><test>heloooooooo</test></soapenv:Body></soapenv:Envelope>


Please refer this link which is a CRON maker, for creating more CRON job expressions.


Wednesday, May 3, 2017

How to overcome the issue "ESB adds port 80 to host header for http endpoints" in WSO2 ESB 4.8.1

There is a known issue in WSO2 ESB 4.8.1 where it adds port 80 to host header for http endpoints.

Issue: Please find the below logs on how ESB 4.8.1 sends the host header for http endpoints.
[2017-04-28 14:54:00,620] DEBUG - wire << "GET /v2/59030280110000c10b975dc7 HTTP/1.1[\r][\n]"
[2017-04-28 14:54:00,620] DEBUG - wire << "Accept-Encoding: gzip,deflate[\r][\n]"
[2017-04-28 14:54:00,620] DEBUG - wire << "Host: www.mocky.io:80[\r][\n]"
[2017-04-28 14:54:00,620] DEBUG - wire << "Connection: Keep-Alive[\r][\n]"
[2017-04-28 14:54:00,620] DEBUG - wire << "User-Agent: Synapse-PT-HttpComponents-NIO[\r][\n]"

As you could see in the above logs it always adds port 80 at the end of Host Header. As a solution you could add below property with the host header that you want the ESB to send the request.
<property name="REQUEST_HOST_HEADER" value="www.mocky.io" scope="axis2"></property>

Configured the below simple API to test the above property.
<api xmlns="http://ws.apache.org/ns/synapse" name="testAPI" context="/testAPI">
   <resource methods="GET">
      <inSequence>
<property name="REQUEST_HOST_HEADER" value="www.mocky.io" scope="axis2"></property>
         <send>
            <endpoint>
               <http method="get" uri-template="http://www.mocky.io/v2/59030280110000c10b975dc7"></http>
            </endpoint>
         </send>
      </inSequence>
      <outSequence>
        <send></send>
      </outSequence>
  </resource>
</api>

We received below logs after adding the REQUEST_HOST_HEADER property in the API.
[2017-04-28 15:13:34,735] DEBUG - wire << "GET /v2/59030280110000c10b975dc7 HTTP/1.1[\r][\n]"
[2017-04-28 15:13:34,736] DEBUG - wire << "Host: www.mocky.io[\r][\n]"
[2017-04-28 15:13:34,736] DEBUG - wire << "Accept-Encoding: gzip,deflate[\r][\n]"
[2017-04-28 15:13:34,736] DEBUG - wire << "Connection: Keep-Alive[\r][\n]"
[2017-04-28 15:13:34,736] DEBUG - wire << "User-Agent: Synapse-PT-HttpComponents-NIO[\r][\n]"

Tuesday, May 2, 2017

How to Convert a JSON Message to SOAP and SOAP to JSON in a Generic Way WSO2 APIM.

Please note that we have tested this scenario on APIM 2.1.0. In this scenario we are using synapse IN and OUT extensions to transform json to xml and vice versa in a generic way.
  • Use below configuration as the IN extension. 
Please find more information on adding Mediation Extensions in [1]

admin-TestPhoneApi:v1.0.0-IN
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="admin--TestPhoneApi:v1.0.0--IN">
    <log level="custom">
        <property name="TRACE" value="Global Mediation Extension"/>
    </log>
 <enrich>
            <source clone="true" xpath="$body/jsonObject/node()"/>
            <target type="body"/>
         </enrich>
         <enrich>
            <source type="body" clone="true"/>
            <target type="property" property="requestPayload"/>
         </enrich>       
         <payloadFactory media-type="xml">
             <format>
           <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://ws.cdyne.com/PhoneVerify/query">
 <soapenv:Body>
       $1
 </soapenv:Body>
</soapenv:Envelope>
</format>
           <args>
               <arg evaluator="xml" expression="$ctx:requestPayload"/>
            </args>
         </payloadFactory>
</sequence>

  • Use below configuration as the OUT extension.

admin-TestPhoneApi:v1.0.0-OUT

<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="admin--TestPhoneApi:v1.0.0--OUT">
    <log level="custom">
        <property name="TRACE" value="Global Mediation Extension"/>
    </log>
<property name="messageType" value="application/json" scope="axis2"/>
</sequence>

  • Create a simple API to send the message to back-end. In here we used "http://ws.cdyne.com/phoneverify/phoneverify.asmx" as the endpoint.

<?xml version="1.0" encoding="UTF-8"?>
<api xmlns="http://ws.apache.org/ns/synapse"
     name="admin--TestPhoneApi"
     context="/TestPhoneApi/1.0.0"
     version="1.0.0"
     version-type="context">
   <resource methods="POST" url-mapping="/*" faultSequence="fault">
      <inSequence>              
         <log level="full"/>
         <property name="api.ut.backendRequestTime"
                   expression="get-property('SYSTEM_TIME')"/>
         <filter source="$ctx:AM_KEY_TYPE" regex="PRODUCTION">
            <then>
               <send>
                  <endpoint name="admin--TestPhoneApi_APIproductionEndpoint_0">
                     <http format="soap12"
                           uri-template="http://ws.cdyne.com/phoneverify/phoneverify.asmx"/>
                     <property name="ENDPOINT_ADDRESS"
                               value="http://ws.cdyne.com/phoneverify/phoneverify.asmx"/>
                 </endpoint>
               </send>
            </then>
            <else>
               <sequence key="_sandbox_key_error_"/>
           </else>
         </filter>
      </inSequence>
      <outSequence>
         <class name="org.wso2.carbon.apimgt.gateway.handlers.analytics.APIMgtResponseHandler"/>
         <send/>
      </outSequence>
   </resource>
   <handlers>
      <handler class="org.wso2.carbon.apimgt.gateway.handlers.common.APIMgtLatencyStatsHandler"/>
      <handler class="org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler">
         <property name="apiImplementationType" value="ENDPOINT"/>
      </handler>
      <handler class="org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler"/>
      <handler class="org.wso2.carbon.apimgt.gateway.handlers.throttling.ThrottleHandler"/>
      <handler class="org.wso2.carbon.apimgt.gateway.handlers.analytics.APIMgtUsageHandler"/>
      <handler class="org.wso2.carbon.apimgt.gateway.handlers.analytics.APIMgtGoogleAnalyticsTrackingHandler">
         <property name="configKey" value="gov:/apimgt/statistics/ga-config.xml"/>
      </handler>
      <handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerExtensionHandler"/>
   </handlers>
</api>

  • Request 1 with headers :
{"CheckPhoneNumber":{"PhoneNumber":"18006785432","LicenseKey":"0"}}
  • Response for request 1:

{
  "CheckPhoneNumberResponse": {
    "CheckPhoneNumberResult": {
      "Company": "Toll Free",
      "Valid": true,
      "Use": "Assigned to a code holder for normal use.",
      "State": "TF",
      "RC": null,
      "OCN": null,
      "OriginalNumber": 18006785432,
      "CleanNumber": 8006785432,
      "SwitchName": null,
      "SwitchType": null,
      "Country": "United States",
      "CLLI": null,
      "PrefixType": "Landline",
      "LATA": null,
      "sms": "Landline",
      "Email": null,
      "AssignDate": null,
      "TelecomCity": null,
      "TelecomCounty": null,
      "TelecomState": "TF",
      "TelecomZip": null,
      "TimeZone": null,
      "Lat": null,
      "Long": null,
      "Wireless": false
    }
  }
}


  • Request 2 with headers:
{"CheckPhoneNumbers":{"PhoneNumbers":{"string":"1"},"LicenseKey":"0"}}
  • Response for request 2
{
  "CheckPhoneNumbersResponse": {
    "CheckPhoneNumbersResult": {
      "PhoneReturn": {
        "Valid": false,
        "OriginalNumber": 1,
        "CleanNumber": null,
        "Wireless": false
      }
    }
  }
}


Monday, April 17, 2017

How to send out the header "JMS_COORELATION_ID" with the message in WSO2 ESB.

In order to send the  "JMS_COORELATION_ID" with the message from wso2 ESB you are required to configure it as a transport header in the synapse configuration.

Hence, the property you need to configure is as below:

 <property name="JMS_COORELATION_ID" value="12345" scope="transport"/>

Please find the proxy configuration below which we tested the above property:

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="SMSForwardProxy"
       transports="jms"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <property name="JMS_COORELATION_ID" value="12345" scope="axis2"/>
         <send>
            <endpoint>
               <address uri="http://localhost:9000/services/SimpleStockQuoteService"/>
            </endpoint>
         </send>
      </inSequence>
      <outSequence>
         <send/>
      </outSequence>
   </target>
   <parameter name="transport.jms.ContentType">
      <rules>
         <jmsProperty>contentType</jmsProperty>
         <default>text/xml</default>
      </rules>
   </parameter>
   <parameter name="transport.jms.ConnectionFactory">myQueueConnectionFactory</parameter>
   <parameter name="transport.jms.DestinationType">queue</parameter>
   <parameter name="transport.jms.Destination">SMSStore</parameter>
   <description/>
</proxy>

With the above configuration we managed to send the "JMS_COORELATION_ID" with the message out from the ESB. Please find the logs below:

[2017-04-13 16:19:29,648] DEBUG - wire << "POST /services/SimpleStockQuoteService HTTP/1.1[\r][\n]"
[2017-04-13 16:19:29,648] DEBUG - wire << "JMS_DESTINATION: SMSStore[\r][\n]"
[2017-04-13 16:19:29,648] DEBUG - wire << "JMS_MESSAGE_ID: ID:45c1d2d1-4c1c-3bb7-b249-9af5f0dcf7bf[\r][\n]"
[2017-04-13 16:19:29,648] DEBUG - wire << "JMS_REPLY_TO: SMSReceiveNotificationStore[\r][\n]"
[2017-04-13 16:19:29,648] DEBUG - wire << "JMS_QPID_DESTTYPE: 1[\r][\n]"
[2017-04-13 16:19:29,648] DEBUG - wire << "JMS_PRIORITY: 4[\r][\n]"
[2017-04-13 16:19:29,648] DEBUG - wire << "JMS_TIMESTAMP: 1492080567188[\r][\n]"
[2017-04-13 16:19:29,649] DEBUG - wire << "JMS_EXPIRATION: 0[\r][\n]"
[2017-04-13 16:19:29,649] DEBUG - wire << "JMS_COORELATION_ID: 12345[\r][\n]"
[2017-04-13 16:19:29,649] DEBUG - wire << "Accept-Encoding: gzip,deflate[\r][\n]"
[2017-04-13 16:19:29,649] DEBUG - wire << "JMS_REDELIVERED: false[\r][\n]"
[2017-04-13 16:19:29,649] DEBUG - wire << "Content-Type: text/xml; charset=UTF-8[\r][\n]"   

Sunday, April 16, 2017

How to install SCIM feature to WSO2 APIM 2.1.0

By default SCIM feature is not available in APIM. You could enable the SCIM feature using the pom.xml based approach. Please find the steps below to enable SCIM feature in APIM 2.1.0 using pom.xml based approach.

  • Downloaded the p2 repo from [1] (WSO2 Carbon 4.4.x (Wilkes))
  • Download the wso2am-2.1.0.zip from [2].
  • Unzip wso2am-2.1.0.zip and p2-repo.zip into the same directory.
  • Create a pom.xml file including below configuration and copy into the same directory.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">     <modelVersion>4.0.0</modelVersion>     <groupId>org.wso2.sample</groupId>     <artifactId>sample-feature-installation</artifactId>     <version>1.0.0</version>     <packaging>pom</packaging>     <name>New feature</name>     <url>http://wso2.org</url>     <build>         <plugins>            <plugin>                 <groupId>org.wso2.maven</groupId>                 <artifactId>carbon-p2-plugin</artifactId>                 <version>1.5.4</version>                 <executions><                     <execution>                         <id>feature-install</id>                         <phase>package</phase>                         <goals>                             <goal>p2-profile-gen</goal>                         </goals>                         <configuration>                             <profile>default</profile>                             <metadataRepository>file:p2-repo</metadataRepository>                             <artifactRepository>file:p2-repo</artifactRepository>                             <destination>wso2am-2.1.0/repository/components</destination>                             <deleteOldProfileFiles>false</deleteOldProfileFiles>                             <features>                                 <feature>                                     <id>org.wso2.carbon.identity.scim.feature.group</id>                                     <version>5.2.0</version>                                 </feature> <feature>                                     <id>org.wso2.carbon.identity.provisioning.server.feature.group</id>                                     <version>5.7.5</version>                                 </feature>                             </features>                         </configuration>                     </execution>                 </executions>             </plugin>             <plugin>                 <groupId>org.apache.maven.plugins</groupId>                 <artifactId>maven-antrun-plugin</artifactId>                 <version>1.1</version>                 <executions>                     <execution>                         <phase>package</phase>                         <configuration>                             <tasks>                                 <replace token="false" value="true" dir="wso2am-2.1.0/repository/components/default/configuration/org.eclipse.equinox.simpleconfigurator">                                     <include name="**/bundles.info"/>                                 </replace>                             </tasks>                         </configuration>                         <goals>                             <goal>run</goal>                         </goals>                     </execution>                 </executions>             </plugin>         </plugins>     </build>     <repositories>         <repository>             <id>wso2-nexus</id>             <name>WSO2 internal Repository</name>             <url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>             <releases>                 <enabled>true</enabled>                 <updatePolicy>daily</updatePolicy>                 <checksumPolicy>ignore</checksumPolicy>             </releases>         </repository>     </repositories>     <pluginRepositories>         <pluginRepository>             <id>wso2-maven-releases-repository</id>             <url>http://maven.wso2.org/nexus/content/repositories/releases/</url>         </pluginRepository>         <pluginRepository>             <id>wso2-maven-snapshots-repository</id>             <url>http://maven.wso2.org/nexus/content/repositories/snapshots/</url>         </pluginRepository>     </pluginRepositories> </project>
  • Run below command:
mvn clean install
  • Enable SCIM for the primary user store from user-mgt.xml file as follows
<Property name="SCIMEnabled">true</Property>
  • Start the server.

Thursday, April 13, 2017

How to read/write files using VFS transport in WSO2 ESB

To enable the VFS transport
Edit the <ESB_HOME>/repository/conf/axis2/axis2.xml file and uncomment the VFS listener and the VFS sender as follows:

<transportreceiver name="vfs" class="org.apache.synapse.transport.vfs.VFSTransportListener"/>
<transportSender name="vfs" class="org.apache.synapse.transport.vfs.VFSTransportSender"/>

Create a folder structure as below:
├── Pass ├── Original ├── Failures ├── output
             ├── test.xml 

Configure the below proxy in WSO2 ESB.

<proxy name="testVFS" startonload="true" trace="disable" transports="https http vfs" xmlns="http://ws.apache.org/ns/synapse">
   <description>
   <target>
      <insequence>
         <property name="transport.vfs.ReplyFileName" scope="transport" value="myfile.xml">
         <property name="OUT_ONLY" value="true">
         <send>
            <endpoint>
               <address uri="vfs:file:///home/ubuntu/output">
            </address>
</endpoint>
         </send>
      </property></property></insequence>
   </target>
   <parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
   <parameter name="transport.PollInterval">5</parameter>
   <parameter name="transport.vfs.MoveAfterProcess">file:///home/ubuntu/Pass</parameter>
   <parameter name="transport.vfs.FileURI">file:///home/ubuntu/Original</parameter>
   <parameter name="transport.vfs.MoveAfterFailure">file:///home/ubuntu/Failures/</parameter>
   <parameter name="transport.vfs.FileNamePattern">.*.xml</parameter>
   <parameter name="transport.vfs.ContentType">application/xml</parameter>
   <parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
</description>
</proxy>

Our proxy will automatically poll for files in the given location.

  • test.xml file will be located in file:///home/ubuntu/Pass
  • myfile.xml will get created in the file:///home/ubuntu/output folder