Wednesday, July 24, 2013

How to use Apache Camel with Eclipse...

What is Apache Camel?

As per its description on wikipediaApache Camel is a rule-based routing and mediation engine which provides a Java object-based implementation of the Enterprise Integration Patterns using an API (or declarative Java Domain Specific Language) to configure routing and mediation rules. The domain-specific language means that Apache Camel can support type-safe smart completion of routing rules in an integrated development environment using regular Java code without large amounts of XML configuration files, though XML configuration inside Spring is also supported.
Camel is often used with Apache ServiceMixApache ActiveMQ and Apache CXF in service-oriented architecture infrastructure projects.
It is a very useful  integration framework based on known Enterprise Integration Patterns. It is also used in Redhat's JBoss Fuse ESB (and open source ESB).

In this blog, I will introduce how we can setup Apache Camel on Eclipse IDE and run simple examples. Our example will use Camel Route builder to queue a message and then consume it.

  1. You will need to download Apache camel from its website. I have Camel v 2.10.1, however newer versions are available.
  2. Need to have Eclipse IDE.
  3. Java 6 or 7 installed.

The example I will be illustrating will use ActiveMQ for sending a message. Hence you will also need activemq-core jar. Take the latest version.
Incase you are planning to use Fuse ESB, then you can download and install Fuse ESB software. It come with activemq jars.

How Camel works with Eclipse:-

Download all the software and setup a new testCamelProj. Add Camel, activemq and other jms required jars.

We are going to use an example, where the Camel RouteBuilder will create a message and put into an activemq jms queue. Then we will use camel-stream to stream it out on console.

Write the Camel RouteBuilder

import org.apache.camel.builder.RouteBuilder;

public class TestSimpleBuilder extends RouteBuilder {
    
    
    @Override
    public void configure() throws Exception {
        // TODO Auto-generated method stub
        
        from("timer://foo?repeatCount=1")
            .setHeader("Header1", constant("Header1"))
            .setBody().simple("Test body")
        .to("jms:queue:incomingA");
                
          
        
        from("jms:queue:incomingA")
            .to("stream:out");
         
     }  
}

In the example above we are using timer to trigger off the route. Setting the header and body and sending the message to a jms queue incomingA. We are using ActiveMQ for queuing.

Then from incoming A queue, we are removing the message and sending to stream out.

Now to run the RouteBuilder

To run this route builder, I have written a simple java application that uses main method to launch it.

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.jms.JmsComponent;
import org.apache.camel.impl.DefaultCamelContext;
private static void testsimplejms(){
        
 {
            ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
            CamelContext context = new DefaultCamelContext();
            context.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
            
            
            context.addRoutes(new TestSimpleBuilder());
            
            context.start();
            Thread.sleep(10000);
            context.stop();
                        
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
    }

The code above, will create a ActiveMQConnectionFactory using vm and also create CamelContext. Then it will add the JMS component created.
Now we add our RouteBuilder to the context. And then start/stop it.

This will run the route and our simple example of putting an element in queue and taking it out.

Hope this was simple to create and run. 

Similar to Apache Camel, you could also use Spring Integration to use EIP features.

Tuesday, July 16, 2013

Oracle Sql tuning...

Tuning SQL Statements

  • Tuning SQL statements involve the following steps.
  •  Ensuring properly constructed SQL statements .
  •  Making use of the  right indexes.
  •  Use of appropriate optimizer Hints.
  •  Prudent choice of SQL Clauses
  •  Avoiding hard parse, etc.,

Introduction to the Oracle Optimize


  • Optimizer is a software component in Oracle, which tells Oracle, the best way to execute a SQL statement.
  • Oracle from versions 9i onwards, makes use of Cost Based Optimizer (CBO) as against the Rule Based Optimizer (RBO) of earlier versions.
  • CBO depends upon a set of statistic tables.
  • These tables contain information on various aspects of data distribution in the table.
  • This includes details like what percentage of the rows have the same value for a given column, null values distribution,  block related distribution, etc.,
  • These details are updated by Oracle periodically.
  • We can also update these details by using Oracle supplied packages

Updating Statistics for the Optimizer



  • Oracle automatically updates the statistics at periodic intervals as specified  by the DBA. 
  • You can also update the statistics with the following Oracle supplied packages.
EXEC dbms_stats.gather_schema_stats(’oratrng’,cascade=>TRUE);
EXEC  dbms_stats.gather_table_stats(‘oratrng’,’EMP’,cascade=>TRUE);

The statistical information gathered by the optimizer includes the following:-

Table Statistics

  • Number of rows
  • Number of blocks
  • Average row length

Column Statistics

  • Number of distinct values (NDV) in column
  • Number of nulls in column
  • Data distribution (histogram)

Index Statistics

  • Number of leaf blocks
  • Levels
  • Clustering factor

System Statistics

  • I/O performance and utilization
  • CPU performance and utilization

Tables Storing the Statistics

The following are some of the tables that store the gathered statistics.
  • USER_TABLES
  • USER_OBJECT_TABLES
  • USER_TAB_STATISTICS
  • USER_TAB_COL_STATISTICS
  • USER_TAB_HISTOGRAMS
  • USER_INDEXES
  • USER_IND_STATISTICS
  • USER_CLUSTERS
  • USER_TAB_PARTITIONS
  • USER_TAB_SUBPARTITIONS
  • USER_IND_PARTITIONS
  • USER_IND_SUBPARTITIONS
  • USER_PART_COL_STATISTICS
  • USER_PART_HISTOGRAMS
  • USER_SUBPART_COL_STATISTICS
  • USER_SUBPART_HISTOGRAMS

Querying  the Statistics

The following sample queries illustrate how to find the statistics from some of these tables.
The Optimizer is the one which will make use of this statistics.

select table_name,column_name,num_distinct 
    from user_tab_col_statistics   
    where table_name = ‘EMP’;

 select table_name, NUM_ROWS 
    from user_tables 
    where table_name in (‘EMP’, ‘DEPT’);




Monday, July 15, 2013

Using Google App Engine (GAE) to upload images and on-demand dynamic rendering of images

In this post I will be discussing about creating an application that would reside and run on Google's App engine and can be used for developing web applications that will store images in different formats and render them on demand.

For developing this web application, you would need
  1. Eclipse platform
  2. JDK ( preferably 1.7)
  3. Google's App Engine ( I am using v 1.8.1)
  4. Google Web Toolkit (GWT v 2.5.1)
  5. Maven
  6. Google GAE plugins for Eclipse ( I am using plugin v 3.6, 4.2)

Since this blog is for Advanced Java-J2EE users, hence I will not be going into details of how to setup Google's App Engine.  However resources listed below will guide you to setup GAE on Eclipse. Reading these and setting up the environment is the prerequisite for creating the application mentioned in this blog.

  • You can checkout that your environment is correctly setup by creating this "Hello World" web application. This can be done very quickly.
           http://googcloudlabs.appspot.com/codelabexercise0.html

  • Deploy the application on GAE environment
           http://googcloudlabs.appspot.com/appendix2.html

Once done with these initial tasks, you are ready to explore some advanced concepts provided by GAE. For the application we will be building for storing and retrieving images, we will be using the DataStore APIs from Datastore defined by GAE. 

As mentioned on Google's website, App Engine Datastore is a schemaless object datastore providing robust, scalable storage for your web application, with the following features:
  • No planned downtime
  • Atomic transactions
  • High availability of reads and writes
  • Strong consistency for reads and ancestor queries
  • Eventual consistency for all other queries
These features make this a highly viable option to download, process and host tons of images rather than maintain a data center by our self to achieve the same result.

Creating Web application on Eclipse


1. Right click and select "New->Web Application Project"



2. Now enter the Project Name, Package information and click Finish



You will notice that some Greeting service and related client/server classes and packages are generated. You can go ahead and delete those or keep them.

3. Now create servlet ImageStoreServlet (extends HttpServlet ). This will be used to download images using provided URLs and store them in google's datastore using Datastore APIs

Code for the servlet is as follows.

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gaetest.image.jdo.Image;
import com.gaetest.pmf.PMF;
import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;

public class ImageStoreServlet extends HttpServlet {

private static String url1 = "http://testsite.com/photos/1.jpg" ;
private static String url2 = "http://testsite.com/photos/2.jpg" ;
private static String url3 = "http://testsite.com/photos/3.jpg" ;
private static String url4 = "http://testsite.com/photos/4.jpg" ;

@Override
   public void doGet(HttpServletRequest req, HttpServletResponse resp)throws IOException 
   {
   
//create list
List<String> imageList = new ArrayList<String>();
imageList.add(url1);
imageList.add(url2);
imageList.add(url3);
imageList.add(url4);

 
  URLFetchService fetchService = URLFetchServiceFactory.getURLFetchService();
  HTTPResponse fetchResponse;
  String fetchResponseContentType = null;
  PersistenceManager pm = PMF.get().getPersistenceManager();

  try{
  int ii = 0;
  for (Iterator<String> iterator = imageList.iterator(); iterator.hasNext();) 
  {
String imageObj = (String) iterator.next();

       // Fetch the image at the location given by the url query string parameter
       fetchResponse = fetchService.fetch(new URL(imageObj));
       for (HTTPHeader header : fetchResponse.getHeaders()) {
          
           if (header.getName().equalsIgnoreCase("content-type")) {
               fetchResponseContentType = header.getValue();
               break;
           }
       }//for
       
       if (fetchResponseContentType != null) {
           // Create a new Movie instance
           Image imageJDO = new Image();
           imageJDO.setImageName("image"+ii++);
           imageJDO.setImageType(fetchResponseContentType);
           imageJDO.setImage(fetchResponse.getContent());

           // Store the image in App Engine's datastore
           pm.makePersistent(imageJDO);
           
       }//if


}//outer for
  }finally{
  pm.close();
  }
       
       


   }


}

In the above code, following observations need to be made:-
  • It is a simple HTTP servlet
  • We are using GAE URLFetchService to fetch the URL contents.
  • We are using JDO to persist the image and additional information into datastore. These and more datastore APIs can be found at  https://developers.google.com/appengine/docs/java/datastore/queries
  • Following is the code of  com.gaetest.pmf.PMF, used to return the PersistenceManager.

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;

public final class PMF {

private static final PersistenceManagerFactory pmfInstance =
   JDOHelper.getPersistenceManagerFactory("transactions-optional");

 private PMF() {}

 public static PersistenceManagerFactory get() {
   return pmfInstance;
 }

}


4. Now create GetImageServlet (extends HttpServlet ) to dynamically on demand render the image. This again uses the datastore APIs to retrieve the requested data.

import java.io.IOException;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gaetest.image.jdo.Image;
import com.gaetest.pmf.PMF;

public class GetImageServlet extends HttpServlet {

@Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException 
    {
        String imageName = req.getParameter("imageName");
        Image imageJDO = getImage(imageName);

        if (imageJDO != null && imageJDO.getImageType() != null &&  imageJDO.getImage() != null) {
            // Set the appropriate Content-Type header and write the raw bytes
            // to the response's output stream
            resp.setContentType(imageJDO.getImageType());
            resp.getOutputStream().write(imageJDO.getImage());
        } else {
            // If no image is found with the given title, redirect the user to
            // a static image
            resp.sendRedirect("/static/noimage.jpg");
        }
    }


private Image getImage(String imageName) 
{
   PersistenceManager pm = PMF.get().getPersistenceManager();


   Query query = pm.newQuery(Image.class, "imageName == imageNameParam");
   query.declareParameters("String imageNameParam");
   query.setRange(0, 1);

   try {
       List<Image> results = (List<Image>) query.execute(imageName);
       if (results.iterator().hasNext()) {
           // If the results list is non-empty, return the first (and only) result
           return results.get(0);
       }
   } finally {
       query.closeAll();
       pm.close();
   }

   return null;
}



}

Some of the observations about this code are as follows:-

  • based on the query parameter "imageName" the servlet uses JDO to retrieve image from the datastore.
5. Add following entry in your web.xml for the servlets created.

 <!-- image servlets and mappings -->
  
  <servlet>
    <servlet-name>ImageStoreServlet</servlet-name>
    <servlet-class>com.gaetest.image.servlet.ImageStoreServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>ImageStoreServlet</servlet-name>
    <url-pattern>/addImages</url-pattern>
  </servlet-mapping>
  
  <servlet>
    <servlet-name>GetImageServlet</servlet-name>
    <servlet-class>com.gaetest.image.servlet.GetImageServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>GetImageServlet</servlet-name>
    <url-pattern>/image</url-pattern>

  </servlet-mapping>


And you are done...

Now you can deploy the application on GAE using the information given above. Once deployed you can access the images using following URL

http://<yourapplicationid>.appspot.com/image?imageName=image2

Before accessing the above images, you will need to add the images. Simply run following URL, 

http://<yourapplicationid>.appspot.com/addImages

This will download and store the images defined in the servlet to your datastore.


Thanks and enjoy your new application on GAE...
In a similar way, you could write application to upload and download files or other data types using datastore. Remember datastore APIs are different from blobstore APIs offered by Google.
We will be exploring blobstore APIs someother day.. 

Wednesday, July 3, 2013

JAX-WS web service using CXF, Spring and Eclipse - uploading a file using web service (using MTOM)

This is a step by step guide to set up CXF web service using Spring. I am taking an example of using MTOM to upload file. You can use similar setup for posting requests to the webservice. This would be the most comprehensive example to setup and test webservice on the web so far. The motivation to write this article came because I could not find a step by step guide to create a web service. 

Installing Apache CXF 

Go to  Apache website (http://cxf.apache.org/download.html )and download the binary distribution.
Install it on your c: drive. I normally store it directly on my C:\ drive but you can nest it within some folder.





Linking the CXF to Eclipse.

Go to Window->Preferences and navigate down to Web Services. Now link your downloaded CXF binary to Eclipse.


















If you want to use Spring, then you should also go to the Enpoint Config tab and check that "Use Spring Application Context" is selected. You could also use CXF Servlet. This example will use Spring Application Context since we will also integrate Spring. 

While you are on this window you might want to browse across different tabs on "CXF 2.x Preferences", to get an idea of all that you can configure from here.


Install Tomcat 7.x if your eclipse does not already have one setup

Go to Apache Tomcat website ( http://tomcat.apache.org/download-70.cgi) and download binary for tomcat. I have it installed at C:\. You can install it at any sub folder.



Creating the web project and writing the web service

Create a new Dynamic Web Project, using File -> New





















If you notice in this configuration, following properties have been set:-

  • Project Name - whatever you want to call your project
  • Target Runtime - this is the runtime env for your web server. If no runtime evn is available, you can click new runtime button and select new server runtime. Select Apache Tomcat 7, since this is the one that you have downloaded in the last step. Click next and give the path of the installation directory of your tomcat.
  • Rest of the configuration on the Dynamic Web project window are as above.
  • Click finish button to create a project

Your newly created web project looks like this



Now in the Java Resources > src folder, create a java class that will contain our file upload method. The class and content look like this.












The complete code for this web service impl is as follows:-

@MTOM

@WebService(targetNamespace = "http://impl.webservice.com/", 

portName = "CXFWebServiceImplPort", 
serviceName = "CXFWebServiceImplService")
public class CXFWebServiceImpl {

public String hello(String userText){
return "Hello "+ userText;
}
@WebMethod
@Oneway
public void dataUpload(
   @XmlMimeType("application/octet-stream") DataHandler data) 
{
System.out.println("Reached dataUpload");
try {
System.out.println(data.getInputStream().toString());
data.getInputStream().close();
System.out.println("dataUpload--> end");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

You see in the code above, that there are two methods:-
  • hello - Simple web service method to recieve a String text and return back the response. 
  • dataUpload - This method is used to upload a file to the web service.
You can read about the different annotations used in this class in CXF documentation. This will help you gain better understanding of web services. I am not going to copy paste that documentation on this post.

Create bottom up web service from this java class

Right click on the class and go to  Web Service and select "Create Web service"















Web service pop up dialog will open. Configure the web service as per screen shots below.

Change the Web service runtime from Axis to Apache CXF 2.x since we are using CXF :)

No changes on this screen, click next


Since we had already annotated the dataUpload as @WebMethod, hence this comes selected in the window. You could have made that selection from here. No changes here. click next..


On this screen, select SOAP binding to SOAP 1.2. We do not want to use SOAP 1.1 anymore..

Click Finish.

Some classes and files would be generated. Tomcat would start itself. If the Tomcat starts and your files are generated, then you are good to go. 

Your setup and web service is all done...

In the generated files, you might want to check the following.


In your wsdl file you will find the URL to the wsdl. It would be 



You can test your web service by setting up SOAPUI project and providing this wsdl URL.

You can also write a JUnit Test case to test it. 

Following is the code for the same:-

public class CXFWebserviceTestCase {
QName serviceName;
QName portName;
Service service;
com.dmi.cxfws.impl.CXFWebServiceImpl_PortType client;

@BeforeClass
public static void setUpBeforeClass() throws Exception {
}

@Before
public void setUp() throws Exception {
serviceName = new QName("http://impl.webservice.com/", "CXFWebServiceImplService");
       portName = new QName("http://impl.webservice.com/", "CXFWebServiceImplPort");

       service = Service.create(serviceName);
       service.addPort(portName, SOAPBinding.SOAP12HTTP_MTOM_BINDING,"http://localhost:8080/webservicesample/services/CXFWebServiceImplPort?wsdl");
      
       client = service.getPort(portName,  com.webservice.impl.CXFWebServiceImpl_PortType.class);
            
}

@Test
public void test_uploadFile() {
DataHandler dh = new DataHandler(new FileDataSource("C:\\data\\in\\DS1.txt"));
        client.dataUpload(dh);
        System.out.println("client end....");
}


You can also setup the project as a Maven project, incase you are working on Maven and deploy is independent of Eclipse on Tomcat...
How to do that? Well, it seems you are getting lazy folks. That for some other day. Try out yourself..

And enjoy the web service implementation and do give your feed back...