Wednesday, December 30, 2015

Data visualization with D3.js

What is Data Visualization ?

Data visualization is the way of present the data in a pictorial or graphical format and it helps people to understand the importance of data in a visual context. This is very crucial because data on its own can be very hard to understand and analyze.

Why Data Visualization ?

As millions of data is collected and analyzed, the decision makers use data visualization tools which enable them to see analytical results presented visually, find relevance among the variables, communicate concepts and hypotheses to others and even predict the results for future. Because of the way the human brain processes information, it is faster for people to gather the significance of many data points when they are displayed in charts and graphs rather than representing them over piles of spreadsheets, flat files or reading tables of reports and it helps to easily interpret the data, saving time and energy.

What is D3 ?

D3 is a JavaScript library which is used to manipulate documents based on data (interactive visualization). D3 helps bring data to life using HTML, SVG, and CSS. D3 stands for Data Driven Documents. Here documents refer to the DOM (Document Object Model) structure in html. It allows developers to bind arbitrary data to a DOM, and then apply data-driven transformations to the document.

Selections in D3

Before moving into the details, first look at the initial version of our html document below. (I'm referring a local copy of D3.js library here)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Example in D3</title>
    <script src="d3.min.js"></script>
</head>
<body>
<script>
    //D3 code goes here
</script>
</body>
</html>

Similar to jQuery, D3 allows us to select elements from the DOM based on CSS selectors, for instance by id, class attribute or tag name. The result of a select operation is an array of selected elements.

In D3 using select(), we can select a single element from the DOM in html. Let's say as an example if we want to color the background of the body tag using color blue then we can do it as follows.

d3.select("body").style("background-color", "blue");

For every data value in the selection, we can append a new DOM element given by element name and associate the data value to it. An example is showing below.

d3.select("body").append("h1").html("Support Vector Machines");

In D3.js selectAll() method uses CSS3 selectors to grab DOM elements. Unlike the Select() method which previously mentioned, the SelectAll() selects all the elements in the DOM that match the specific selector string. 

d3.selectAll("p").style("background-color","blue");

In the above example it selects all the <p> elements available on the page. If there is none then it returns an empty selection. Here most important thing is that we don’t need to loop over our set of elements in order to apply modification on them. Instead, we apply the style operator to the selection, and D3 takes care of invoking it on every single element within.

Scales in D3

Scales transform numbers or discrete values in a certain interval (called the domain) into numbers in another interval (called the range).  For instance, let’s suppose we have a  dataset which is always over 100 and always below 800. We would like to plot it, say, in a bar chart, which can be only within 100 pixels length.

Domain (data space) rep­re­sents the bound­aries within which our data lies. Let's say as an example if I have an array of num­bers with no num­ber smaller than 1 and no num­ber larger than 1000, my domain would be 1 to 1000.

There will not always be a direct map­ping between the data points and actual pixels on the screen. Let's say as an example, if we are plot­ting a graph of sales and the sales is in tens of thou­sands, it is unlikely that we will be able to have a bar graph with the same pixel length as the data. In that case, we need to spec­ify the bound­aries within which the orig­i­nal data can be trans­formed. These bound­aries are called the range.

The most com­mon types of scales are quan­ti­ta­tive scales and ordi­nal scales. Quan­ti­ta­tive scale func­tions are those that trans­late one numeric value into another numeric value using dif­fer­ent types of equa­tions such as lin­ear, log­a­rith­mic etc. Data may not always in the numeric format. It may con­tain ordinal/categorical/discrete values. For example, alpha­bets. Alpha­bets are ordi­nal (means categorical with clear ordering of the variables) val­ues, i.e. they can be arranged in an order, but you can­not derive one alpha­bet from the other unlike numbers.

d3.scale.linear() - It transforms numeric data in a given dataset into pixel space.
eg: d3.scale.linear().domain([0,1000]).range([0, 100]); 

d3.scale.ordinal() -  It transforms data that has discrete values into pixel space.
eg: d3.scale.ordinal().domain(["A", "B", "C", "D"]).rangePoints([0, 100]);

If you write the output of scale("A"), scale("B"), scale("C") and scale("D") to the console (eg: console.log(scale("A"))) it prints 0, 33.33, 66.66 and 100 respectively.

With rangePoints(interval), d3 fits to the number of categories (eg: n number of points or categories) in the domain within the interval. In that case, the value of the first point is the beginning of the interval, that of the last point is the end of the interval.

With rangeBands(interval), d3 fit n bands within the interval. Here, the value of the last item in the domain is less than the upper bound of the interval.

If we use rangeRound() instead of range(), this will guarantee that the output of the scales are integers, which is better to position marks on the screen with pixel precision than numbers with decimals.

How to visualize dataset using D3 ?

In this section I will able to describe how to plot a horizontal bar-chart for the following sample dataset.

 [{
    "tableName": "PROCESS_USAGE_SUMMARY_DATA",
    "timestamp": 1447495522776,
    "values": {
        "processDefKey": ["manualTaskProcess:1:14"],
        "avgExecutionTime": 31066
    }
}, {
    "tableName": "PROCESS_USAGE_SUMMARY_DATA",
    "timestamp": 1447495522890,
    "values": {
        "processDefKey": ["VacationRequest:1:22"],
        "avgExecutionTime": 16215.5
    }
}, {
    "tableName": "PROCESS_USAGE_SUMMARY_DATA",
    "timestamp": 1447495522987,
    "values": {
        "processDefKey": ["OrderProcess:1:10"],
        "avgExecutionTime": 54892
    }
}, {
    "tableName": "PROCESS_USAGE_SUMMARY_DATA",
    "timestamp": 1447495523074,
    "values": {
        "processDefKey": ["LoanProcess:1:6"],
        "avgExecutionTime": 25149
    }
}, {
    "tableName": "PROCESS_USAGE_SUMMARY_DATA",
    "timestamp": 1447495523145,
    "values": {
        "processDefKey": ["SubProcess:1:18"],
        "avgExecutionTime": 54145
    }
}]


In this example you can see that it has a set of five data items which was collected from the WSO2 DAS (Data Analytics Server) analytics REST API. In order to display the dataset in a horizontal bar chart, need to connect each datum to a bar that will represent it by its length. In D3, we can achieve this by applying the data() operator on the selection of bars. Here I display average execution time of the processes against process id. Therefore before applying any D3 functionality first what I have to do here is make the data into appropriate format as follows. (The array called data is hold the above dataset)

for(var i = 0 ; i < data.length ; i++){
    dataset.push({
        "processDefKey": data[i].values.processDefKey,
        "avgExecutionTime": data[i].values.avgExecutionTime
    });


Now you can see that dataset variable holds the following JSON array.

[{
    "processDefKey": ["manualTaskProcess:1:14"],
    "avgExecutionTime": 31066
}, {
    "processDefKey": ["VacationRequest:1:22"],
    "avgExecutionTime": 16215.5
}, {
    "processDefKey": ["OrderProcess:1:10"],
    "avgExecutionTime": 54892
}, {
    "processDefKey": ["LoanProcess:1:6"],
    "avgExecutionTime": 25149
}, {
    "processDefKey": ["SubProcess:1:18"],
    "avgExecutionTime": 54145
}]
 
Now create a div element in the .html file like below to render the bar-chart.

<div class="main" style="width: 850px;height: 400px;border-style: solid">
    <h2 style="text-align: center;">Process Id VS Average execution time</h2>
</div>


Before we can add x and y axises in D3, we need to clear some space in the margins. Here margins in D3 are specified as an object with top, right, bottom and left properties (you can see it below). Then, the outer size of the bar-chart area, which includes the margins, is used to compute the inner size available for graphical region by subtracting the margins. For example, values for a 700×400 chart are:

var margins = {top: 30, right: 100, bottom: 30, left: 100};
var height = 400 - margins.left - margins.right;
var width = 700 - margins.top - margins.bottom;
var barPadding = 5;


Here barpadding variable is used to keep the space between two rectangles in the bar-chart. 700 and 400 are the outer width and height respectively, while the computed inner width and height are 630 and 200. These inner dimensions can be used to initialize scale ranges. To apply the margins to the SVG container, I set the width and height of the SVG element to the outer dimensions, and add a group (g tag in D3) element to offset the origin of the chart area by the top-left margin.

var chart = d3.select('.main')
                       .append('svg')
                       .attr('width', width + margins.left + margins.right)
                       .attr('height', height + margins.top + margins.bottom)
                       .append('g')
                    .attr('transform', 'translate(' + margins.left + ',' + margins.top + ')');


The next step is adding the x and y axises and label them for the human readability. Here, define x and y axises by binding them to the existing x-scale and y-scale declaring one of the four orientations. Since x-axis will appear below the bars, and therefore use the bottom orientation. For y axis, use the left orientation.

In the domain function we're using a helper called d3.max() and it looks at our data set and figures out what is the largest value. Here d3.max() will iterate over an entire dataset (Array) for us. 

// Create a scale for the x-axis based on data
// Domain - min and max values in the dataset
// Range - physical range of the scale


var xScale = d3.scale.linear()
               .domain([0, d3.max(dataset, function(d){
                    return d.avgExecutionTime;
                })]).range([0, width]);

// Implements the scale as an actual axis
// Orient - places the axis on the bottom of the graph
// Ticks - number of points on the axis, automated


var xAxis = d3.svg.axis()
              .scale(xScale)
              .orient('bottom')
              .ticks(10);


Here ticks(n) method will split the domain of the given axis into n number of points and show them on the axis.

// Creates a scale for the y-axis based on process definition keys

var yScale = d3.scale.ordinal()
               .domain(dataset.map(function(d){
                    return d.processDefKey;
               })).rangeRoundBands([height, 0]);

// Creates an axis based off the yScale properties


var yAxis = d3.svg.axis()
              .scale(yScale)
              .orient('left');



Now define a tooltip to show the additional informations (in this case it is average execution time) when mouse pointer move on to the particular rectangle element.

//add tooltip

var tooltip = d3.select(".main").append("div").attr("class", "d3-tip");
tooltip.append('div').attr('class', 'label');
tooltip.append('div').attr('class', 'contentBox');


The next thing is mapping data to the rectangles in bar-chart. For that we can use selectAll() method and it will select all the existing rectangle elements (in D3 we can define rectangles using "rect") on the SVG. At the beginning there is no any rect elements in the chart, but we have only data array.  when we will invoke enter() method, it will give us virtual selection. Here all the stuff after invoking enter() will execute only for the case where there is no DOM element, there is no rect but there is data element. (That means data elements are entering into the picture)


// Step 1: selectAll.data.enter.append
// Loops through the dataset and appends a rectangle for each value


chart.selectAll('rect')
     .data(dataset)
     .enter()
     .append('rect')

// Step 2: X & Y
// X - Places the bars in horizontal order, based on number of
//        points & the width of the chart
// Y - Places vertically based on scale


     .attr('x', 0)
     .attr('y', function(d){
                    return yScale(d.processDefKey);
            })

// Step 3: Height & Width
// Width - Based on barpadding and number of points in dataset
// Height - Scale using avgExecution Time and height of the chart area


     .attr('height', (height / dataset.length) - barPadding)
     .attr('width', function(d){
                    return xScale(d.avgExecutionTime);
                })
     .attr('fill', 'steelblue')

// Step 4: Info for hover interaction


     .attr('class', function(d){
                    return d.processDefKey;

                })
     .attr('id', function(d){
                    return d.avgExecutionTime;
                })
                .on("mouseover", function(d) {
                    var pos = d3.mouse(this);
                    console.log(pos);
                    tooltip.transition()
                           .duration(200)
                           .style("left", (d3.event.pageX) + "px")
                           .style("top", (d3.event.pageY - 30) + "px");
                    tooltip.select('.label').html('AVG Execution Time');
                    tooltip.select('.contentBox').html(d.avgExecutionTime + ' ms');
                    tooltip.style('display', 'block');
                })
                .on("mouseout", function() {
                    tooltip.style('display', 'none');
                });


So as the final step we can render the x axis as well as y axis once the chart is finished. To avoid the overlap with the rectangles, moves the y-axis 10 pixels left and also add the x and y axises labels as below.

// Renders the yAxis once the chart is finished
// Moves it to the left 10 pixels so it doesn't overlap


chart.append('g')
     .attr('class', 'axis')
     .attr('transform', 'translate(-10, 0)')
     .call(yAxis);

// Appends the xAxis


chart.append('g')
     .attr('class', 'axis')
     .attr('transform', 'translate(0,' + (height + 10) + ')')
     .call(xAxis);

// Adds xAxis title


chart.append('text')
     .text('AVG Execution Time (ms)')
     .attr('transform', 'translate('+(width/2 - 50)+', ' + (height + 50) + ')');

// Add yAxis title


chart.append('text')
     .text('Process Definition Key')
     .attr('transform', 'translate(-70, -20)');


Now I will show you the CSS code below and there you can see the styles which applies to the tooltip, SVG, x and y axies and div element.

.main {
       margin: 0px 25px;
}

svg {
    padding: 20px 40px;
}

.axis path,
.axis line {
      fill: none;
      stroke: black;
      shape-rendering: crispEdges;
}

text,
.axis text {
      font-size: 11px;
}

rect:hover {
      fill: orange;
}

.d3-tip {
        background: #eee;
        border-radius: 10px;
        box-shadow: 0 0 5px #999999;
        color: #333;
        display: none;
        font-size: 11px;
        left: 130px;
        padding: 12px;
        position: absolute;
        text-align: center;
        top: 95px;
        height: 20px;
        width: 100px;
        z-index: 10;
}


The resulting bar chart is now I will show you below —five bars representing the five items in our data set.



References

[1] https://medium.com/@c_behrens/enter-update-exit-6cafc6014c36#.ppi08m9d9
[2] http://www.jeromecukier.net/blog/2011/08/11/d3-scales-and-color/
[3] http://bost.ocks.org/mike/bar/3/

Saturday, November 14, 2015

Indexing and Searching through Lucene

Why Lucene in WSO2 Data Analytics Server ?

A common use-case for using Lucene indexing in Data Analytics Server (DAS) is to perform a full-text search on one or more persisted event stream data. DAS provides interactive data analysis (means it is used where a stored dataset can be queried in an ad-hoc manner in finding useful information more quickly and more accurately) for allowing you to search for persisted events using the Data Explorer .

What is Lucene ?

Lucene is an extremely rich and powerful full-text search (information retrieval) library which is written in Java. You can use Lucene to provide full-text indexing across both database objects and documents in various formats. Lucene provides search over documents. A document is essentially a collection of fields, where a field supplies a field name and value (name-value pair).

The primitive concept behind the Lucene is to take dataset and place it in fields to either be stored, indexed, or both indexed and stored. Indexed means you can search against that field, stored means you cannot search against the field but you can retrieve it’s contents. There are also non-stored and non-indexed fields but they are primarily used for the storage of metadata.

You can retrieve the dataset stored in the database, put it into fields (as name-value pair), put those fields into a "document", and then add the document to the indexing process. The index is a set of files on disk or in memory. There are multiple files contained in an an index and the files are platform independent.

Searching and Indexing through Lucene

Lucene is able to retrieve informations fast and efficiently because, instead of searching the text directly, it searches an index instead. This would be the equivalent of retrieving pages in a book related to a keyword by searching the index at the back of a book, as opposed to searching the words in each page of the book.

What actually gets indexed is a set of terms. A term (eg:- title:"Modern") combines a field name with a token that may be used for search. For instance, a title field like Modern Operating Systems, 2nd Edition might yield the tokens modern, operat, 2, and edition after case normalization, stemming and stoplisting. The index structure provides the reverse mapping from terms, consisting of field names and tokens, back to documents. This type of index is called an inverted index, because it inverts a page-centric data structure (page -> words) to a keyword-centric data structure (word -> pages). 

The following diagram shows how the indexing process happens in Lucene.
In WSO2 DAS, published events by data agents through event receivers can be persisted in RDBMS such as MySql and denormalizing the tables (RDBMS) into Lucene Documents when performing the lucene indexing.

The pseudo code will look something like this:

//The sql query to be performed
String sql = "SELECT DISTINCT processInstanceId, duration FROM PROCESS_USAGE_SUMMARY";
//ResultSet to hold the data retreived from the database  
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
    Document doc = new Document();
    doc.add(new Field("processInstanceId", rs,getString("processInstanceId"), Field.Store.YES, Field.Index.TOKENIZED));
    doc.add(new Field("duration", rs,getLong("duration"), Field.Store.YES, Field.Index.UN_TOKENIZED));
    // ... repeat for each column in result set
    writer.addDocument(doc);
}

When you perform a Search operation, it involves creating a Query (usually via a QueryParser) and handing this Query to an IndexSearcher, which returns a list of Hits. Actually this returns a set of documents according to the query you provided and from that extract the information in the documents and finally display the results. You can build the query string as the format provided in the WSO2 DAS (as a JSON string) and then pass it to its REST API  to return the result in the JSON format.

The Lucene query language allows the user to specify which field or fields to search on, which fields to give more weight, the ability to perform boolean queries (AND, OR, NOT) and other functionality as well. For more about Lucene query parser syntax click here.

References



Saturday, October 10, 2015

SPARK SQL User Defined Functions (UDFs) for WSO2 Data Analytics Server

What are UDFs ?

Generally SPARK-Sequel having some built-in functions, we can use that built-in functions in the Spark script without adding any extra code or calculation. However some times user requirement is not satisfied by that built-in functions. At that time user can write some own custom functions called UDFs and they are operate on distributed data-frames and works row by row unless you're creating an user defined aggregation function. WSO2 DAS has an abstraction layer for generic Spark UDF which makes it convenient to introduce UDFs to the server.

Here I will describe how to write Spark-Sequel UDF Example in Java.

Simple UDF to convert the date into the given date format

Step 1: Create the POJO class

The following example shows the UDF POJO for converting the date in the format of eg:Thu Sep 24 09:35:56 IST 2015 to the date in the format of yyyy-MM-dd. The name of the Spark UDF should be the name of the method defined in the class (in this example it is dateStr). This will be used when invoking the UDF through Spark-SQL. Here dateStr("Thu Sep 24 09:35:56 IST 2015") returns the String “2015-09-24”. (POJO class name: AnalyticsUDF)
















 Step 2: Packaging the class as jar

The custom UDF class you created should be bundled as a jar and added to <DAS_HOME>/repository/components/lib directory.

Step 3: Update spark UDF configuration file

Add the newly created custom UDF to the <DAS_HOME>/repository/conf/analytics/spark/spark-udf-config.xml file as shown in the example below.








(Here org.wso2.carbon.pc.spark.udfs is the package name of the class).


Saturday, October 3, 2015

BPMN data publisher in WSO2 Business Process Server

The purpose of writing this blog post is to demonstrate how to publish completed BPMN process and task instances to the WSO2 Data Analytics Server (DAS). Before moving into the configuration part of Business Process Server (BPS) to publish data, first I will give you a brief introduction about this new feature.

The execution data on process instances has to be captured for analyzing the behavior of processes. In order to facilitate this, execution data of BPMN process instances has to be published to WSO2 DAS. Once published, such data can be analyzed and presented from DAS.

This data publishing component can run independent of the process runtime and access instance data using the REST API, Java API or directly from the database. Data streams, data items included in streams, polling frequency, publishing endpoints, etc have to configurable as much as possible.

Proposed solution mainly consisted of two parts. The first step is to access the completed process and task instances data using the activiti engine JAVA API. The next step is to publish instances which grabbed from the step one to WSO2 Data Analytics Server (DAS) through a data publisher.

WSO2 Business Process Server

 

Business Process Management (BPM) is a key technology and a systematic approach to increase productivity and re-energizing businesses, making an organization's work-flow more effective, more efficient and more capable of adapting to an ever-changing environment. WSO2 Business Process Server (BPS) enables developers to easily deploy, manage and monitor business processes and process instances written using the WS-BPEL and BPMN standards through a complete web-based graphical user interface. Here a business process is an activity or set of activities that will accomplish a specific organizational goal.
 

Business Process Model Notation (BPMN)

 

BPMN is a graphical notation which describes the logic of steps in a business process. This notation has been especially designed to coordinate the sequence of processes and messages that flow between participants in different activities. The BPMN provides a common language which allows all the parties involved to communicate processes clearly, completely and efficiently. In this way, BPMN defines the notation and semantics of a Business Process Diagram (BPD).

BPD is a diagram based on the flowchart technique, designed to present a graphical sequence of all the activities that take place during a process. It also includes all relative information for making an analysis. BPD is a diagram designed for the use of process analysts who design, control and manage processes. In a BPD diagram there are a series of graphical elements that are grouped into categories.

Access instances using activiti engine JAVA API


The primary component that have to deal with when designing and developing BPMN processes with Activiti is the Activiti Engine. Here the activiti engine is the entry point to deploy new process definitions, starting new process instances, querying for process instances, user tasks which are running as well as already completed and so on. In the first part, need to capture all the completed process and task instances and for that use a in-built interface called HistoryService which provided in the JAVA API to grab the completed process instances and task instances.

The HistoryService provides an interface to query for completed process and task instances to gain the information about them such as process definition key, process instance id, start time, end time, assignee of the task, owner, claim time and etc. This service exposes mainly query capabilities to access this historic data. Before dive into the configuration part of the server let's try to identify how the historic data about process and task instances is stored inside the Activiti Engine database.

The historic process instances store in the database table called ACT_HI_PROCINST and the historic tasks store in ACT_HI_ACTINST table. A historic process instance is stored in the ACT_HI_PROCINST table when a new process instance is started. So when try to query on historic process instances will also grant results of all created process instances that are still running which don't have an end time yet. When the process instance enters its first user task state a record in the historic activity table is made. Whenever the task is finished, the record is updated with the end time of the task. When the user task is completed, the end time of the task instance is updated with the time at completion.


Data Agent

DAS data agent is used to collect data from WSO2 service-hosting products (such as WSO2 Business Process Server (BPS), WSO2 ESB, WSO2 Application Server (AS), WSO2 Data Services Server (DSS) and etc.) and send to the WSO2 DAS server. DAS server receives data events via its Thrift API. This protocol uses a binary protocol and enables fast data transmission between the service-publishing products and DAS server. Data Agent can be configured early through stream definition so that the data to be extracted from the data-publishing product can be per-defined.
 

Data Publisher


Data publisher generally allow to send data to a predefined set of data fields, to the DAS only specified in the stream definitions. This is a set of fixed data fields, which send through a data bridge. And can also send custom key-value pairs with data events. Here in this project use the thrift Data publisher and it will be sending events to the Data Bridge via thrift using the tcp transport. When starting the server the Data Receiver of the Data Bridge is exposing two thrift ports. The “Thrift SSL port” should be used for secure data transmission and the “Thrift port” for non secure data transfer. To access the secure port and send data need connect to their server with the following url format.

ssl://<Ip address for the server>:<Thrift SSL post>

E.g. ssl://10.100.7.75:7711

Data Streams

 

In the stream concept the data sender has to agree on a set of data types it wish to send in an each data event. When the message is sent to the Data Receiver, the set of types of it wish to send, is sent with the message defining the Stream. This is known as the Stream Definition. Each Stream Definition is uniquely identified using the pair of Stream Name and its Version. Data Stream can be defined in two ways. One is using a Java code, and the other way is defining a Stream as a Java string object with the format of a JSON object. In this project use the JAVA based stream definition and you can see it in the implementation phase in this report.

(Like creating tables before sending any data to store in a database, first define the streams before sending events. Here streams are description of how the sending data look like (like database Schema))

Before sending events I need to define the stream definition to send data. Data Bridge can use various Stream Definition Stores and according to the stream definition store the frequency of defining the streams varies. Below two generic streams can be provided.
    process.instance.stream:
    {
      "name": "BPMN_Process_Instance_Data_Publish",
      "version": "1.0.0",
      "nickName": "",
      "description": "BPMN process instances data",
      "payloadData": [
        {
          "name": "processDefinitionId",
          "type": "STRING"
        },
        {
          "name": "processInstanceId",
          "type": "STRING"
        },
        {
          "name": "startActivityId",
          "type": "STRING"
        },
        {
          "name": "startUserId",
          "type": "STRING"
        },
        {
          "name": "startTime",
          "type": "STRING"
        },
        {
          "name": "endTime",
          "type": "STRING"
        },
        {
          "name": "duration",
          "type": "LONG"
        },
        {
          "name": "tenantId",
          "type": "STRING"
        }
      ]
    }

    task.instance.stream:
    {
      "name": "BPMN_Task_Instance_Data_Publish",
      "version": "1.0.0",
      "nickName": "",
      "description": "BPMN user tasks data",
      "payloadData": [
        {
          "name": "taskDefinitionKey",
          "type": "STRING"
        },
        {
          "name": "taskInstanceId",
          "type": "STRING"
        },
        {
          "name": "processInstanceId",
          "type": "STRING"
        },
        {
          "name": "createTime",
          "type": "STRING"
        },
        {
          "name": "startTime",
          "type": "STRING"
        },
        {
          "name": "endTime",
          "type": "STRING"
        },
        {
          "name": "duration",
          "type": "LONG"
        },
        {
          "name": "assignee",
          "type": "STRING"
        }
      ]
    }
     


      Configuring BPMN Data publisher to publish data to the WSO2 DAS

       Step 1

      In the BPS UI console, first select the Configure tag and then go to BPMN Data Publisher. Now you can see the configuration UI for the publisher as below. Then fill the Thrift API configuration part according to the correct DAS (Data Analytics Server) instance server username password and the thrift url.




      Step 2

      To enable the data publisher for publishing events to the DAS you should have to change the value of the property called dataPublishingEnabled to true. (This configuration includes in the activiti.xml file. You can find it from the <BPS_HOME>/repository/conf folder.)

      Step 3

      After doing the first two steps restart the BPS server instance. (To avoid the port conflict with DAS, change the port offset of the BPS inside of carbon.xml file). Now in the DAS side you should have to persist the stream definitions for both task and process instances separately. You can see the fallowing output when clicking the streams menu item in DAS UI console. For enabling to store the incoming data from the BPS server, need to create two data receivers to capture process and task instances data.  




      How to configure the event receivers ??? Click Here  

      Step 4

      You can see the event flow between event receivers and the persist event store by clicking the menu item called Flow in DAS UI console as below.
        
      Step 5

      Finally you can see the sample published process and task instances through the BPMN data publisher to the data Analytics Server in the following two figures respectively.

      Sunday, June 14, 2015

      Implement a WSO2 Carbon Component using eclipse IDE

      Introduction

      This tutorial mainly focus on how to implement a WSO2 carbon component from scratch and help you to understand the structure of the project that needs to be followed  when implementing a WSO2 carbon component. I assume that you have an overall understanding about WSO2 carbon platform and how it works.

      First of all I give you a brief introduction about the award-winning WSO2 carbon platform. It is a component-based, service oriented platform for the enterprise-grade WSO2 middleware products stack. It is 100% open source and delivered under Apache License 2.0. The WSO2 Carbon platform is lean, high-performant and consists of a collection of OSGi bundles.  

      The WSO2 Carbon core platform hosts a rich set of middleware components encompassing capabilities such as security, clustering, logging, statistics, management and more. These are basic features required by all WSO2 products that are developed on top of the base platform.

      All WSO2 products are a collection of Carbon components. They have been developed simply by plugging various Carbon components that provide different features. The WSO2 Carbon component manager provides the ability to extend the Carbon base platform, by selecting the components that address your unique requirements and installing them with point-and-click simplicity. As a result, by provisioning this innovative base platform, you can develop your own, lean middleware product that has remarkable flexibility to change as business requirements change.

      Once you have the basic knowledge on how the architecture works in carbon, you can start implementing a Carbon component. Before move on to any coding stuff first look at the prerequisites that we need to implement the carbon component using eclipse IDE.

       Prerequisites
      • Java
      • Maven
      • Any WSO2 carbon product (Here I use WSO2 Application Server)
      • Eclipse (or you can use IdeaJ as well)
      Scenario

      Suppose we have a simple object called OrderBean for storing order details in the back-end component and let’s try to display those information at the front-end UI.

      Creating the Project Structure

      Now I will explain about the project structure to implement the carbon component. Here I'm going to create an Order Process carbon component using ecpilse. This will consists of two parts called back-end runtime and front-end console UI. First look at how to implement back-end runtime.

      As a first step I will create a maven project. (Before that, you should have install maven plugin to the eclipse)

      File -> New -> Other -> Maven Project (Inside of the Maven folder)


      Then click Next and you will see the fallowing UI.


      Click Next and then select the appropriate archetype to create the project structure. Here I will use default project structure. And again click Next.


      Now I will have to specify Archetype parameters for my maven project. See the fallowing figure to setup those parameters (Please change the version to 1.0.0-SNAPSHOT). And then click Finish.


      Makesure that packaging type is bundle in the pom.xml file. (Because both backend and frontend must package as OSGi bundle in carbon). I'm using maven-bundle-plugin to do that.

      <groupId>org.wso2.carbon</groupId>
      <artifactId>org.wso2.carbon.example.OrderProcess</artifactId>
      <version>1.0.0-SNAPSHOT</version>
      <packaging>bundle</packaging>
       
      This will be an OSGI bundle. So, I have to configure the Apache Felix plugin to set up the configurations.

             <build>
        <plugins>
         <plugin>
          <groupId>org.apache.felix</groupId>
          <artifactId>maven-bundle-plugin</artifactId>
          <version>1.4.0</version>
          <extensions>true</extensions>
          <configuration>
           <instructions>
            <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
            <Bundle-Name>${pom.artifactId}</Bundle-Name>
            <Export-Package>
             org.wso2.carbon.example.OrderProcess.*
            </Export-Package>
           </instructions>
          </configuration>
         </plugin>
        </plugins>
       </build>

      Since I'm using Carbon registry to store the items of the OrderBean, following dependencies should be added to the back-end project. (Remember to use byte arrays when you are storing the values in the Carbon registry)

      <dependencies>  
           <dependency>  
             <groupId>org.wso2.carbon</groupId>  
             <artifactId>org.wso2.carbon.registry.core</artifactId>  
             <version>4.2.0</version>  
           </dependency>  
           <dependency>  
             <groupId>org.wso2.carbon</groupId>  
             <artifactId>org.wso2.carbon.registry.api</artifactId>  
             <version>4.2.0</version>  
           </dependency>  
       </dependencies>  

      After adding the dependencies and the plugins, pom.xml file of the back-end will be similar to following pom. (If your project have an error then you should have to update the project such that right click the project then select Maven -> Update Project)

      (You should have to change the value of the Export-Package element in your pom.xml file according to the package structure)

      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
      
       <groupId>org.wso2.carbon</groupId>
       <artifactId>org.wso2.carbon.example.OrderProcess</artifactId>
       <version>1.0.0-SNAPSHOT</version>
       <packaging>bundle</packaging>
      
       <name>WSO2 Carbon - Order Process</name>
       <url>http://maven.apache.org</url>
      
       <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       </properties>
      
       <!-- <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> 
        <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> -->
      
       <build>
        <plugins>
         <plugin>
          <groupId>org.apache.felix</groupId>
          <artifactId>maven-bundle-plugin</artifactId>
          <version>1.4.0</version>
          <extensions>true</extensions>
          <configuration>
           <instructions>
            <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
            <Bundle-Name>${pom.artifactId}</Bundle-Name>
            <Export-Package>
             org.wso2.carbon.example.OrderProcess.*
            </Export-Package>
           </instructions>
          </configuration>
         </plugin>
        </plugins>
       </build>
      
       <dependencies>
        <dependency>
         <groupId>org.wso2.carbon</groupId>
         <artifactId>org.wso2.carbon.registry.core</artifactId>
         <version>4.2.0</version>
        </dependency>
        <dependency>
         <groupId>org.wso2.carbon</groupId>
         <artifactId>org.wso2.carbon.registry.api</artifactId>
         <version>4.2.0</version>
        </dependency>
       </dependencies>
      
       <repositories>
        <repository>
         <id>wso2-nexus</id>
         <name>WSO2 internal Repository</name>
         <url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
         <releases>
          <enabled>true</enabled>
          <updatePolicy>daily</updatePolicy>
          <checksumPolicy>ignore</checksumPolicy>
         </releases>
        </repository>
       </repositories>
      
       <pluginRepositories>
        <pluginRepository>
         <id>wso2-maven2-repository</id>
         <url>http://dist.wso2.org/maven2</url>
        </pluginRepository>
        <pluginRepository>
         <id>wso2-maven2-snapshot-repository</id>
         <url>http://dist.wso2.org/snapshots/maven2</url>
        </pluginRepository>
       </pluginRepositories>
      
      </project>
      

      Create the back-end service

      I already created a service class called ProcessOrderService inside the package org.wso2.carbon.example.OrderProcess. This service consists of two methods. One for processing the order and the other is for canceling the order.

      Before creating the service class I already created a package called org.wso2.carbon.example.OrderProcess.data to hold my data objects called OrderBean, Item, Address, Customer.

      Now I will show my OrderBean class implementation below and you will see that it implements the Serializable interface, since because I'm going to use Carbon registry to store the OrderBean objects in the carbon registry.

      package org.wso2.carbon.example.OrderProcess.data;
      
      import java.io.Serializable;
      
      public class OrderBean implements Serializable{
       private Customer customer;
       private Address shippingAddress;
       private Item[] orderItems;
       private String orderID;
       private double totalPrice;
      
       /**
        * @return customer
        */
       public Customer getCustomer() {
        return customer;
       }
      
       public void setCustomer(Customer customer) {
        this.customer = customer;
       }
      
       public Address getShippingAddress() {
        return shippingAddress;
       }
      
       public void setShippingAddress(Address shippingAddress) {
        this.shippingAddress = shippingAddress;
       }
      
       public Item[] getOrderItems() {
        return orderItems;
       }
      
       public void setOrderItems(Item[] orderItems) {
        this.orderItems = orderItems;
       }
      
       public String getOrderID() {
        return orderID;
       }
      
       public void setOrderID(String orderID) {
        this.orderID = orderID;
       }
      
       public double getPrice() {
        return totalPrice;
       }
      
       public void setPrice(double price) {
        this.totalPrice = price;
       }
      
      }

      package org.wso2.carbon.example.OrderProcess.data;
      
      import java.io.Serializable;
      
      public class Customer implements Serializable{
       private String custID;
       private String firstName;
       private String lastName;
      
       public String getCustID() {
        return custID;
       }
      
       public void setCustID(String custID) {
        this.custID = custID;
       }
      
       public String getFirstName() {
        return firstName;
       }
      
       public void setFirstName(String firstName) {
        this.firstName = firstName;
       }
      
       public String getLastName() {
        return lastName;
       }
      
       public void setLastName(String lastName) {
        this.lastName = lastName;
       }
      
      }

      package org.wso2.carbon.example.OrderProcess.data;
      
      import java.io.Serializable;
      
      public class Address implements Serializable{
       private String streetName;
       private String cityName;
       private String stateCode;
       private String country;
       private String zipCode;
      
       public String getStreetName() {
        return streetName;
       }
      
       public void setStreetName(String streetName) {
        this.streetName = streetName;
       }
      
       public String getCityName() {
        return cityName;
       }
      
       public void setCityName(String cityName) {
        this.cityName = cityName;
       }
      
       public String getStateCode() {
        return stateCode;
       }
      
       public void setStateCode(String stateCode) {
        this.stateCode = stateCode;
       }
      
       public String getCountry() {
        return country;
       }
      
       public void setCountry(String country) {
        this.country = country;
       }
      
       public String getZipCode() {
        return zipCode;
       }
      
       public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
       }
      
      }

      package org.wso2.carbon.example.OrderProcess.data;
      
      import java.io.Serializable;
      
      public class Item implements Serializable{
       private String itemName;
       private String itemID;
       private double unitPrice;
       private int quantity;
      
       public String getItemName() {
        return itemName;
       }
      
       public void setItemName(String itemName) {
        this.itemName = itemName;
       }
      
       public String getItemID() {
        return itemID;
       }
      
       public void setItemID(String itemID) {
        this.itemID = itemID;
       }
      
       public int getQuantity() {
        return quantity;
       }
      
       public void setQuantity(int quantity) {
        this.quantity = quantity;
       }
      
       public double getUnitPrice() {
           return unitPrice;
          }
      
       public void setUnitPrice(double unitPrice) {
           this.unitPrice = unitPrice;
          }
      
      }

      Now you can see my service class implementation below.

      package org.wso2.carbon.example.OrderProcess;
      
      import java.io.ByteArrayInputStream;
      import java.io.ByteArrayOutputStream;
      import java.io.IOException;
      import java.io.ObjectInputStream;
      import java.io.ObjectOutputStream;
      import java.util.ArrayList;
      import java.util.List;
      import java.util.logging.Logger;
      
      import org.wso2.carbon.context.CarbonContext;
      import org.wso2.carbon.context.RegistryType;
      import org.wso2.carbon.example.OrderProcess.data.Item;
      import org.wso2.carbon.example.OrderProcess.data.OrderBean;
      import org.wso2.carbon.registry.api.Registry;
      import org.wso2.carbon.registry.api.RegistryException;
      import org.wso2.carbon.registry.api.Resource;
      
      
      public class ProcessOrderService {
       private final static Logger LOGGER = Logger.getLogger(ProcessOrderService.class.getName());
      
       private List<OrderBean> orderList = new ArrayList<OrderBean>();
       private int orderCounter = 0;
       private double totalAmount = 0;
       private Registry registry = null;
       private static final String ORDER_PATH = "order_location";
       
       public ProcessOrderService(){
        registry = CarbonContext.getThreadLocalCarbonContext().getRegistry(RegistryType.valueOf(RegistryType.LOCAL_REPOSITORY.toString()));
       }
      
       /**
        * Acquire the order
        * 
        * @param orderBean
        * @return OrderBean object
        */
       public OrderBean processOrder(OrderBean orderBean) {
      
        // Number of items ordered
        if (orderBean.getOrderItems() != null) {
         // Set the order ID.
         orderBean.setOrderID("ABC-" + (orderCounter++));
         try {
                   Resource orderRes = registry.newResource();
                   orderRes.setContent(serialize(orderBean.getOrderItems()));  
                   registry.put(ORDER_PATH, orderRes);
                   
                   Resource getItemsRes = registry.get(ORDER_PATH);
                   Item[] items = (Item[]) deserialize((byte[]) getItemsRes.getContent());
                   
                   for (Item item : items) {
           double totalItemCost = item.getUnitPrice() * item.getQuantity();
           totalAmount += totalItemCost;
          }
                   
                   // set the total price
          orderBean.setPrice(totalAmount);
          orderList.add(orderBean);
          
                   return orderBean;
                  } catch (RegistryException e) {
                   e.printStackTrace();
                  } catch (IOException e) {
                   e.printStackTrace(); 
                  } catch (ClassNotFoundException e) {
                   e.printStackTrace();
                  }
       
        }
      
        return new OrderBean();
       }
      
       /**
        * Delete the given order
        * 
        * @param orderID
        * @return boolean to check weather order is deleted or not
        */
       public boolean cancelOrder(String orderID) {
        LOGGER.info("cancelOrder method starting");
      
        for (OrderBean orderBean : orderList) {
      
         if (orderBean.getOrderID().equals(orderID)) {
          LOGGER.info("canceling OrderBean Processing");
          orderList.remove(orderBean);
          return true;
         }
        }
      
        LOGGER.info("cancelProcssing over");
        return false;
       }
       
       private static byte[] serialize(Object obj) throws IOException {
              ByteArrayOutputStream b = new ByteArrayOutputStream();
              ObjectOutputStream o = new ObjectOutputStream(b);
              o.writeObject(obj);
              return b.toByteArray();
          }
      
          private static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
              ByteArrayInputStream b = new ByteArrayInputStream(bytes);
              ObjectInputStream o = new ObjectInputStream(b);
              return o.readObject();
          }
      }

      (If you have App.java class inside your service package please remove it. )

      Now I should have to write the service configuration (services.xml) for my service implementation. For that first create a folder called resources inside the src/main/. Then create a folder called META-INF inside the resources folder. Inside the META-INF folder create services.xml file with following content. Change the service and service class names according to your project.

      <serviceGroup>
          <service name="ProcessOrderService" scope="transportsession">
              <transports>
                  <transport>https</transport>
              </transports>
              <parameter name="ServiceClass">org.wso2.carbon.example.OrderProcess.ProcessOrderService</parameter>
          </service>
          
          <parameter name="adminService" locked="true">true</parameter>
          <parameter name="hiddenService" locked="true">true</parameter>
          <parameter name="AuthorizationAction" locked="true">/permission/admin/protected</parameter>
      </serviceGroup>

      Now go to the pom.xml file location of the back-end project using command line interface and type mvn clean install to build the project. If the build get success you will get a jar file like org.wso2.carbon.example.OrderProcess-1.0.0-SNAPSHOT.jar inside the target directory. Then copy the created jar file to repository/components/dropins directory in the WSO2 Application server. 

      We can't see the WSDL file of the created service directly accessing the url (http://192.168.1.2:9765/services/ProcessOrderService?wsdl) after running the application server. That is because I have added this as a admin service and by default admin services WSDLs are hidden. In order to view the WSDL file open the carbon.xml file in the repository/conf and set the value of HideAdminServiceWSDLs as false.

      <HideAdminServiceWSDLs>false</HideAdminServiceWSDLs>  

      Now start the WSO2 Application Server and put the above URL in the browser (last part should be the Service name that you provide in the services.xml). Save the WSDL file in your computer to use it for front-end project.

       Create the front-end console UI

       Now I will create the front-end project like above (maven project) and edit the pom.xml file as below. Inside of this pom file you can see that I've used the previously saved WSDL file. Do the necessary modifications to the pom file according to the your project.
      • org.wso2.carbon.example.OrderProcess.ui
        • artifactId - org.wso2.carbon.example.OrderProcess.ui
        • packaging - bundle
        • name - WSO2 Carbon - Order Process
        • plugin - maven-bundle-plugin
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
      
       <groupId>org.wso2.carbon</groupId>
       <artifactId>org.wso2.carbon.example.OrderProcess.ui</artifactId>
       <version>1.0.0-SNAPSHOT</version>
       <packaging>bundle</packaging>
      
       <name>WSO2 Carbon - Order Process</name>
       <url>http://maven.apache.org</url>
      
       <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       </properties>
      
       <!-- <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> 
        <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> -->
      
       <dependencies>
        <dependency>
         <groupId>org.apache.axis2.wso2</groupId>
         <artifactId>axis2</artifactId>
         <version>1.6.1.wso2v4</version>
        </dependency>
        <dependency>
         <groupId>org.apache.stratos</groupId>
         <artifactId>org.wso2.carbon.ui</artifactId>
         <version>4.2.0-stratos</version>
        </dependency>
       </dependencies>
      
       <build>
      
        <plugins>
         <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <configuration>
           <source>1.5</source>
           <target>1.5</target>
          </configuration>
         </plugin>
         <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-antrun-plugin</artifactId>
          <version>1.1</version>
          <executions>
           <execution>
            <id>source-code-generation</id>
            <phase>process-resources</phase>
            <goals>
             <goal>run</goal>
            </goals>
            <configuration>
             <tasks>
              <java classname="org.apache.axis2.wsdl.WSDL2Java" fork="true">
               <arg
                line="-uri src/main/resources/OrderProcess.wsdl -u -uw -o target/generated-code
                                          -p org.wso2.carbon.example.OrderProcess.ui
                                          -ns2p http://org.apache.axis2/xsd=org.wso2.carbon.example.OrderProcess.ui.types.axis2,http://OrderProcess.example.carbon.wso2.org=org.wso2.carbon.example.OrderProcess.ui,http://data.OrderProcess.example.carbon.wso2.org/xsd=org.wso2.carbon.example.OrderProcess.ui.types.data" />
               <classpath refid="maven.dependency.classpath" />
               <classpath refid="maven.compile.classpath" />
               <classpath refid="maven.runtime.classpath" />
              </java>
             </tasks>
            </configuration>
           </execution>
          </executions>
         </plugin>
         <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>build-helper-maven-plugin</artifactId>
          <executions>
           <execution>
            <id>add-source</id>
            <phase>generate-sources</phase>
            <goals>
             <goal>add-source</goal>
            </goals>
            <configuration>
             <sources>
              <source>target/generated-code/src</source>
             </sources>
            </configuration>
           </execution>
          </executions>
         </plugin>
         <plugin>
          <groupId>org.apache.felix</groupId>
          <artifactId>maven-bundle-plugin</artifactId>
          <version>1.4.0</version>
          <extensions>true</extensions>
          <configuration>
           <instructions>
            <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
            <Export-Package>
             org.wso2.carbon.example.OrderProcess.ui.*
            </Export-Package>
            <Import-Package>
             !javax.xml.namespace,
             javax.xml.namespace;version="0.0.0",
             *;resolution:=optional,
            </Import-Package>
            <Carbon-Component>UIBundle</Carbon-Component>
           </instructions>
          </configuration>
         </plugin>
        </plugins>
      
       </build>
      
       <repositories>
        <repository>
         <id>wso2-nexus</id>
         <name>WSO2 internal Repository</name>
         <url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
         <releases>
          <enabled>true</enabled>
          <updatePolicy>daily</updatePolicy>
          <checksumPolicy>ignore</checksumPolicy>
         </releases>
        </repository>
       </repositories>
       
       <pluginRepositories>
        <pluginRepository>
         <id>wso2-maven2-repository</id>
         <url>http://dist.wso2.org/maven2</url>
        </pluginRepository>
        <pluginRepository>
         <id>wso2-maven2-snapshot-repository</id>
         <url>http://dist.wso2.org/snapshots/maven2</url>
        </pluginRepository>
       </pluginRepositories>
       
      </project>

      Now go to the pom.xml file location of the front-end project using command line interface and type mvn compile to compile the project. (It will download the necessary dependencies and then compile the classes as well)

      As the next step I will create the Client called OrderProcessClient inside the org.wso2.carbon.example.OrderProcess.ui package, which will use the generated stub to access the back-end service which I created above.

      package org.wso2.carbon.example.OrderProcess.ui;
      
      import java.rmi.RemoteException;
      
      import org.apache.axis2.client.Options;
      import org.apache.axis2.client.ServiceClient;
      import org.apache.axis2.context.ConfigurationContext;
      import org.wso2.carbon.example.OrderProcess.ui.ProcessOrderServiceStub;
      import org.wso2.carbon.example.OrderProcess.ui.types.data.OrderBean;
      
      public class OrderProcessClient {
      
       private ProcessOrderServiceStub stub;
      
       public OrderProcessClient(ConfigurationContext configCtx, String backendServerURL,
                                   String cookie) throws Exception {
        String serviceURL = backendServerURL + "ProcessOrderService";
        stub = new ProcessOrderServiceStub(configCtx, serviceURL);
        ServiceClient client = stub._getServiceClient();
        Options options = client.getOptions();
        options.setManageSession(true);
        options.setProperty(org.apache.axis2.transport.http.HTTPConstants.COOKIE_STRING, cookie);
       }
      
       public OrderBean processOrder(OrderBean orderBean) throws Exception {
        try {
         return stub.processOrder(orderBean);
        } catch (RemoteException e) {
         String msg = "Cannot process the order" + " . Backend service may be unvailable";
         throw new Exception(msg, e);
        }
       }
      
       public boolean cancelOrder(String orderID) throws Exception {
        try {
         return stub.cancelOrder(orderID);
        } catch (RemoteException e) {
         String msg = "Cannot cancel the order" + " . Backend service may be unvailable";
         throw new Exception(msg, e);
        }
       }
      }

      Like I mentioned above in back-end project you will need to create resouces folder inside of the <folder-name>/src/main/ folder of your front-end  project. After that create a folder called web inside of the resource folder. Inside this web folder, create another directory and named it as orderprocess-mgt.

      Create a .jsp file called orderprocessmanager.jsp inside of the orderprocess-mgt directory. This is the jsp page that consist of the UI part. I will have a table of existing orders.

      <%@ page import="org.apache.axis2.context.ConfigurationContext" %>
      <%@ page import="org.wso2.carbon.CarbonConstants" %>
      <%@ page import="org.wso2.carbon.ui.CarbonUIUtil" %>
      <%@ page import="org.wso2.carbon.utils.ServerConstants" %>
      <%@ page import="org.wso2.carbon.ui.CarbonUIMessage" %>
      <%@ page import="org.wso2.carbon.example.OrderProcess.ui.OrderProcessClient" %>
      <%@ page import="org.wso2.carbon.example.OrderProcess.ui.types.data.OrderBean" %>
      <%@ page import="org.wso2.carbon.example.OrderProcess.ui.types.data.Customer" %>
      <%@ page import="org.wso2.carbon.example.OrderProcess.ui.types.data.Address" %>
      <%@ page import="org.wso2.carbon.example.OrderProcess.ui.types.data.Item" %>
      <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
      <%@ taglib uri="http://wso2.org/projects/carbon/taglibs/carbontags.jar" prefix="carbon" %>
      <%
              String serverURL = CarbonUIUtil.getServerURL(config.getServletContext(), session);
              ConfigurationContext configContext =
                      (ConfigurationContext) config.getServletContext().getAttribute(CarbonConstants.CONFIGURATION_CONTEXT);
              String cookie = (String) session.getAttribute(ServerConstants.ADMIN_SERVICE_COOKIE);
      
              OrderProcessClient client;
              OrderBean order;
              OrderBean orderBean = new OrderBean();
      
        Customer customer = new Customer();
        customer.setCustID("A123");
        customer.setFirstName("Isuru");
        customer.setLastName("Wijesinghe");
        orderBean.setCustomer(customer);
      
        Address address = new Address();
        address.setCityName("Colombo");
        address.setCountry("Sri Lanka");
        address.setStateCode("04");
        address.setStreetName("Armer Street");
        address.setZipCode("02");
        orderBean.setShippingAddress(address);
      
        Item item1 = new Item();
        item1.setItemID("11");
        item1.setItemName("MACBook");
        item1.setQuantity(12);
        item1.setUnitPrice(100);
      
        Item item2 = new Item();
        item2.setItemID("10");
        item2.setItemName("UltrasBook");
        item2.setQuantity(10);
        item2.setUnitPrice(30);
      
        Item[] orderItems = { item1, item2 };
      
        orderBean.setOrderItems(orderItems);
      
              try {
                  client = new OrderProcessClient(configContext, serverURL, cookie);
                  order = client.processOrder(orderBean);
              } catch (Exception e) {
                  CarbonUIMessage.sendCarbonUIMessage(e.getMessage(), CarbonUIMessage.ERROR, request, e);
      %>
                  <script type="text/javascript">
                         location.href = "../admin/error.jsp";
                  </script>
      <%
                  return;
          }
      %>
      
      <div id="middle">
       <h2>Order Process Management</h2>
      
          <div id="workArea">
        <table class="styledLeft" id="moduleTable">
                      <thead>
                      <tr>
                          <th width="20%">Customer ID</th>
                          <th width="20%">First Name</th>
                          <th width="20%">Last Name</th>
                          <th width="20%">Order Price</th>
                          <th width="20%">Number Of Items</th>
                      </tr>
                      </thead>
                      <tbody>
                 <%
                   
                 %>
                   <tr>
                       <td><%=order.getCustomer().getCustID()%></td>
                       <td><%=order.getCustomer().getFirstName()%></td>
                       <td><%=order.getCustomer().getLastName()%></td> 
                       <td><%=order.getPrice()%></td> 
                       <td><%=order.getOrderItems().length%></td>              
                      </tr>
                 <%
                   
                 %>
                      </tbody>
               </table>
          </div>
      </div

      Here you can see that I've used some style classes and IDs. Those are predefined classes and IDs in the Carbon. Don't forget to import the carbon tag library as well.

      Now I will have to add the UI component to the menu bar as a menu item of the application server. For that you must create the component.xml file. Befeore creating it first you should have to create META-INF inside the resources folder in front-end project and then create the component.xml file inside of it as below.

      <component xmlns="http://products.wso2.org/carbon">
          <menus>
              <menu>
                  <id>orderprocess_menu</id>
                  <i18n-key>orderprocess.menu</i18n-key>
                  <i18n-bundle>org.wso2.carbon.example.OrderProcess.ui.i18n.Resources</i18n-bundle>
                  <parent-menu>manage_menu</parent-menu>
                  <link>../orderprocess-mgt/orderprocessmanager.jsp</link>
                  <region>region1</region>
                  <order>50</order>
                  <style-class>manage</style-class>
                  <!--  --><icon>../log-admin/images/log.gif</icon>-->
                  <require-permission>/permission/protected/manage</require-permission>
              </menu>
          </menus>
      </component>

      Here i18n-bundle value depend on the package that the created Client resides. Create folder structure according to the package name inside the web folder. As an example I created the package called org.wso2.carbon.example.OrderProcess.ui to hold the client code. Therefore I must have to create a directory structure similar to the package name of the client code and inside of it create another directory called i18n. Then inside of it create a resource bundle called Resources.properties (create a empty file and named it as Resources.properties) inside the above created folder. Then update the file contend as below.

      orderprocess.menu=Order Process

      (This is similar to the i18n-key value inside of the component.xml and assign it a name and it is the menu item name in the menu bar of the application server that you can see after deploying it. Here I mentioned it as Order Process)

      Now go to the pom.xml file location of the front-end project and type maven clean install in the command line interface.

      Deploying the component


      Now you copy the generated jar files inside the target folder in both back-end  front-end projects in to the dropins folder that I mentioned previously and restart the WSO2 Application Server. Then under the Services (in the main menu tab) you can see your menu item name called Order Process. Once you click it you can see the fallowing output.