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
      }
    }
  }
}