Friday, 25 August 2017

The 100% Open Source ESB

Open Source ESB Market

Today, open source solutions giving a significant competition to the proprietary software solutions. Same applies for the ESB software.

There are number of open source ESB solutions available in the market, but the WSO2 ESB is the only ESB solution to be claimed as a 100% Open Source ESB solution in this competitive market. It was licensed under Apache License versions 2.0 .

When we say 100% Open Source ESB, there can be several questions coming in to your mind. Below will answer your questions.

Is the entire source code available freely? How about the Enterprise edition of WSO2 ESB?

There is no such concept called Enterprise WSO2 ESB and Open Source WSO2 ESB as you have come across with other open source ESB solutions. In WSO2 ESB, we provide the entire source code available for the users without restricting the use of any available feature.



Managing the success with Open Source Model

When it comes to Open Source ESB, you may have some doubts whether you can get necessary resources that helps to continue with an open source product.

The importance of WSO2 ESB is that, we have identified this and provides a higher level of support to the people who are using WSO2 ESB through several channels.

  • Source Code - Source code is managed in the git repository.
  • Issue tracker -  Issues can be tracked 
  • Community Contribution - You can contribute to the product
  • Documentation - There is complete guide on the use of WSO2 ESB.
  • An AI bot - An AI bot to answer product related queries
  • Stackoverflow - Raise your questions
  • Mailing List - You can monitor the mail threads and participate on discussions about product developments


Sustaining the business operations while catering to the Open Source model

The business model of the company is based on helping customers to be successful with using WSO2 products by providing necessary consultancy services as well as on-going production subscription support.

It would be nice to try it out by your self.

For more information visit WSO2 website.

Thursday, 3 August 2017

When you should consider using WSO2 ESB !!!

Over the time business operations and processes growing in a rapid rate which requires the organizations to focus more on the integration of different applications and reuse the services as much as possible for maintainability.

The WSO2 ESB (Enterprise Service Bus) will seamlessly integrate applications, services, and processes across the platforms, if we simplify it, ESB is a collection of enterprise architecture design patterns that is catered through one single product.

Lets see when you need to consider using WSO2 ESB for your business;

1. You have few applications/services working independently and now you need to integrate those

2. When you want to deal with multiple message types and media types

3. When you want to connect and consume services using multiple communication protocols (ex: jms, websockets , FIX)

4. When you want to implement Enterprise Integration scenarios such as route messages to suitable back-end or aggregate the responses coming form the back-end

5. When you want to expose your applications as a service or API to other applications

6. When you want to augment application security in to your applications

Likewise there are many more scenarios where WSO2 ESB is capable of catering to your integration requirements.

To get more information about WSO2 ESB please refer -  http://wso2.com/library/articles/2017/07/what-is-wso2-esb/

Wednesday, 19 July 2017

Working with WSO2 carbon Admin Services

WSO2 products managed internally using defined SOAP web services named as admin services. This blog will describe how to call the admin services and perform operation with out using the Management Console.

Note - I will be using WSO2 Enterprise Integrator to demonstrate this.

Lets look at how to access the admin services in wso2 products. By default the admin services are hidden from the user. To enable the admin services,


1. Go to <EI_HOME>/conf/carbon.xml and enable admin services as follows

<HideAdminServiceWSDLs>false</HideAdminServiceWSDLs>

2. Now start the EI server using

./integrator.sh -DosgiConsole
When the server is started click 'Enter' and you will be directed to the osgi console mode.

3. To search the available admin services, Add 'listAdminServices' in the osgi console.This will list down the available admin services with the URL to access the admin services.





Access Admin Service via SOAP UI

4. You can access any of the admin service via the service URL listed in the above step.

I will demonstrate how to access functionalities supported by the ApplicationAdmin service. This service support the functionalities such as list the available applications, get application details, delete application etc.

5. Start SOAP UI and create a SOAP project using the following WSDL.
https://localhost:9443/services/ApplicationAdmin?wsdl
 
6. If you want to list all the available applications in the EI server, open the SOAP request associated with listAllApplications and provide the HTTP basic authentication headers of the EI server. (Specify the user name and password of the EI server)


Similarly you can access any available admin service via SOAP UI with HTTP basic authentication headers.

Reference - https://docs.wso2.com/display/AM1100/WSO2+Admin+Services

Tuesday, 4 July 2017

Implementing Aggregator Pattern using Ballerina


Introduction to Aggregator Pattern

Aggregator is one of the basic pattern defined in SOA patterns and EIP patterns that can be used to define more complex scenarios.

According to the EIP patterns “The Aggregator is a special Filter that receives a stream of messages and identifies messages that are correlated. Once a complete set of messages has been received (more on how to decide when a set is 'complete' below), the Aggregator collects information from each correlated message and publishes a single, aggregated message to the output channel for further processing’ [1]

Use Case


Let’s assume a Salesperson wants to get the Customer's Personal Information, Contact Information and the Purchasing Behavior for a given customer ID through the Customer Relationship Management (CRM) system for the upcoming direct marketing campaign. In a real world scenario, the  CRM system needs to call multiple backend services to get the required information and aggregate the responses coming from the backend systems to provide the information requested by the salesperson.

The system will send a request message with the customer ID to retrieve the required information from following systems.
  • Send a request to "Customer Info Service" to get customer's personal information
  • Send a request to "Contact Info Service" to get customer's contact Information
  • Send a request to "Purchasing Behavior Service" to get the purchasing details of the customer

Implementation Description


Following backend services will provide the requested information based on the customer ID provided.
  •     ContactInfo.bal
  •     CustomerInfo.bal
  •     PurchasingInfo.bal
Intermediate service (AggregatorService) will get the responses coming from the backend services and integrate the responses to provide the response to the Salesperson.

Let's Code with Ballerina

First, go to Ballerina website and download the latest ballerina distribution.

Note - I have used Ballerina 0.89 version to demonstrate this use case

Start Ballerina Composer

Ballerina Composer is a visual editor tool that provides the capability to write or draw your integration scenario.

To start the composer, go to <Ballerina_Home>/bin and execute following command depending on your environment.

Linux Environment - ./composer
Windows Environment  - composer.bat

Implementing the backend services

To implement the above use case let's create the required backend services; Customer Info Service, Contact Info Service and Purchasing Behavior Service.

Customer Information Service
I have created a service named “CustomerInfoService” via the composer and provide the base path “/customerInfo” to access this service directly by the outside clients. To demonstrate the scenario, I have created a map to maintain the customer information. The jsonpath is used to extract the customer ID from the incoming request and extract the customer information from the ‘customerInfoMap’ based on the customer ID. If there is no details for the requested ‘CustomerID’, service will return an error payload.

Let’s see how this can be represented using the composer.

 
Following is the code representation of the above design.

package aggregator;

import ballerina.net.http;
import ballerina.lang.messages;
import ballerina.lang.jsons;
import ballerina.lang.system;

@http:config {basePath:"/customerInfo"}
service<http> CustomerInfoService {


    @http:POST{}

    @http:Path{value:"/"}
    resource CustomerInfoResource(message m) {
    json incomingPayload = messages:getJsonPayload(m);
        
    map customerInfoMap = {};
    json cus_1 = {"PersonalDetails": {"Name": "Peter Thomsons","Age": "32","Gender": "Male"}};
    json cus_2 = {"PersonalDetails": {"Name": "Anne Stepson","Age": "50","Gender": "Female"}};
    json cus_3 = {"PersonalDetails": {"Name": "Edward Dewally","Age": "23","Gender": "Male"}};
    customerInfoMap["100"]= cus_1;
    customerInfoMap["101"]= cus_2;
    customerInfoMap["102"]= cus_3;
       
        string customerID = jsons:getString(incomingPayload,"$.Customer.id");
        system:println("Customer ID = " + customerID);
        message response = {};
       
        json payload;
        payload, _ = (json) customerInfoMap[customerID];

        if (payload != null) {
            messages:setJsonPayload(response,payload);
        } else {
            json errorpayload = {"Response": {"Error": "No Details available for the given Customer ID"}};
            messages:setJsonPayload(response, errorpayload);
        }
       
    reply response;
    }
}


  

This service will return the customer Information based on the requested customer ID.

Note - I have created the Contact Info Service and Purchasing Behaviour Service similar to the above service. Only difference is the payload used in the service.

Implementing the Intermediate service

So far we have created the ‘Customer Information Service’, ‘Contact Information Service’ and ‘Purchasing Information Service’ using ballerina. Let’s see how to create an intermediate service to aggregate the responses coming from each of the backend system and provide an aggregated response to the salesperson.


I have created a service named “AggregatorService” to aggregate the backend responses. To implement the scenario I have used the Fork Join function in Ballerina, which has the capability of defining individual workers that will work on an assigned task and wait until all the workers are completed with the assigned task. When the backend responses are collected those will be aggregated to create a JSON payload as diagramed in composer below.



Following is the code representation of the above design.
 package aggregator;

import ballerina.net.http;
import ballerina.lang.messages;
import ballerina.lang.jsons;

@http:config {basePath:"/AggregatorService"}
service<http> AggregatorService {

 @http:POST{}

    @http:Path{value:"/"}
    resource CRMResource(message m) {
    http:ClientConnector customerInfoEP = create http:ClientConnector("http://localhost:9090/customerInfo");
    http:ClientConnector contactInfoEP = create http:ClientConnector("http://localhost:9090/contactInfo");
    http:ClientConnector purchasingInfoEP = create http:ClientConnector("http://localhost:9090/purchasingInfo");
    json incomingPayload = messages:getJsonPayload(m);
    string customerID = jsons:getString(incomingPayload, "$.Customer.id");
    message aggregateResponse = {};

    if (customerID == "100" || customerID == "101" || customerID == "102" ) {
        
        fork {
            worker forkWorker1 {
            message response1 = {};
            message m1 = messages:clone(m);
            response1 = http:ClientConnector.post(customerInfoEP, "/", m1);
            response1 -> fork;
            }
            
            worker forkWorker2 {
            message response2 = {};
        message m2 = messages:clone(m);
            response2 = http:ClientConnector.post(contactInfoEP, "/", m2);
          response2 -> fork;
            }

        worker forkWorker3 {
            message response3 = {};
            response3 = http:ClientConnector.post(purchasingInfoEP, "/", m);
            response3 -> fork;
            }

        } join (all) (map results){
            any[] t1;
            any[] t2;
    any[] t3;
            t1,_ = (any[]) results["forkWorker1"];
            t2,_ = (any[]) results["forkWorker2"];
    t3,_ = (any[]) results["forkWorker3"];
    message res1;
    message res2;
    message res3;
            res1, _  = (message) t1[0];
            res2, _  = (message) t2[0];
    res3, _  = (message) t3[0];
            json jsonres1 = messages:getJsonPayload(res1);
    json jsonres2 = messages:getJsonPayload(res2);
    json jsonres3 = messages:getJsonPayload(res3);

    
    json payload = {};
    payload.CustomerDetailsResponse = {};
    payload.CustomerDetailsResponse.PersonalDetails = jsonres1.PersonalDetails;
    payload.CustomerDetailsResponse.ContactDetails = jsonres2.ContactDetails;
    payload.CustomerDetailsResponse.PurchasingDetails = jsonres3.PurchasingDetails;
     messages:setJsonPayload(aggregateResponse,payload);
    }
 } else {
     json errorpayload = {"Response": {"Error": "No Details available for the given Customer ID"}};

 messages:setJsonPayload(aggregateResponse, errorpayload);
 }

reply aggregateResponse;
        
        
    }
}


Executing the Service


Deploying the Service
Now we have all the backend services and aggregator service created using Ballerina. Let’s see how to deploy and invoke the services.

I have packaged all the backend services and intermediate service under “aggregator” package by defining the “package aggregator;” on top of each service. For the demonstration purpose I have created a ballerina archive named “aggregator.bsz” including all the services in the “aggreagtor” package.

Use following command to create a ballerina archive

<Ballerina_HOME>/bin/ballerina build service <package> -o <FileName.bsz>

Ex: <Ballerina_HOME>/bin/ballerina build service aggregator -o aggregator.bsz

Run the following command to deploy and run the service.

./ballerina run service <BallerinaArchiveName>

Ex: ./ballerina run service aggregator.bsz

Note : Ballerina Archive for the above use case can be found from [2]


Invoking the Service

Now the Salesperson can get all the expected information (personal details, contact details and purchasing behavior information) required for the direct marketing campaign by providing the CustomerID to the CRM system.

Here, I have used “Postman” Rest Client to represent the CRM system and requesting the information for the CustomerID = “101”.

References 

  1. http://www.enterpriseintegrationpatterns.com/patterns/messaging/Aggregator.html
  2. https://github.com/sashikamw/BallerinaHackathon

Saturday, 24 June 2017

How to use nested UDTs with WSO2 DSS

WSO2 Data Services Server(DSS) is a platform for integrating data stores, creating composite data views and hosting data in different sources such as REST style web resources.

This blog guides you through the process of extracting the data using a data services when nested User Defined Types (UDT) used in a function.

Lets take the following oracle package that returns a nested UDT. When a nested UDT (A UDT that use standard data types and other UDT in it) exists in the oracle package, oracle package should be written in a way that it returns a single ref cursor, as DSS do not support nested UDTs out of the box.

Lets take the following oracle package that includes a nested UDT called 'dType4'. In this example I have used Oracle DUAL Table to represent the results of multiple types included in the 'dType4'.

Sample Oracle Package


create or replace TYPE dType1 IS Object (City VARCHAR2(100 CHAR) ,Country VARCHAR2(2000 CHAR));
/
create or replace TYPE dType2 IS TABLE OF VARCHAR2(1000);
/
create or replace TYPE dType3 IS TABLE OF dType1;
/
create or replace TYPE dType4 is Object(
Region VARCHAR2(50),
CountryDetails dType3,
Currency dType2);
/

create or replace PACKAGE myPackage IS
FUNCTION getData RETURN sys_refcursor;
end myPackage;
/
create or replace PACKAGE Body myPackage as FUNCTION getData
RETURN SYS_REFCURSOR is
    tt  dType4;
    t3  dType3;
    t1  dType1;
    t11 dType1;
    t2  dType2;
    cur sys_refcursor;
  begin
    t1  := dType1('Colombo', 'Sri Lanka');
    t11 := dType1('Delihi', 'India');
    t2  := dType2('Sri Lankan Rupee', 'Indian Rupee');
    t3  := dType3(t1, t11);
    tt  := dType4('Asia continent', t3, t2);
    open cur for
      SELECT tt.Region, tt.CountryDetails, tt.Currency from dual;
    return cur;
  end;
end myPackage;
/

Lets see how we can access this Oracle package using the WSO2 Data Services Server.

Creating the Data Service

1. Download WSO2 Data Services Server
2. Start the server and go to "Create DataService" option
3. Create a data service using given sample data source.

In this data service I have created an input mapping to get the results of the oracle cursor using 'ORACLE_REF_CURSOR' sql type. The given output mapping is used to present the  results returned by the oracle package.


<data name="NestedUDT" transports="http https local">
   <config enableOData="false" id="oracleds">
      <property name="driverClassName">oracle.jdbc.driver.OracleDriver</property>
      <property name="url">jdbc:oracle:thin:@XXXX</property>
      <property name="username">XXX</property>
      <property name="password">XXX</property>
   </config>
   <query id="qDetails" useConfig="oracleds">
      <sql>{call ?:=mypackage.getData()}</sql>
      <result element="MYDetailResponse" rowName="Details" useColumnNumbers="true">
         <element column="1" name="Region" xsdType="string"/>
         <element arrayName="myarray" column="2" name="CountryDetails" xsdType="string"/>
         <element column="3" name="Currency" xsdType="string"/>
      </result>
      <param name="cur" ordinal="1" sqlType="ORACLE_REF_CURSOR" type="OUT"/>
   </query>
   <resource method="GET" path="data">
      <call-query href="qDetails"/>
   </resource>
</data>

Response of the data service invocation is as follows

<MYDetailResponse xmlns="http://ws.wso2.org/dataservice">
   <Details>
      <Region>Asia continent</Region>
      <CountryDetails>{Colombo,Sri Lanka}</CountryDetails>
      <CountryDetails>{Delihi,India}</CountryDetails>
      <Currency>Sri Lankan RupeeIndian Rupee</Currency>
   </Details>
</MYDetailResponse>


Saturday, 28 January 2017

Use ZAP tool to intercept HTTP Traffic

ZAP Tool

Zed Attack Proxy is one of the most popular security tool that used to find security vulnerabilities in applications.

This blog discuss how we can use the ZAP tool to intercept and modify the HTTP and HTTPS traffic.

Intercepting the traffic using the ZAP tool


Before we start, lets download and install the ZAP Tool.

1) Start the ZAP tool using / zap.sh

2) Configure local proxy settings
 To configure the Local Proxy settings in the ZAP tool go to Tools -> Options -> Local Proxy and provide the port to listen.


3) Configure the browser
 Now open your preferred browser and set up the proxy to listen to above configured port.

For example: If you are using FireFox browser browser proxy can be configured by navigating to "Edit -> Preferences -> Advanced -> Setting -> Manual Proxy Configuration" and providing the same port configured in the ZAP proxy


4) Recording the scenario

Open the website that you want to intercept using the browser and verify the site is listed in the site list. Now record the scenario that you want to intercept by executing the steps in your browser.


5) Intercepting the requests

Now you have the request response flow recorded in the ZAP tool. To view the request response information you have to select a request from the left side panel and get the information via the right side "Request" and "Response" tabs.

Next step is to add a break point to the request to stop it to modify the content.

Adding a Break Point

Right click on the request  that you want to add a break point, and then select "Break" to add a break point



After adding the breakpoint. Record the same scenario that you recorded above. You will notice that, when the browser reached to the intercepted request it will open up a new tab called 'Break'.

Use the "Break" tab to modify the request  headers and body. Then click the "Submit and step to next request or response" icon to submit the request.




Then ZAP will return the request to the server with the changes applied to it.