[Article] Implementing a Complete Enterprise Software System Using WSO2 Integration Cloud

  • By Nipun Suwandaratna
  • 26 May, 2017


Introduction to WSO2 Integration Cloud

WSO2 Integration Cloud is a public hosting of the WSO2 Integration platform that comprises integration components, services components, and custom components. WSO2 Integration Cloud also provides the ability to create MySQL databases hosted in the cloud (Figure 1).

Figure 1

For integration purposes, WSO2 Integration Cloud supports enterprise service bus (ESB) composite applications and Ballerina artifacts. With ESB composite applications you can implement mediation functionality like content or rule-based routing, message transformation (e.g. XML to JSON), protocol transformation (e.g. SOAP to REST), service composition, etc. Click here to learn more about WSO2’s ESB capabilities (now available via WSO2 Enterprise Integrator).

Ballerina is a general purpose, concurrent and strongly typed programming language with both textual and graphical syntaxes, that’s optimized for integration. It allows you to integrate apps and services by programming with a Sequence Diagram oriented visual programming approach designed to develop mediation workflows. It is network aware and enables programming based on sequence diagrams.

Furthermore, you can deploy services and applications based on the following:

  • Java Web Applications: Can deploy dynamic web applications bundled in WAR files.
  • Java Microservice: This option allows you to deploy Java Microservices created using the WSO2 Microservices Framework for Java (WSO2 MSF4J). MSF4J is an annotation-based programming model to create microservices.
  • PHP Web Application: Allows you to deploy PHP web applications.
  • WSO2 Jaggery Application: Jaggery is a framework that allows you to create web apps and HTTP Web services and handle front-end, back-end, communication and persistence logics purely in JavaScript.
  • WSO2 Data Service: Data services created using WSO2 data services components.

Using custom Docker images you can deploy any type of artifact to WSO2 Integration Cloud. You can also create MySQL databases in WSO2 Integration Cloud and connect to them from any application hosted within WSO2 Cloud or elsewhere.

Next, we’ll take a look at how you can use some of the WSO2 Integration Cloud components to build a complete system.



Business Scenario

Let’s consider the use case of a car rental company that rents cars and keeps a record of the customer and rent details. The company uses two systems to maintain information:

  1. A database that has customer information
  2. A system that stores start-dates and end-dates of car rentals - this will be implemented as a RESTful web service

Therefore, at present, information about a rental needs to be queried from 2 places; the customer information from the customer database and the vehicle rent dates from the car rental service. The current operation involves an operator to retrieve the information from both these systems to look up customer information pertaining to a particular rental.

There’s a requirement now to obtain rental information, including customer data and rent dates, via a single service. This would require an entity aggregation scenario where customer data from the database should be combined with data from the car rental service to present an aggregated view of the rental data. It also involves service chaining where first the car rental service is called to retrieve information about a particular rental, then the customerID is extracted from the response and used to look up customer data (Figure 2).

Figure 2

Traditionally, implementing the aforementioned operational systems would involve development of the systems individually as well as hosting them separately. They would also require database hostings. This would incur multiple deployment costs. And on top of that integrating the systems would further add development and deployment overheads.

However, by using the WSO2 Integration Cloud all of the above systems could be easily deployed in one place. It’s a one-stop solution for hosting services and robust enterprise integrations. Another advantage of using WSO2 Cloud is the flexibility of Scaling. WSO2 Integration Cloud employs a complete container-based hosting model. Each application is isolated and hosted in a separate container and can be scaled independently. The pricing model reflects this allowing you to choose your subscription based on usage.

All components of this system including the database can be hosted in WSO2 Cloud. In the following sections we’ll take a look at how to do the following on WSO2 Cloud:

  1. Creating a database to store customer data
  2. Creating a data service to easily expose data from the database as SOAP services using WSO2 data services components
  3. Creating a car rental service as a microservice
  4. Creating and deploying the ‘InfoService’ which will perform service chaining and entity aggregation



Customer data service


Creating the database

WSO2 Integration Cloud provides the facility to create and host a MySQL database on the cloud. Therefore, we’ll first setup the database in the cloud.

First login to WSO2 Integration Cloud and click on ‘Create Database’ (Figure 3).

Figure 3

You will be presented a screen to create the database as illustrated in Figure 4.

Figure 4

Once you create a database you will be presented the database URL and a username (Figure 5).

Figure 5

You can now log in to this database using a MySQL client.

Create the database using the following DDL:

CREATE TABLE `Customer` (
  `custID` varchar(90) NOT NULL PRIMARY KEY,
  `LName` varchar(200) DEFAULT NULL,
  `FName` varchar(200) DEFAULT NULL,
  `Address` varchar(200) DEFAULT NULL
);

And enter the following customer data:

 
insert into Customer values ("842700000", "Green", "Rachel","21, Hildale Avenue");
insert into Customer values ("852700000", "Buffet", "Phoebe","31, McLarens Bar");
insert into Customer values ("862700000", "Geller", "Monica","50, Down Streen, Timbuktoo");
insert into Customer values ("843300000", "Geller", "Ross","100, Hyatt Place, BM");
insert into Customer values ("853300000", "Bing", "Chandler","121, Palm Grove, Colombo 06");



Creating a data service

Now that the database has been created we need a way to extract the data from the database as a service. Traditionally this would involve coding a service to extract information from the database and exposing it as a service. However, WSO2 data services components offer a very convenient way to expose data as services by generating data services using a wizard. Follow the steps below to create a data service to expose the data from the database as a SOAP service.

Generate a data service by following the steps in this guide.

Note: When generating the service enter the database name you provided and select the database table (customer) when given the option to select tables. Once created you can try the service out and bundle it into an archive file as explained in the guide. Once you have created the archive file (.CAR file) you can deploy the data service on WSO2 Integration cloud.

Follow the below steps to do this

  1. Click ‘Create Application’ -> select ‘WSO2 Data Service’.
  2. Define the application name, version, and description.
  3. Next, select the ‘Upload from file system’ radio option and upload the CAR file you created.
  4. You can select a runtime in the next dropdown. At the time of this publication, the latest runtime is ‘WSO2 Data Services Server - 3.5.1’.
  5. Select a container spec.
  6. Upload an icon for the service.
  7. Next, you can create Environmental Variables and Tags. Environment variables allow you to change the apps configurations without modifying the source code, and tags allow you to define metadata about the application such as the app creator and version using key-value pairs.
  8. Start the service.

You can access the WSDL and try this service out using a tool such as SOAP-UI.

[The .dbs file and the Customer Data Service CAR file can be found in the Artifacts section of this article: Customer_DataService.dbs & CustomerDataServiceCAR_1.0.0.car]



Creating car rental service as a microservice

Next, we’ll create the car rental service as a microservice.

You can follow the instructions given in the following URL to create a fresh MSF4J project: https://github.com/wso2/msf4j/tree/master/archetypes

Running the given Mavan command will create a project with the following structure:

myservice
├── pom.xml
└── src
    └── main
        └── java
            └── org
                └── example
                    └── service
                        ├── Application.java
                        └── MyService.java

The org.example.service package has 2 classes: Application.java and MyService.java. The Application.java class in the application entry point and the MyService.java is the microservice resource class. You can write your service logic in this class.

For this example, we’ve implemented a service which returns some hard-coded values based on the input (vehicle no.).

Download the source files provided in this article and build the microservice by running the ‘mvn clean install’ command from the parent directory.

With the given artefacts msf4j-service-1.0.0-SNAPSHOT.jar will be generated in the target directory.

Here we have created a microservice that takes a single URL parameter and outputs vehicle rental details.

  1. In WSO2 Integration Cloud select Java Microservice.
  2. Enter Application name, version, and description.
  3. Upload the jar created above from filesystem.
  4. Select the runtime. E.g. this example uses WSO2 MSF4J 2.1.0, therefore you need to select ‘OracleJDK 8 + WSO2 MSF4J 2.1.0’ from the dropdown as runtime.
  5. Next, select a container specification. For this example ‘256MB RAM and 0.2 vCPU’ would be sufficient.256MB RAM and 0.2 vCP.
  6. Upload an icon and click Create.

Environment variables and tags have been explained in the ‘Customer data service’ section of this article.

Once you start the service you can access the service RESTfully by passing a URL parameter as shown below:

https://<organization_key>-<service_name>.wso2apps.com/service/getRental/{Vehicle_NO}
E.g. https://{cloud-service-url}/service/getRental/KIT-2000

[The Car Rental Service workspace can be found in the Artifacts section of this article: msf4j-service.zip and the msf4j-service-1.0.0-SNAPSHOT.jar can be found at: msf4j-service\target]



Info service


Service chaining

Figure 6

Now that we have both the data service and the car rental service up and running we can do a service chaining scenario that would provide a single service interface to access a composite data view from both these services. It becomes a service chaining scenario because the ‘customer ID’ retrieved from calling the ‘CarRentalService’ needs to be passed to the ‘CustomerDataService’ to retrieve the customer data.

For this we will create a WSO2 ESB service:

  1. Open WSO2 Developer Studio.
  2. Go to Developer Studio tab and open dashboard.
  3. Create ESB Config Project.
  4. Select the project you just created and again from the dashboard create a REST API.
  5. Select ‘Create a New Artefact’ and click next.
  6. Enter CustomerAPI as the name and /customer for the context and click Finish.
  7. You will be presented with a UI that allows creation of artifacts using drag-drop (Figure 7).

Figure 7

You can see there are two tabs below the palette: design and source.

Go to source and replace the content with the following API definition:

<api xmlns="https://ws.apache.org/ns/synapse" name="CustomerAPI" context="/customer">
   <resource methods="GET" uri-template="/{vehicleID}">
      <inSequence>
         <header name="Accept" scope="transport" action="remove"/>
         <call>
            <endpoint name="HTTPEndpoint">
               <http method="GET" uri-template="<car_rental_service_url>/service/getRental/{uri.var.vehicleID}"/>
            </endpoint>
         </call>
         <property name="custID" expression="//rental/customerID"/>
         <property name="rDate" expression="//rental/returnDate"/>
         <property name="sDate" expression="//rental/startDate"/>
         <log>
            <property name="LOG:custID" expression="$ctx:custID"/>
         </log>
         <payloadFactory media-type="xml">
            <format>
               <p:select_with_key_Customer_operation xmlns:p="https://ws.wso2.org/dataservice">
                  <a:custID xmlns:a="https://ws.wso2.org/dataservice">$1</a:custID>
               </p:select_with_key_Customer_operation>
            </format>
            <args>
               <arg evaluator="xml" expression="$ctx:custID"/>
            </args>
         </payloadFactory>
         <log level="full"/>
         <call>
            <endpoint name="DSSEndpoint">
               <address uri="<Customer Data Service Endpoint>/<operation>" format="soap12"/>
            </endpoint>
         </call>
         <log level="full"/>
         <property xmlns:ns1="https://ws.wso2.org/dataservice" name="LName" expression="//ns1:Customer/ns1:LName"/>
         <property xmlns:ns1="https://ws.wso2.org/dataservice" name="FName" expression="//ns1:Customer/ns1:FName"/>
         <property xmlns:ns1="https://ws.wso2.org/dataservice" name="Address" expression="//ns1:Customer/ns1:Address"/>
         <log>
            <property name="LOG:LName" expression="$ctx:LName"/>
            <property name="LOG:FName" expression="$ctx:FName"/>
            <property name="LOG:Address" expression="$ctx:Address"/>
         </log>
         <payloadFactory media-type="xml">
            <format>
               <result>
                  <custID>$1</custID>
                  <startDate>$2</startDate>
                  <returnDate>$3</returnDate>
                  <firstName>$4</firstName>
                  <lastName>$5</lastName>
                  <address>$6</address>
               </result>
            </format>
            <args>
               <arg evaluator="xml" expression="$ctx:custID"/>
               <arg evaluator="xml" expression="$ctx:sDate"/>
               <arg evaluator="xml" expression="$ctx:rDate"/>
               <arg evaluator="xml" expression="$ctx:FName"/>
               <arg evaluator="xml" expression="$ctx:LName"/>
               <arg evaluator="xml" expression="$ctx:Address"/>
            </args>
         </payloadFactory>
         <log level="full"/>
         <property name="messageType" value="application/xml" scope="axis2"/>
         <respond/>
      </inSequence>
   </resource>
</api>

Replace <car_rental_service_url> and <Customer Data Service Endpoint>/<operation> with the Car rental service URL, Customer data service URL and the operations (e.g. select_with_key_Customer_operation)

E.g.
<car_rental_service_url>:
https://<cloud service url>/service/getRental/{uri.var.OrgID}
 
 <Customer Data Service Endpoint>/<operation>:
https://<cloud service url>/service/getRental/{uri.var.vehicleID}

Now if you go back to the design view you’ll see something like what’s shown in Figure 8.

Figure 8

REST to SOAP Conversion

You may notice that this service is invoked RESTfully. However, the backend Car Rental Service is REST and the Customer Data Service is SOAP.

We invoke the ESB service with the ‘vehicleID’ as a URL param. Within the API definition we have invoked the Car Rental Service passing this vehicleID as a URL parameter:

<call>
        <endpoint name="HTTPEndpoint">
          <http method="get" trace="disable" uri-template="https://localhost:8080/service/getRental/{uri.var.vehicleID}"/>
        </endpoint>
</call>

Then we have extracted the customer ID and constructed a payload to be passed to the Customer Data Service using the payloadFactory mediator:

<payloadFactory media-type="xml">
        <format>
          <p:select_with_key_Customer_operation xmlns:p="https://ws.wso2.org/dataservice">
            <a:custID xmlns:a="https://ws.wso2.org/dataservice">$1</a:custID>
          </p:select_with_key_Customer_operation>
        </format>
        <args>
          <arg evaluator="xml" expression="$ctx:custID"/>
        </args>
  </payloadFactory>

Then using the result variables we have saved from both responses, we have formatted an aggregated response for the Info service output:

<payloadFactory media-type="xml">
        <format>
          <result>
            <custID>$1</custID>
            <startDate>$2</startDate>
            <returnDate>$3</returnDate>
            <firstName>$4</firstName>
            <lastName>$5</lastName>
            <address>$6</address>
          </result>
        </format>
        <args>
          <arg evaluator="xml" expression="$ctx:custID"/>
          <arg evaluator="xml" expression="$ctx:sDate"/>
          <arg evaluator="xml" expression="$ctx:rDate"/>
          <arg evaluator="xml" expression="$ctx:FName"/>
          <arg evaluator="xml" expression="$ctx:LName"/>
          <arg evaluator="xml" expression="$ctx:Address"/>
        </args>
      </payloadFactory>
      <log level="full"/>
      <property name="messageType" scope="axis2" type="STRING" value="application/xml"/>
      <respond/>

You can now export this API bundled in a CAR file following the same steps you did to export the Customer Data Service previously:

  1. Go to the Dashboard -> Create Composite Application Project -> provide a project name and select the ESB project you created from the Dependencies box.
  2. Once this is done right click on the composite application project -> select Export -> under WSO2 Platform Distribution select Composite Application Archive -> Click next and provide an Export Destination -> click Finish.

Once the CAR file is created you can create a WSO2 ESB Composite Application Project in WSO2 Integration Cloud and upload the CAR similar to how you uploaded the Customer Data Service CAR.

[The CAR file can be found in the Artifacts section of this article]

Once all services are started you can invoke the ESB service as follows:

You can invoke this service using the generated URL. E.g. https:///customer/KIT-2000.

You will receive a composite output which contains:

  • CustomerID
  • FirstName
  • LastName
  • Address
  • StartDate
  • EndDate


Conclusion

As shown above, WSO2 Integration Cloud facilitates hosting enterprise integrations in the cloud in a scalable and cost-effective manner. The different components of Integration Cloud could be used to create versatile integration scenarios, which could be robust cloud-to-cloud and/or cloud-to-enterprise (cloud or on-premise) scenarios and could integrate different applications with heterogeneous protocols. For example cloud services such as Salesforce, Gmail and Twitter could be connected with Integration Cloud using connectors provided by WSO2. Furthermore, you can connect to mobile apps, social media apps and any type of JDBC database. You could also leverage the built-in databases. The creation of data services can be done either by using the internal database or external data sources.

You can also make use of the powerful analytics capabilities to monitor integration flows and create rich custom dashboards.

The flexibility in scaling allows you to deploy at any scale, which is sufficient to meet the current traffic demands and scale up as necessary, thus making it a cost effective container based hosting solution for your integration requirements. As the load requirements grow you can easily scale up the system by spinning up new containers. You can use your own custom Docker images if required as well.

Apart from Integration Cloud, WSO2 Cloud offers an API Cloud for exposing your services as managed APIs, an Identity Cloud for security and identity & access management needs, and Device Cloud that allows you to manage Android, iOS, and Windows devices.

Visit WSO2 Cloud for more details - https://wso2.com/cloud/.



Artifacts