Case Study : How to monitor your business using WSO2 Business Activity Monitor

Scenario

Your organisation has an internal Order Management System (OMS). Whenever a customer wants to place an order,it's the internal staff who can access the system and create it. During a planning meeting, this closed nature of OMS has been identified as a barricade for future expansions. It was decided to let an outside development community to access OMS's data & encourage them to write applications based on it. Along with this change, planning team has also identified that monitoring Order data is equally important as well.

What you need? 

We will be using a sample database shipped with WSO2 Data Services Server to simulate OMS's database. The dashboard & gadget hosting capabilities of WSO2 BAM will be used to build a monitoring window of Order data.

Setting up the environment

Both WSO2 Data Services Server (v2.2.0) & WSO2 Business Activity Monitor (v1.0.0) are based on a common platform (called WSO2 Carbon). Due to this, both these servers have same port configurations. In order to successfully implement our scenario, we need to have both of these servers running at once. Hence, we need to change ports of one of the servers.

Let's change port configuration of WSO2 Data Services server.Here's how you do it.

1. Extract wso2dataservices-2.2.0.zip file. This will create a folder called wso2dataservices-2.2.0 & will be referred as WSO2DS_HOME hereafter.

2. Open WSO2DS_HOME/conf/transports.xml

3. Search for value '<parameter name="port">9763</parameter>' & change it to '<parameter name="port">9764</parameter>'

4. Search for value '<parameter name="port">9443</parameter>' & change it to '<parameter name="port">9444</parameter>' 

Setting up business data service

By default, WSO2 Data Services Server ships an embedded H2 sample database. This sample database has following table definitions & sample data populated in these tables. (Refer WSO2_DS_v2.2.0_HOME/samples/DataService/sql/h2 for database creation & population scripts).

As our business service, we will create a data service exposing following details as operations.

getLatestOrders() - returns the latest Orders available in the database

getOrdersWithHighestAmount() - returns the top 5 Orders having highest total amount

getCustomerWithHighestOrderCount() - returns top 5 of customers who have placed most number of Orders in the system

addOrder(..) - added new order to database

The complete data service (OrderStats) is as follows. 

<?xml version="1.0" encoding="UTF-8"?>
<data name="OrderStats" baseURI="http://ws.wso2.org/dataservice/samples/orderstats">
    <config id="default">
        <property name="org.wso2.ws.dataservice.driver">org.h2.Driver</property>
        <property name="org.wso2.ws.dataservice.protocol">jdbc:h2:file:./samples/DataService/database/DATA_SERV_SAMP</property>
        <property name="org.wso2.ws.dataservice.user">wso2ds</property>
        <property name="org.wso2.ws.dataservice.password">wso2ds</property>
    </config>
    <operation name="getOrdersWithHighestAmount">
        <call-query href="ordersWithHighestAmountSQL"/>
    </operation>
    <query id="ordersWithHighestAmountSQL" useConfig="default">
        <sql>
        SELECT TOP 3
	ORDERS.ORDERNUMBER,
	ORDERS.ORDERDATE,
	ORDERS.STATUS,
	CUSTOMERS.CUSTOMERNAME , 
	 (SELECT FLOOR(SUM(QUANTITYORDERED * PRICEEACH)) 
        	FROM ORDERDETAILS 
        	      WHERE ORDERNUMBER = ORDERS.ORDERNUMBER 
        	         GROUP BY ORDERNUMBER) AS AMOUNT
	FROM 
	   ORDERS,
	   CUSTOMERS 
	WHERE 
	   ORDERS.CUSTOMERNUMBER  = CUSTOMERS.CUSTOMERNUMBER
	</sql>
        <result element="Orders" rowName="Order">
            <element name="OrderNumber" column="ORDERNUMBER"/>
            <element name="OrderDate" column="ORDERDATE"/>
            <element name="Status" column="STATUS"/>
            <element name="CustomerName" column="CUSTOMERNAME"/>
            <element name="Amount" column="AMOUNT"/>
        </result>
    </query>

    <operation name="getCustomerWithHighestOrderCount">
        <call-query href="customerWithHighestOrderCountSQL"/>
    </operation>
    <query id="customerWithHighestOrderCountSQL" useConfig="default">
        <sql>
	SELECT TOP 5 
	CUSTOMERS.CUSTOMERNAME,
	COUNT(CUSTOMERS.CUSTOMERNUMBER) TOTAL_ORDER_COUNT   
	FROM 
	  ORDERS,
	  CUSTOMERS 
	WHERE 
	  ORDERS.CUSTOMERNUMBER  = CUSTOMERS.CUSTOMERNUMBER  
	GROUP BY 
	  CUSTOMERS.CUSTOMERNUMBER
	ORDER BY 
	  TOTAL_ORDER_COUNT DESC;
   </sql>
        <result element="Customers" rowName="Customer">
            <element name="Name" column="CUSTOMERNAME"/>
            <element name="Count" column="TOTAL_ORDER_COUNT"/>
        </result>
    </query>

    <operation name="getLatestOrders">
        <call-query href="latestOrdersSQL"/>
    </operation>
    <query id="latestOrdersSQL" useConfig="default">
        <sql>
	SELECT TOP 3
	ORDERS.ORDERNUMBER,
	ORDERS.ORDERDATE,
	ORDERS.STATUS,
	CUSTOMERS.CUSTOMERNAME
	FROM 
	   ORDERS,
	   CUSTOMERS 
	WHERE 
	   ORDERS.CUSTOMERNUMBER  = CUSTOMERS.CUSTOMERNUMBER   
	ORDER BY ORDERDATE DESC
   </sql>
        <result element="LatestOrders" rowName="LatestOrder">
            <element name="OrderNumber" column="ORDERNUMBER"/>
            <element name="OrderDate" column="ORDERDATE"/>
            <element name="Status" column="STATUS"/>
            <element name="CustomerName" column="CUSTOMERNAME"/>
        </result>
    </query>
    <operation name="addOrder">
      <call-query href="addOrderSQL">
        <with-param name="orderNo" query-param="orderNo" />
        <with-param name="orderDate" query-param="orderDate" />
        <with-param name="requiredDate" query-param="requiredDate" />
        <with-param name="status" query-param="status" />
        <with-param name="customerNo" query-param="customerNo" />
      </call-query>
    </operation>
    
   <query id="addOrderSQL" useConfig="default">
     <sql>
     INSERT INTO 
	ORDERS (ORDERNUMBER ,ORDERDATE ,REQUIREDDATE ,STATUS ,CUSTOMERNUMBER ) 
	VALUES (?,?,?,?,?)
     </sql>
     <param name="orderNo" sqlType="INTEGER" />
     <param name="orderDate" sqlType="DATE" />
     <param name="requiredDate" sqlType="DATE" />
     <param name="status" sqlType="STRING" />
     <param name="customerNo" sqlType="INTEGER" />    
   </query>
</data>

  

Deploying OrderStats data service in WSO2 Data Services Server

1. Boot up the WSO2 Data Services Server

Go inside wso2dataservices-2.2.0/bin folder

Type

./wso2server.sh (if your in Linux/Unix environment)

or

./wso2server.bat (for Windows environment)

Once the boot up is completed, you will see a message similar to following.

[2009-12-29 00:48:29,515] INFO - WSO2 Carbon started in 17 sec

2. Open up a web browser & login to Data Services administration console @ https://localhost:9444/carbon

(The default username/password are admin/admin).

3. Download OrderStats.dbs attached (bearing same content as listed above) to the end of this article.

4. Select 'Upload' option from your left hand menu (highlighted) & you will be take to a screen similar to following. Browse to the location where you saved 'OrderStats.dbs' & upload it to the system.

5. Click on 'Manage -> Services -> List' (Highlighted bellow) link & you will see the 'OrderStats' being listed as a service there.

Testing our business data service

WSO2 Data Services server ships tool called 'Try-It', which let's you to tests data services without leaving Administration console. Let's use this 'Try-It' tool to test the operations of our 'OrderStats' data service. To invoke 'Try-It' tool for OrderStats data service, click on 'Try this service' link (highlighted) on the service listing page.

  

You will get a page similar to following. This lists all the operations available on the OrderStats service.

To Invoke 'getLatestOrders' operation, click on the button & you will be presented with the results as follows.

Now let's select the 'addOrder' operation & add a new Order having following values. Once a new Order is added, invoke 'getLatestOrders' operation & you will see the new Order being listed on top.(This is due to having 'ORDER BY ORDERDATE DESC' in SQL).

 

Now that we have seen the output of these 4 operations, let's continue on how to add monitoring to Order management process using WSO2 Business Activity Monitor.

Monitoring business data through WSO2 BAM

WSO2 BAM server offers many options to monitor statistics of a given business service. This includes polling a service for statistics as well as receiving statistics exposed by services as and when a desired event happens. 

 

 The built-in dashboard (portal) page offers a way to present these collected statistics in the form of small portlet windows. This is pretty much similar to portal pages available in iGoogle, My Yahoo. These portlets can be written using Google's Gadget API.

In this tutorial, I will only explain how to write a Gadget to retrieve data from our business operations & display those on a dashboard page.

Booting up WSO2 BAM

1. Extract wso2bam-1.0.0.zip. This will create a folder called wso2bam-1.0.0. This folder will be referred to as WSO2BAM_HOME hereafter.

2. Go inside WSO2BAM_HOME/bin & start the server using either wso2server.bat or wso2server.sh (depending on your OS environment)

3. Access Admin Console using the url https://localhost:9443/carbon. The default username/password are admin/admin (similar to previous instructions on Booting up WSO2 DS)

Note : You cannot have multiple logged in sessions to different products based on WSO2 Carbon. Hence, once you login to WSO2 BAM Admin console, your previous login to WSO DS will be invalidated. As a work-a-round to this, you can use two different browser implementations (eg: FireFox/Chrome/IE) to keep both logged in sessions active. But this step is not a must & mentioned as additional information only.

Writing our first gadget – Orders with highest total amount

Listed bellow is the complete source for this gadget. (The same has been attached as an XML @ the end of this article)

<?xml version="1.0" encoding="UTF-8"?>
<Module>
    <ModulePrefs title="Orders with highest total amount"
                 description="Orders with highest total amount"
                 author="Sumedha Rubasinghe"
                 author_email="contact@wso2.org"
                 author_link="http://wso2.org/"
                 title_url="http://wso2.org/"
                 height="100"
                 scrolling="true">
        <Require feature="dynamic-height"/>
        <Require feature="settitle"/>
    </ModulePrefs>
    <Content type="html">
    <![CDATA[
    <style>
    	table.xx {
          font-family: verdana,arial,sans-serif;
          font-size:11px;
          color:#333333;
          border-width: 1px;
          border-color: #666666;
          border-collapse: collapse;
    	}
    	table.xx th {
    	  border-width: 1px;
    	  padding: 1px;
    	  border-style: solid;
    	  border-color: #666666;
    	  background-color: #dedede;
    	}
    	table.xx td {
    	  border-width: 1px;
    	  padding: 1px;
    	  border-style: solid;
    	  border-color: #666666;
    	  background-color: #FFFFF3;
    	}
    </style>
    <script type="text/javascript">
        var params = {};
        params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;
        var url = "http://localhost:9764/services/OrderStats/getOrdersWithHighestAmount";
        var refreshInterval = 0;
        var sep = "?";
        if (url.indexOf("?") > -1) {
          sep = "&";
        }
        url = [ url, sep, "nocache=", refreshInterval ].join("");
        gadgets.io.makeRequest(url, readFeed, params);

        function readFeed(feed) {
            if (feed == null) {
                alert('There is no data.');
                return;
            }
           // alert(feed.text);
           var html = '';
           if (feed.data.childNodes) {
            html +='<table class=\"xx\">';
            html +='<th>Order</th><th>Date</th><th>Status</th><th>Customer</th><th>Amount</th>';
            //Orders
            for (var i = 0; i < feed.data.childNodes.length; i++) {
            	//Order
            	for(var a = 0;a < feed.data.childNodes[i].childNodes.length; a++){
            		html +='<tr>';
            		//OrderNumber,Date,status,etc..
            		for(var b = 0;b < feed.data.childNodes[i].childNodes[a].childNodes.length;b++){
            			html +='<td>'+feed.data.childNodes[i].childNodes[a].childNodes[b].childNodes[0].data+'</td>';
            		}
            		html +='</tr>';
            	}
            }
            html +='</table>';
           }
           gadgets.window.setTitle('Highest Value Orders');         
           document.getElementById('content_div1').innerHTML = html;
           setTimeout("gadgets.window.adjustHeight()",100);
        }
  </script>
    <div id="content_div1"><img src="waiting.gif" alt="" /> </div>
</div>
    ]]>
    </Content>
</Module>

Following lines are calling the 'OrderStats' data service running on WSO2 Data Services instance. Here, we are using SOAPHTTPBinding (http://localhost:9764/services/OrderStats/getOrdersWithHighestAmount) of 'OrderStats' service.

 var url = "http://localhost:9764/services/OrderStats/getOrdersWithHighestAmount";
 …..
 …..
 gadgets.io.makeRequest(url, readFeed, params);

How to deploy 'Orders with highest total amount' gadget on WSO2 BAM server?

Now that we have seen source for this gadget, let's see how we can deploy this on WSO2 BAM server & view the outcome. There's a built-in registry available with WSO2 BAM server. The gadgets can be hosted within this registry.

On your WSO2 BAM Admin console's left had menu, click on the 'Browse' link under 'Registry' tab (highlighted).

 

Click on the 'system' link on your right hand side panel. On the page that follows click on the 'gadgets' link.

Now your screen should look like following. This repository location is the default place for hosting gadgets being using by WSO2 BAM. As you can see, source for all the existing gadgets are listed here.

Now let's upload source for 'Orders with highest total amount' gadget to this location as well. Click on the 'Add Resource' (highlighted) link & you will be taken into a screen similar to following.

Fill values as follows.

Method : Text content

Name : 1G_HighestTotalValue.xml(This can be any string. As you will see in a minute, the download URL for resource is determined by this name)

Media type : text/plain

Content : Copy the full content of 'aa_Orders_with_highest_total amount.xml' (attached) & paste it in the text area.

Click 'Add' button & now we have gadget's source stored in the registry.

Open up a new browser window & enter the URL 'http://localhost:9763/registry/resource/system/gadgets/1G_HighestTotalValue.xml' . You should be able to see the copied source of ' aa_Orders_with_highest_total amount.xml' similar to following. (Note: The Gadget specification does not allow you to use HTTPS URLs.)

 

We are going to use this URL in the next step. i.e. adding our gadget to dashboard.

Adding our gadget to dashboard

Click on 'Main Dashboard' link on your left hand menu.

This will load a screen similar to following. In this screen, click on 'Add New Tab' link & enter 'Orders' as new tab's name.

 

Your new tab will appear as follows.

 

On the next screen that appears, enter 'http://localhost:9763/registry/resource/system/gadgets/1G_HighestTotalValue.xml' (same URL we tested in the browser) as the URL of the 'Orders with highest total amount' gadget.

 

Your page should get refreshed & newly loaded page will have our gadget displayed similar to following.

Congratulations !!!.. Your first gadget is successfully loaded in WSO2 Business Activity Monitor's dashboard. Now let's try to deploy other two gadgets as well.

 

Deploying other 2 gadgets

Follow the above steps to upload the gadget definitions for other two gadgets to registry.Contents for these two gadgets can be found (attached) inside aa_Latest_Orders.xml & aa_Highest_ordering_customers.xml files.

When uploading I have used 1G_LatestOrders.xml & 1G_HighestOrders.xml as resource names respectively. Hence following URLs should list the source of the gadgets.

http://localhost:9763/registry/resource/system/gadgets/1G_LatestOrders.xml

http://localhost:9763/registry/resource/system/gadgets/1G_HighestOrders.xml

Once all of the three gadgets are uploaded, your resource browser should look like following.

 

Add two new gadgets to your dashboard using the URLs mentioned above.

 

Finally, your dashboard should look like following.

Final dashboard

Summary

WSO2 Data Services allows you to create data services exposing legacy data sources in your SOA platform. WSO2 Business Activity Monitor (the most recent addition to WSO2's family of products) let's you monitor services deployed on your SOA platform. In this article, I have demonstrated how WSO2 Data Services & WSO2 Business Activity Monitor combined can add value to your business service deployments & monitoring. I have taken a very simple use case & explained some of the very basic features of these two products.

Future work

1. How to modify gadget's source & view the results on the fly?

2. How to make your gadget's more eye catchy? 

AttachmentSize
aa_Highest_ordering_customers.xml2.86 KB
aa_Latest_Orders.xml2.82 KB
aa_Orders_with_highest_total amount.xml2.86 KB
OrderStats.dbs_.zip1.07 KB
library project main code
Learn Cloud
Learn
Cloud

The WSO2 Application Server is a reliable application server that can host your enterprise web applications. The WSO2 Application Server as a Service is offered in StratosLive, the WSO2 Platform as a Service. This article explains how a simple web application can be developed and deployed from Carbon Studio to the WSO2 Application Server...

Latest Webinar
Different groups within an organization need to monitor different Key Performance Indicators (KPIs) - An operations team will be interested in the response times of business services and loads of each service,..
Thursday, February 9th 2012, 09.00 AM (PST)

Thursday, February 9th 2012, 10.00 AM (GMT)