Saturday, October 24, 2015

How does maven work?

I do believe if you are in this page, you at least have had glimpse of what maven is and created a maven project. In a nutshell, maven helps you to manage your product builds, reporting, etc.

As you've probably heard, the magic word or words in maven is "mvn clean install". I remember when I heard of maven for the first time, experienced developers fired mvn clean install a million times. So let's have a look into what these magic word means. So this posts revolves around this magic words.

Maven works in something called life cycles. You may have heard of build life cycle in maven. By passing a few commands to maven, we basically execute one or more phases in one or more life cycles defined in maven. There are 3 built-in life cycles in maven; default, clean and site. Does this ring any bells?? Recall the magic words; "mvn clean install". Yes, the 2nd word!!! By typing the word clean, we are invoking a life cycle of the maven. I hope you got the idea.

So what does these 3 life cycles do;
  • clean: Cleaning all the generated artifacts from maven in a previous build.
  • default: Compiling, packaging, installing and deployment stuff of your project (Will look into this deeper in a bit)
  • site: Creating documentation of your project as a site.

Before proceed further, let's have a closer look at the 3 magic words; "mvn clean install". The mvn command basically invokes the maven runtime. Anything following the term mvn are the commands we passed into maven. The first command we pass into maven is clean. Which means we are telling maven to execute the clean phase of the clean life cycle. Now hold on, a new word!!! "phase". A life cycle is composed of a sequence of activities or phases. clean is a phase belong to the clean life cycle. Thus maven will execute the clean phase of the clean life cycle.

Important: maven execute activities on the sequence of the parameters fed into it. In the preceding case, since we pass clean as the first argument, maven executes clean before install.

When you build using the default life cycle, the generated class files, artifacts, documentation stuff goes in to the target directory in the maven project. So whenever you build using maven, make sure you invoke clean phase which will delete all the items in the target folder and generate everything fresh.

Now lets look at what install means. This is a phase belong to the default life cycle. We use this life cycle very often. So I'm elaborating the phases in the default life cycle;

  1.     validate
  2.     initialize
  3.     generate-sources
  4.     process-sources
  5.     generate-resources
  6.     process-resources
  7.     compile
  8.     process-classes
  9.     generate-test-sources
  10.     process-test-sources
  11.     generate-test-resources
  12.     process-test-resources
  13.     test-compile
  14.     process-test-classes
  15.     test
  16.     prepare-package
  17.     package
  18.     pre-integration-test
  19.     integration-test
  20.     post-integration-test
  21.     verify
  22.     install
  23.     deploy

Preceding illustrates 23 phases in default life cycle. Note that install phase is the 22st phase in the default life cycle. If we instruct maven to execute a phase in a life cycle, all the preceding phases prior to it gets executed. Which implicitly means a particular phase in a life cycle, depends on all the proceeding phases. In our case, when we execute install phases, all the 21 phases prior to install phase in the above list are getting executed. As you may have heard, maven manages your project build and dependencies. Thus knowing these phases could come handy.

Before concluding this post, let me elaborate 3 phases in default life cycle which you might be using extensively.
  • compile : This will compile all the classes in the project.
  • package : This is yet another phase in the default life cycle. You may have noticed that in your pom file, a tag called packaging. This tag may containing different values(i.e: jar, bundle, pom, etc). This is used by the package phase. Depending on the package type, maven decide how to package your project. If it is jar, then your classes are bundled into a jar file. There are lot more to this than what I have mentioned here. I'll elaborate more on this in a different post.
  • install : If you read this post carefully, you are aware that package phase gets executed before install phase. Once the maven artifact(the package) is generated install will go and place the artifact in the local repository.
Prior to calling any above phases, make sure to pass in clean to remove old artifacts.

What is a Local repository?

Maven deposits your build artifacts in a repository. There are local repositories which resides in your local computer. Remote repositories residing in remote servers which your project can access to download your project dependencies. install phase will make sure that the artifact you built(the jar file of your project) get deposited into the local repository.

By default, when you execute maven for the first time, a folder called .m2 is created in your user folder. This is your local repository. All the project dependencies will get downloaded into this repository so maven can compile your project. This is a storage location of your build artifacts which are yet to be published. Thus when you run maven install command on your project, it will place your project artifacts in the .m2 folder.

By default, maven is configured to use a set of predefined remote repositories containing extensively used java artifacts. If you need to access custom java artifacts (i.e: java artifacts developed in the company that you work on), then maven give you the freedom to point to remote repositories in which the required java artifacts resides.

By reading this I hope you got a clear how maven works. Feel free to give your thoughts on this.

Thursday, August 6, 2015

Changing button bar to address bar in Nautilus

Recently I got a new machine from my office and I had to install Ubuntu(14.04) on it. I am quite new to Ubuntu. Thus it took some time for me to familiarize myself with it. Coming from a windows background I was reluctant to use Ubuntu. However, now I find it really cool to work with. One thing I badly wanted is to get rid of the path bar and move to address bar, or to have both at once pretty much like in windows. I went through a lot of blog posts/forums and I figured that it is not possible to have both at once.

If somebody is wondering what am I talking about, I am talking about changing this;


to this;


This is possible to do with  Ctrl + L. However, it is not permanent. 

If you want it to be permanent you might need to switch some wires. Let's try that out;

To do this you need to install dconf. 

dconf is a low-level configuration system and settings management. Its main purpose is to provide a back-end to GSettings on platforms that don't already have configuration storage systems. It depends on GLib. It is part of GNOME 3 and is a replacement for GConf [1].

You need to install dconf-tools and update low-level configuration using dconf-editor [2]. This can be installed using Ubuntu software center or apt-get as follows;

$ sudo apt-get install dconf-tools
$ dconf-editor



dconf-editor

As per the preceding screenshot, navigate to org -> gnome -> nautils -> preferences and update the value for always-use-location-entry field.


References;

Wednesday, August 5, 2015

Writing a carbon component

What is carbon?

Most probably when you search to write a carbon component I am pretty sure you are coming here with a background knowledge about the carbon platform. Thus I will not go into details of it. 

In a nutshell carbon is the core of any WSO2 middleware product. WSO2 middleware products are built on top of Carbon core. It is based on Java OSGi technology, which allows components to be dynamically installed, started, stopped, updated and uninstalled, and it eliminates component version conflicts. [1]

What we are going to build?

We will write a simple service, which returns a collection of orders, a front end client to consume the service and display the orders. This will be done using 3 maven modules.
  1. Back end service
  2. Service stubs
  3. Frontend
We will be using Maven as our build tool. So if you do not have maven installed in your computer install maven before continue.

In order to deploy the components we create, we will be needing a WSO2 carbon product. In my case I use WSO2 AS. For the ease of development I am using intelliJ. You can use any IDE you are accustom to.

Let’s get started!!!

To begin with, let’s create the project structure. I am going to create a one maven project which will be the parent maven project for aforementioned 3 maven modules.

  •  Parent maven project
    • Order-Manager
      • groupId: org.wso2.carbon.sample.ordermanager
      • artifactId: order-manager
      • packaging: bundle
  • Sub modules
    • Back end server
      • artifactId: order-manager-service
      • packaging: bundle
    • Service stub
      • artifactId: order-manager-stub
      • packaging: bundle
    • Frontend
      • artifacatId: order-manager-client
      • packaging: bundle

    Note: The sole purpose of parent maven project is to aggregate the 3 sub modules. If you are creating this from an IDE, you will get src folder for this project which provide no purpose. So you can delete it and continue. In addition, these names are arbitrary names I came up with. You have the liberty of choosing your own naming for these projects. If so make sure you do the necessary code changes accordingly.

    If you are creating these projects/modules from an IDE, the pom files of each module will point the parent as the Order-Manager project and pom.xml of Order-Manager will contain all 3 sub modules. You might need to update all 4 pom files otherwise.

    If you reach up to here you will see your intelliJ project view as follows;

    figure 1 - project structure



















    Now its time to give attention to each project one at a time.

    Order-Manager

    So lets start from the Order-Manager project. There is nothing left for you to do if you use an IDE. I am just illustrating my pom file. Cross check against your parent project's pom file.

     <?xml version="1.0" encoding="UTF-8"?>  
     <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.sample.ordermanager</groupId>  
       <artifactId>order-manager</artifactId>  
       <packaging>pom</packaging>  
       <version>1.0-SNAPSHOT</version>  
       <modules>  
         <module>order-manager-service</module>  
         <module>order-manager-stub</module>  
         <module>order-manager-client</module>  
       </modules>  
     </project>  
    
    snippet 1 - pom.xml for order-manager project

    order-manager-service

    Next lets move to order-manager-server project. Here we create a service and bundle it as an OSGi component and deploy it in WSO2 Application server.

    figure 2 - order-manager-service project structure















    I have written this simple service to fetch 2 orders which is added programmatically. Feel free to come up with your own architecture of the service.

     package org.wso2.carbon.sample.ordermanager.service.beans;  
     /**  
      * Created by dinushab on 8/2/15.  
      */  
     public class Item {  
       private String itemName;  
       private int itemPrice;  
       private int quantity;  
    
       public Item() {  
       }  
    
       public Item(String name, int price, int quantity) {  
         this.itemName = name;  
         this.itemPrice = price;  
         this.quantity = quantity;  
       }  
    
       public String getItemName() {  
         return itemName;  
       }  
    
       public void setItemName(String itemName) {  
         this.itemName = itemName;  
       }  
    
       public int getItemPrice() {  
         return itemPrice;  
       }  
    
       public void setItemPrice(int itemPrice) {  
         this.itemPrice = itemPrice;  
       }  
    
       public int getQuantity() {  
         return quantity;  
       }  
    
       public void setQuantity(int quantity) {  
         this.quantity = quantity;  
       }  
     }
    
    snippet 2 - Item.java


     package org.wso2.carbon.sample.ordermanager.service.beans;  
     /**  
      * Created by dinushab on 8/2/15.  
      */  
     public class Order {  
    
       private int orderId;  
       private Item[] items;  
    
       public int getOrderId() {  
         return orderId;  
       } 
     
       public void setOrderId(int orderId) {  
         this.orderId = orderId;  
       } 
     
       public Item[] getItems() {  
         return items;  
       }  
    
       public void setItems(Item[] items) {  
         this.items = items;  
       }
      
       public int getTotalCost() {  
         int totalCost = 0;  
         for (Item item : items) {  
           totalCost += item.getQuantity() * item.getItemPrice();  
         }  
         return totalCost;  
       }  
     }  
    snippet 3 - Order.java


     package org.wso2.carbon.sample.ordermanager.service;  
     import org.wso2.carbon.sample.ordermanager.service.beans.Item;  
     import org.wso2.carbon.sample.ordermanager.service.beans.Order;  
     import java.util.Collection;  
     import java.util.HashMap;  
     /**  
      * Created by dinushab on 8/2/15.  
      */  
     public class OrderManagerService {  
    
       private static HashMap<Integer, Order> orders = new HashMap<Integer, Order>();  
       private static final String LINE_SEPARATOR = System.getProperty("line.separator");  
    
       static {  
         Order order1 = new Order();  
         order1.setOrderId(1);  
         order1.setItems(getSampleItems());  
         orders.put(1, order1);  
         Order order2 = new Order();  
         order2.setOrderId(2);  
         order2.setItems(getSampleItems2());  
         orders.put(2, order2);  
       }  
    
       public OrderManagerService() {  
       } 
     
       /**  
        * Add a new Order  
        *  
        * @param newOrder  
        *      Order  
        * @return String message saying whether add order was successful or not.  
        */  
       public String addOrder(Order newOrder) {  
         String responseMsg;  
         if (orders.containsKey(newOrder.getOrderId())) {  
           responseMsg = "Order already added";  
         } else {  
           orders.put(newOrder.getOrderId(), newOrder);  
           responseMsg = "Order successfully added";  
         }  
         return responseMsg;  
       }  
    
       /**  
        * Return the order for the given order Id. For the moment the scenario of  
        * not having order for a given order id is not handled.  
        *  
        * @param orderId  
        *      int  
        * @return Order  
        */  
       public Order getOrder(int orderId) {  
         return orders.get(orderId);  
       }  
    
       /**  
        * Returns the order summary string.  
        *  
        * @param orderId  
        *      int  
        * @return String  
        */  
       public String getOrderSummary(int orderId) {  
         if (!orders.containsKey(orderId)) {  
           return "Order not found";  
         }  
         Order order = orders.get(orderId);  
         StringBuffer buffer = new StringBuffer();  
         buffer.append("*****************************************************" + LINE_SEPARATOR);  
         buffer.append("Your order number is : " + orderId + LINE_SEPARATOR);  
         buffer.append("Total cost for your order is : " + order.getTotalCost() + LINE_SEPARATOR);  
         buffer.append("*****************************************************");  
         return buffer.toString();  
       }  
    
       /**  
        * Return all orders added to the service.  
        *  
        * @return Collection<Order>  
        */  
       public Collection<Order> getOrders() {  
         return orders.values();  
       }  
    
       private static Item[] getSampleItems() {  
         Item item1 = new Item("Bat", 4500, 3);  
         Item item2 = new Item("Pads", 5000, 2);  
         Item[] items = new Item[2];  
         items[0] = item1;  
         items[1] = item2;  
         return items;  
       }  
    
       private static Item[] getSampleItems2() {  
         Item item1 = new Item("Monitor", 15000, 3 );  
         Item item2 = new Item("Keyboard", 500, 4);  
         Item item3 = new Item("Mouse", 350, 4);  
         Item[] items = new Item[3];  
         items[0] = item1;  
         items[1] = item2;  
         items[2] = item3;  
         return items;  
       }  
     }  
    
    snippet 4 - OrderManagerService.java


    After completion of writing the service logic, we need to add the configuration file which tells the OSGi container what is the service we are exposing and what is the service implementation class and associated meta-data with it. For that we introduce the services.xml file inside src/main/resources/META-INF folder.


     <serviceGroup>  
       <service name="OrderService" scope="transportsession">  
         <transports>  
           <transport>https</transport>  
         </transports>  
         <parameter name="ServiceClass">org.wso2.carbon.sample.ordermanager.service.OrderManagerService</parameter>  
       </service>  
       <parameter name="adminService" locked="true">true</parameter>  
       <parameter name="hiddenService" locked="true">true</parameter>  
       <parameter name="AuthorizationAction" locked="true">/permission/protected/manage</parameter>  
     </serviceGroup>  
    
    snippet 5 -services.xml

    Important:
    • In services.xml file the service tag defines the service we expose. The name attribute defines the name of the service. We will be using this service name when we develop the client.
    • Inside service tag, we specify a special parameter tag having the name attribute as ServiceClass. This is used to point the fully qualified class name of the service implementation.
    Now we have completed all the necessary java classes and configuration files to our order manager service. In order to build it as an OSGi bundle, lets look at the pom.xml;


     <?xml version="1.0" encoding="UTF-8"?>  
     <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">  
       <parent>  
         <artifactId>order-manager</artifactId>  
         <groupId>org.wso2.carbon.sample.ordermanager</groupId>  
         <version>1.0-SNAPSHOT</version>  
       </parent>  
       <modelVersion>4.0.0</modelVersion>  
       <artifactId>order-manager-service</artifactId>  
       <packaging>bundle</packaging>  
       <build>  
         <plugins>  
           <plugin>  
             <groupId>org.apache.felix</groupId>  
             <artifactId>maven-bundle-plugin</artifactId>  
             <extensions>true</extensions>  
             <configuration>  
               <instructions>  
                 <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>  
                 <Bundle-Name>${pom.artifactId}</Bundle-Name>  
                 <Export-Package>org.wso2.carbon.sample.ordermanager.service.*</Export-Package>  
               </instructions>  
             </configuration>  
           </plugin>  
         </plugins>  
       </build>  
     </project>  
    
    snippet 6 - pom.xml for order-manager-service project

    Did you notice the value for packaging tag? Yes it is marked as bundle. This is because we need to bundle it as an OSGi bundle. To do this we use a plugin called maven-bundle-plugin. Recall your knowledge in OSGi bundles, we need to mark the packages that we expose from the bundle. For that we have specified Export-Package inside the plugin configuration. Otherwise our service classes will not be exposed to OSGi container leaving our service bundle useless.

    Now navigate to root level of your order-manager-service project(where your pom.xml resides) in terminal and execute the following command mvn package. This will create the bundle inside the target folder of the project. (You can do the same thing using the maven plugin of your favorite IDE). You can see the order-manager-service-1.0-SNAPSHOT.jar created in the target directory of order-manager-service project. The name of the jar file may vary depending on the naming that you used.

    Deploying the service

    Now that we have created the service as a bundle, its time to deploy this inside one of WSO2's carbon product.  In order to do that, open up the carbon product you downloaded(I will refer to the root directory of the carbon product as <carbon_home>) and copy the service bundle you created in to <carbon_home>/repository/components/dropins directory. 

    order-manager-stub

    Now that we have deployed the service in the WSO2 AS, we need the wsdl of the service to generate the client stub. However, by default the carbon product does not allow you to get the wsdl of a service because you have a secure connection. So you need to do some setting changes to get this. Open up <carbon_home>/repository/carbon.xml and change the value of <HideAdminServiceWSDLs> from true to false.

    Now start the carbon product and go to https://localhost:9443/services/OrderService?wsdl to get the wsdl.

    Save the wsdl in order-manager-stub/src/main/resources/wsdl folder. Revert the change you did in carbon.xml file.

    We need to update the pom.xml in order-manager-stub as follows;

     <?xml version="1.0" encoding="UTF-8"?>  
     <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">  
       <parent>  
         <artifactId>order-manager</artifactId>  
         <groupId>org.wso2.carbon.sample.ordermanager</groupId>  
         <version>1.0-SNAPSHOT</version>  
       </parent>  
       <modelVersion>4.0.0</modelVersion>  
       <artifactId>order-manager-stub</artifactId>  
       <packaging>bundle</packaging> 
    
       <dependencies>  
         <dependency>  
           <groupId>org.apache.axis2.wso2</groupId>  
           <artifactId>axis2</artifactId>  
           <version>1.6.1.wso2v10</version>  
         </dependency>  
         <dependency>  
           <groupId>org.apache.ws.commons.axiom.wso2</groupId>  
           <artifactId>axiom</artifactId>  
           <version>1.2.11.wso2v4</version>  
         </dependency>  
         <dependency>  
           <groupId>wsdl4j.wso2</groupId>  
           <artifactId>wsdl4j</artifactId>  
           <version>1.6.2.wso2v4</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>  
    
       <build>  
         <plugins>  
           <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>  
                     <path id="wsdl2java.classpath">  
                       <pathelement location="${settings.localRepository}/org/apache/ws/commons/axiom/wso2/axiom/1.2.11.wso2v4/axiom-1.2.11.wso2v4.jar"/>  
                       <pathelement location="${settings.localRepository}/org/apache/axis2/wso2/axis2-client/1.6.1.wso2v10/axis2-client-1.6.1.wso2v10.jar" />  
                       <pathelement location="${settings.localRepository}/org/apache/axis2/wso2/axis2/1.6.1.wso2v10/axis2-1.6.1.wso2v10.jar" />  
                     </path>  
                     <java classname="org.apache.axis2.wsdl.WSDL2Java" fork="true">  
                       <classpath refid="wsdl2java.classpath" />  
                       <arg line="-uri src/main/resources/wsdl/OrderService.wsdl -u -uw  
                        -o target/generated-code -p org.wso2.carbon.sample.ordermanager.stub"/>  
                     </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>  
             <extensions>true</extensions>  
             <configuration>  
               <instructions>  
                 <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>  
                 <Bundle-Name>${project.artifactId}</Bundle-Name>  
                 <Private-Package>  
                 </Private-Package>  
                 <Export-Package>  
                   org.wso2.carbon.sample.ordermanager.*  
                 </Export-Package>  
                 <Import-Package>  
                   !org.wso2.carbon.sample.ordermanager.*  
                 </Import-Package>  
                 <DynamicImport-Package>*</DynamicImport-Package>  
               </instructions>  
             </configuration>  
           </plugin>  
         </plugins>  
       </build>  
     </project>  
    

    snippet 7 - pom.xml of order-manager-stub project

    Few things to note in this pom file are;
    • Dependencies added for code generation
    • Remote repository to access those dependencies
    • If you use different naming for your project, make sure you point to the correct path for the wsdl file through the -uri switch and give the proper package through -p switch under the arguments for the maven-antrun-plugin.
    • maven plugin to generate source code from the wsdl file.
    • update the Export-Package and Import-Package tags for maven-bundle-plugin accordingly
    Execute mvn install command. This will generate source code from the wsdl, compile it, package it and install it in the local .m2 repository. That is all you need to do in order-manager-stub project.

    order-manager-client

    Finally we need to create a client to consume the service we created. Project structure of order-manager-client;
    figure 3 - order-manager-client project structure
















    The Client.java class will consume the stub generated in order-manager-stub project.

     package org.wso2.carbon.sample.ordermanager.client;  
     import org.apache.axis2.AxisFault;  
     import org.apache.axis2.client.Options;  
     import org.apache.axis2.client.ServiceClient;  
     import org.apache.axis2.context.ConfigurationContext;  
     import org.apache.axis2.transport.http.HTTPConstants;  
     import org.wso2.carbon.sample.ordermanager.service.beans.xsd.Order;  
     import org.wso2.carbon.sample.ordermanager.stub.OrderServiceStub;  
     import java.rmi.RemoteException;  
     /**  
      * Created by dinushab on 8/2/15.  
      */  
     public class Client {  
       OrderServiceStub stub;  
    
       public Client(ConfigurationContext ctx, String backendServerUrl, String cookie) throws AxisFault {  
         String serviceUrl = backendServerUrl + "OrderService";  
         stub = new OrderServiceStub(ctx, serviceUrl);  
         ServiceClient serviceClient = stub._getServiceClient();  
         Options options = serviceClient.getOptions();  
         options.setManageSession(true);  
         options.setProperty(HTTPConstants.COOKIE_STRING, cookie);  
       }  
    
       public String getOrderSummary(int orderId) throws RemoteException {  
         return stub.getOrderSummary(orderId);  
       }  
    
       public Order[] getOrders() throws RemoteException {  
         return stub.getOrders();  
       }  
     }  
    
    Snippet 8 - Client.java

    This class will merely access the stub and call the getOrders method which will return the 2 orders we have added programmatically in our service class code.

    Again, if you use different nameing for your project, make sure to change the OrderService text to the correct service name which you created.

    The client will be accessible through the management console of your carbon product through a menu item. In order to do that we need give the configuration to the carbon product as to where to show the link and which jsp file to render in the browser so the user can consume the service. We do this from component.xml. The component.xml resides in src/main/resources/META-INF directory of your client project (refer figure 3).


     <component xmlns="http://products.wso2.org/carbon">  
       <menus>  
         <menu>  
           <id>order_manager_menu</id>  
           <i18n-key>order.manager.menu</i18n-key>  
           <i18n-bundle>org.wso2.carbon.sample.ordermanager.ui.i18n.Resources</i18n-bundle>  
           <parent-menu>manage_menu</parent-menu>  
           <link>../ordermanager/index.jsp</link>  
           <region>region1</region>  
           <order>50</order>  
           <style-class>manage</style-class>  
           <require-permission>/permission/protected/manage</require-permission>  
         </menu>  
       </menus>  
     </component>  
    
    Snippet 9 - component.xml

    i18n-key is the i18n key for the menu text which will be shown in the front end. The value for this key is picked up from org/wso2.carbon/sample/ordermanager/ui/i18n/Resources.properties file. Note that we specify only the name of the file without the extension.

    order.manager.menu = Order Service
    Snippet 10 - Resources.properties

    link tag in component.xml points to the jsp which will be rendered when the user clicks on the menu item. The jsp file needs to be placed inside order-manager-client/src/main/resources/web/ordermanager/index.jsp. The main point is this file should be in any sub directory under order-manager-client/src/main/resources/web directory and point to it properly inside link tag.


      <%@ 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.sample.ordermanager.client.Client" %>  
      <%@ page import="org.wso2.carbon.sample.ordermanager.service.beans.xsd.Order" %>  
      <%@ page import="org.wso2.carbon.sample.ordermanager.service.beans.xsd.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);  
       Order[] orders = null;  
        try {  
         Client client = new Client(configContext, serverURL, cookie);  
         orders = client.getOrders();  
        } catch (Exception e) {  
         e.printStackTrace();  
        }  
      %>  
      <div id="middle">  
       <h2>Order Manager</h2>  
       <div id="workArea">  
       <%  
         if(orders != null) {  
       %>  
        <%  
            for(Order order:orders){  
        %>  
         <br />  
           <b><span style="padding-top: 5px;padding-bottom: 2px;">Order Id: <%= order.getOrderId() %> <span></b>  
         <br />  
           <table class="styledLeft" id="moduleTable">  
               <thead>  
               <tr>  
                 <th width="30%">Name</th>  
                 <th width="20%">Price</th>  
                 <th width="20%">Quantity</th>  
                 <th width="20%">Total</th>  
               </tr>  
               </thead>  
               <tbody>  
             <%  
                 for(Item item:order.getItems()){  
             %>  
                 <tr>  
                   <td><%=item.getItemName()%></td>  
                   <td>Rs. <%=item.getItemPrice()%></td>  
                   <td><%=item.getQuantity()%></td>  
                   <td>Rs. <%=(item.getQuantity()*item.getItemPrice())%></td>  
               </tr>  
             <%  
                 }  
             %>  
               </tbody>  
            </table>  
         <%  
             }  
         %>  
       <%  
         }  
       %>  
       </div>  
      </div>  
    
    Snippet 11 - index.jsp

    The index.jsp accesses the Client.java and calls the getOrders method. The jsp takes care of rendering 2 orders in a table. This is a simple example to show how the carbon components work. You can add additional operations and extend this service and the client as you wish.


     <?xml version="1.0" encoding="UTF-8"?>  
     <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">  
       <parent>  
         <artifactId>order-manager</artifactId>  
         <groupId>org.wso2.carbon.sample.ordermanager</groupId>  
         <version>1.0-SNAPSHOT</version>  
       </parent>  
       <modelVersion>4.0.0</modelVersion>  
       <artifactId>order-manager-client</artifactId>  
       <packaging>bundle</packaging>  
       <dependencies>  
         <dependency>  
           <groupId>org.wso2.carbon.sample.ordermanager</groupId>  
           <artifactId>order-manager-stub</artifactId>  
           <version>1.0-SNAPSHOT</version>  
         </dependency>  
       </dependencies>  
       <build>  
         <plugins>  
           <plugin>  
             <groupId>org.apache.felix</groupId>  
             <artifactId>maven-bundle-plugin</artifactId>  
             <extensions>true</extensions>  
             <configuration>  
               <instructions>  
                 <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>  
                 <Bundle-Name>${project.artifactId}</Bundle-Name>  
                 <Export-Package>  
                   org.wso2.carbon.sample.ordermanager.*  
                 </Export-Package>  
                 <Import-Package> 
                   *;resolution:=optional  
                 </Import-Package>  
                 <Carbon-Component>UIBundle</Carbon-Component>  
               </instructions>  
             </configuration>  
           </plugin>  
         </plugins>  
       </build>  
     </project>  
    
    Snippet 12 - pom.xml of order-manager-client project

    Note the dependency in the preceding pom.xml. It references the order-manager-stub project. This will be taken from the .m2 repository. Now run mvn package command to generate the bundle and copy it to the <carbon_home>/repository/components/dropins directory and restart the carbon product.

    Notice the Order Service menu item in the left side panel. Clicking it will lead you to figure 4.

    figure 4 - carbon product management console

    References

    [1] - https://en.wikipedia.org/wiki/WSO2_Carbon

    Why should you use react JS?

    Tired of choosing a proper framework to write your web application? This is a common question that most developers get stuck when the...