Enterprise Architecture & Integration, SOA, ESB, Web Services & Cloud Integration

Enterprise Architecture & Integration, SOA, ESB, Web Services & Cloud Integration

Tuesday 24 November 2015

Read HTTP Header and Pass as CORS headers in WSO2 ESB

Are you facing CORS headers issue? If you want to understand it better, it has been defined well in https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS and https://en.wikipedia.org/wiki/Cross-origin_resource_sharing. You can also follow http://enable-cors.org/.

As you read, you would understand that you may have to pass the following response headers
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers


It is straightforward to add the first two headers in the response path (i.e., Out Sequence). For third header i.e., Access-Control-Allow-Headers, you may have to use the value that has come in the request header "Access-Control-Request-Headers". If so, you can achieve this in two steps:

Step 1:
Get the value for header "Access-Control-Request-Headers" and store the value in synapse config scope. It means that the value will be available both in and out sequence.

Snippet that need to be added in "In Sequence":
<property name="Access-Control-Request-Headers" expression="get-property('transport', 'Access-Control-Request-Headers')"/>

Step 2:
Get the value from synapse config, and set it as response header

Snippet that need to be added in "Out Sequence":
<property name="Access-Control-Allow-Headers"
     expression="$ctx:Access-Control-Request-Headers"
     scope="transport"
     type="STRING"/>


Sunday 15 November 2015

Expose existing SOAP Web Services as REST API using WSO2 ESB

Problem statement

Your enterprise might have invested a lot in exposing software assets as SOAP Web Services to integrate with internal and external applications. If a new "modern" consumer who can (or wants to) consume only REST API, would you rewrite the entire thing to support REST clients?

WSO2 ESB (for example, version 4.8.1 which I have used) supports RESTful integration using API. We can leverage this feature to expose SOAP web services through REST API without changes to SOAP services. So, same time you would be able to support existing SOAP clients and new REST clients.

There are many blogs / web sites available on detailed explanation on REST style. You can follow this https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm from Roy Fielding. Another blog on REST can be found here in http://rest.elkstein.org/2008/02/what-is-rest.html

Steps involved

The following steps are required to achieve what we said.
  1. Define REST API
  2. Transform request REST data into SOAP data
  3. Call the back end application / URL
  4. Transform response SOAP data into REST data (for example JSON)
  5. Respond with JSON response

Sample use case - Student Exam Result Service


Usecase overview

We will implement a simple use case - student exam results application. The organisation has the SOAP service already running in the premise that will take student id as input parameter and responds with marks for four subjects.

Sample request SOAP message:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:stud="http://www.example.org/student/">
   <soapenv:Header/>
   <soapenv:Body>
      <stud:getMarks>
         <student>John Smith</student>
      </stud:getMarks>
   </soapenv:Body>
</soapenv:Envelope>

Sample response message:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:stud="http://www.example.org/student/">
   <soapenv:Header/>
   <soapenv:Body>
      <stud:getMarksResponse>
         <marks>
            <Mathematics>95</Mathematics>
            <Science>97</Science>
            <Lang-I>92</Lang-I>
            <Lang-II>94</Lang-II>
         </marks>
      </stud:getMarksResponse>
   </soapenv:Body>
</soapenv:Envelope>

WSDL:
<wsdl:definitions name="Student" targetNamespace="http://www.example.org/student/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.example.org/student/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <wsdl:types>
      <xsd:schema targetNamespace="http://www.example.org/student/">
         <xsd:element name="getMarks">
            <xsd:complexType>
               <xsd:sequence>
                  <xsd:element name="student" type="xsd:string"/>
               </xsd:sequence>
            </xsd:complexType>
         </xsd:element>
         <xsd:element name="getMarksResponse">
            <xsd:complexType>
               <xsd:sequence>
                  <xsd:element name="marks" type="tns:Marks"/>
               </xsd:sequence>
            </xsd:complexType>
         </xsd:element>
         <xsd:complexType name="Marks">
            <xsd:sequence>
               <xsd:element name="Mathematics" type="xsd:int"/>
               <xsd:element name="Science" type="xsd:int"/>
               <xsd:element name="Lang-I" type="xsd:int"/>
               <xsd:element name="Lang-II" type="xsd:int"/>
            </xsd:sequence>
         </xsd:complexType>
      </xsd:schema>
   </wsdl:types>
   <wsdl:message name="getMarksRequest">
      <wsdl:part element="tns:getMarks" name="parameters"/>
   </wsdl:message>
   <wsdl:message name="getMarksResponse">
      <wsdl:part element="tns:getMarksResponse" name="parameters"/>
   </wsdl:message>
   <wsdl:portType name="Student">
      <wsdl:operation name="getMarks">
         <wsdl:input message="tns:getMarksRequest"/>
         <wsdl:output message="tns:getMarksResponse"/>
      </wsdl:operation>
   </wsdl:portType>
   <wsdl:binding name="StudentSOAP" type="tns:Student">
      <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
      <wsdl:operation name="getMarks">
         <soap:operation soapAction="http://www.example.org/student/getMarks"/>
         <wsdl:input>
            <soap:body use="literal"/>
         </wsdl:input>
         <wsdl:output>
            <soap:body use="literal"/>
         </wsdl:output>
      </wsdl:operation>
   </wsdl:binding>
   <wsdl:service name="Student">
      <wsdl:port binding="tns:StudentSOAP" name="StudentSOAP">
         <soap:address location="http://www.example.org/"/>
      </wsdl:port>
   </wsdl:service>
</wsdl:definitions>

Now, lets do some hands on in WSO2 ESB.

1. Define REST API

In WSO2 ESB Management Console, goto Main --> Service Bus --> API and create a new API. The steps are very clearly mentioned in the WSO2 documentation site https://docs.wso2.com/display/ESB480/Getting+Started+with+REST+APIs how to create API. 


The API definition will look like this.

<api xmlns="http://ws.apache.org/ns/synapse"
     name="StudentAPI"
     context="/exam-results">
   <resource methods="GET" uri-template="/student/{student}" >

<inSequence> </inSequence>
<outSequence> </outSequence>
</resources>
</api>

This will provide a REST GET url like this http://localhost:8280/exam-results/student/1002 where 1002 is the student id for which we need the marks scored in four subjects. The URL may directly be accessed from a browser for instance.

2. Transform request REST data into SOAP data

Use Payload Mediator to transform REST data into SOAP data

         <payloadFactory media-type="xml">
            <format>
               <stud:getMarks xmlns:stud="http://www.example.org/student/">
                  <student>$1</student>
               </stud:getMarks>
            </format>
            <args>
               <arg evaluator="xml" expression="get-property('uri.var.student')"/>
            </args>
         </payloadFactory>

3. Call the back end application / URL

Set Action property and configure the SOAP end point URL

         <header name="Action" value="http://www.example.org/student/getMarks"/>
     <send>
            <endpoint>
<address uri="http://localhost:8088/services/Student" format="soap11"/>
            </endpoint>
         </send>

4. Transform response SOAP data into REST data (for example JSON)

Now, you will get the response in SOAP format. Use Payload Mediator to transform into REST data i.e., JSON

         <payloadFactory media-type="json">
            <format>{"Language_1": "$1", "Language_2": "$2", "Maths": "$3", "Science": "$4"}</format>
            <args>
               <arg xmlns:stud="http://www.example.org/student/"
                    evaluator="xml"
                    expression="$body/stud:getMarksResponse/marks/Lang-I"/>
               <arg xmlns:stud="http://www.example.org/student/"
                    evaluator="xml"
                    expression="$body/stud:getMarksResponse/marks/Lang-II"/>
               <arg xmlns:stud="http://www.example.org/student/"
                    evaluator="xml"
                    expression="$body/stud:getMarksResponse/marks/Mathematics"/>
               <arg xmlns:stud="http://www.example.org/student/"
                    evaluator="xml"
                    expression="$body/stud:getMarksResponse/marks/Science"/>
            </args>
         </payloadFactory>

5. Respond with JSON response


Change the response type to JSON and send the response to REST client

         <property name="messageType" value="application/json" scope="axis2"/>
         <send/>









When you execute, the output will look like
{
  "Language_1": "92",
  "Language_2": "94",
  "Maths": "95",
  "Science": "97"
}

See below the complete API definition

<?xml version="1.0" encoding="UTF-8"?>
<api xmlns="http://ws.apache.org/ns/synapse"
     name="StudentAPI"
     context="/exam-results">
   <resource methods="GET" uri-template="/student/{student}">
      <inSequence>
         <log level="custom">
            <property name="student_name_##########"
                      expression="get-property('uri.var.student')"/>
         </log>
         <payloadFactory media-type="xml">
            <format>
               <stud:getMarks xmlns:stud="http://www.example.org/student/">
                  <student>$1</student>
               </stud:getMarks>
            </format>
            <args>
               <arg evaluator="xml" expression="get-property('uri.var.student')"/>
            </args>
         </payloadFactory>
         <header name="Action" value="http://www.example.org/student/getMarks"/>
         <property name="Accept-Encoding" scope="transport" action="remove"/>
         <log level="custom">
            <property name="#body" expression="$body/*"/>
         </log>
         <send>
            <endpoint>
               <address uri="http://localhost:8088/services/Student" format="soap11"/>
            </endpoint>
         </send>
      </inSequence>
      <outSequence>
         <log level="custom">
            <property name="#response-body-from-Backend" expression="$body/*"/>
         </log>
         <payloadFactory media-type="json">
            <format>{"Language_1": "$1", "Language_2": "$2", "Maths": "$3", "Science": "$4"}</format>
            <args>
               <arg xmlns:stud="http://www.example.org/student/"
                    evaluator="xml"
                    expression="$body/stud:getMarksResponse/marks/Lang-I"/>
               <arg xmlns:stud="http://www.example.org/student/"
                    evaluator="xml"
                    expression="$body/stud:getMarksResponse/marks/Lang-II"/>
               <arg xmlns:stud="http://www.example.org/student/"
                    evaluator="xml"
                    expression="$body/stud:getMarksResponse/marks/Mathematics"/>
               <arg xmlns:stud="http://www.example.org/student/"
                    evaluator="xml"
                    expression="$body/stud:getMarksResponse/marks/Science"/>
            </args>
         </payloadFactory>
         <property name="messageType" value="application/json" scope="axis2"/>
         <log level="custom">
            <property name="#body" expression="$body/*"/>
         </log>
         <send/>
      </outSequence>
   </resource>
</api>

Hope this is useful to you. Please let me know if any further help.

Wednesday 14 October 2015

Enable TLS in Standalone Java to connect to WSO2 IS

Some days ago, I wrote a blog on how to disable SSL and enable TLS in WebLogic application server. The link is here if you are interested to read further http://ayyappan-gandhirajan.blogspot.in/2015/09/enable-tls-security-in-weblogic-n-WSO2-IS.html

My colleague has approached me today to know how to do the same thing in a Core Java environment - I mean he is running a standalone program which uses HttpURLConnection to connect to HTTPS URL (which is hosted in WSO2 Identity Server, available at http://wso2.com/products/identity-server/)

After spending some time, I found a way to do this which has been described below:

1. Add JVM argument -Dhttps.protocols=TLSv1 on the client side

2. Or add this line into your the jave program - java.lang.System.setProperty("https.protocols", "TLSv1");

He just added JVM argument, and now he is able to connect the HTTPS URL without any issue.

Hope you like it.

Wednesday 30 September 2015

Enable TLS security in Weblogic Application server to avoid "Read channel closed" error

Some host servers have been configured "not" to use SSL v1, v2 and v3 protocols for security reasons. Instead, they have been configured to use TLS protocol to ensure more secure HTTPS traffic.

Recently, I faced an issue with using SSL. My WebLogic application server had to connect to WSO2 Identity Server (http://wso2.com/products/identity-server/) for getting access token (https://docs.wso2.com/display/IS500/OpenID+Connect+with+the+WSO2+Identity+Server+and+WSO2+OAuth2+Playground) using an HTTPS URL. However, I was initially getting error "Read channel closed" on the WebLogic side. There was no other useful information. My other colleague, who takes care of WSO2 IS, troubleshooted and found that SSL has been disabled on the WSO2 IS server. This gave me a clue and then finally found the following option to make WebLogic to use TLS rather than SSL for initiating HTTPS traffic.

Pass this JVM argument -Dweblogic.security.SSL.protocolVersion=TLS1 into your WebLogic application server start up script. Restart the server and it is DONE.

With the above, my WebLogic server is now able to connect to WSO2 IS using HTTPS protocol.

Hope this helps.


Wednesday 15 April 2015

How to find out character set in Oracle database

There is a simple SQL Query which can be used to find out the character set used in Oracle database

select * from nls_database_parameters where parameter='NLS_CHARACTERSET';

When I executed this, I got this below.

NLS_CHARACTERSET    AR8MSWIN1256