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.


2 comments:

  1. This is a very good article for any one to follow. Clearly structured and very helpful.

    ReplyDelete
  2. Thank you for a very nice article !!

    ReplyDelete