Thursday, August 06, 2009

BTrace – A dynamic trace tool for Java platform

BTrace (where the ‘B’ stands for bytecode) is an open source tool hosted on java.net, where you can find extensive documentation and samples. It is conceptually similar to the much-talked-about Solaris DTrace platform, but can be used on any Java platform/app.

The main BTrace concept is that of dynamically connecting to a running Java application (or server) to attach short “scripts” which log a range of events and infos such as

  • method calls;
  • execution times;
  • constructor invocation;
  • available memory;

In a way, BTrace scripts are very similar to AOP’s aspects, but can be attached to any existing Java code (or better, bytecode) at runtime and without any configuration or modification at development time.

Script execution is tied to several situations

  • reaching a specific line number;
  • invoking a given method;
  • returning from a method;
  • invoking system calls (e.g. exit);
  • recurring timer (period execution at fixed intervals);
  • and many more

The scripts are simply Java classes which take advantage of methods from the btrace API, and are configured by using simple but powerful annotations. Here you are an hello world script which traces session creation in hibernate:

   1: // import BTrace annotations
   2: import com.sun.btrace.annotations.*;
   3: // import logging methods
   4: import static com.sun.btrace.BTraceUtils.*;
   5:  
   6: @BTrace
   7: public class DemoAppTrace 
   8: {
   9:     // store the entry time in this thread local
  10:     @TLS private static long startTime;
  11:  
  12:     // probe the openSession() method of Hibernate SessionFactory
  13:     @OnMethod(clazz=”org.hibernate.SessionFactory”,    method=”openSession”)
  14:     public static void onOpenTrace() 
  15:     {
  16:         // you can only log using the static println method from BTraceUtils
  17:         println(”Hibernate: opening a new session…”);
  18:         
  19:         // the BTrace built-in strcat function is needed to avoid the overhead of string concatenation
  20:         println(strcat(strcat(name(probeClass()), "."), probeMethod()));
  21:         startTime = timeMillis();
  22:     }
  23:  
  24:     // probe the completion of openSession() method 
  25:     // the Kind.RTURN tell the BTrace to probe the end of the method execution 
  26:     @OnMethod(clazz=”org.hibernate.SessionFactory”,    method=”openSession”, location=@Location(Kind.RETURN))
  27:     public static void onReturnTrace() 
  28:     {
  29:         // the BTrace built-in strcat function is needed/used to avoid the overhead of string concatenation
  30:         println(strcat("Time taken (msec) ", str(timeMillis() - startTime)));
  31:     }
  32: }

How to run – as explained in their documentation:

Steps to run BTrace
  1. Find the process id of the target Java process that you want to trace. You can use jps tool to find the pid.
  2. Write a BTrace program - you may want to start modifying one of the samples.
  3. Run btrace tool by the following command line:
       btrace <pid> <btrace-script>
BTrace Command Line
BTrace is run using the command line tool btrace as shown below:
    btrace [-p <port>] [-cp <path>] <pid> <btrace-script> [<args>]
where
  • pid is the process id of the traced Java program
  • btrace-script is the trace program. If it is a ".java", then it is compiled before submission. Or else, it is assumed to be pre-compiled [i.e., it has to be a .class] and submitted.
optional
  • port is the server socket port at which BTrace agent listens for clients. Default is 2020.
  • path is the classpath used for compiling BTrace program. Default is ".".
  • args is command line arguments passed to BTrace program. BTrace program can access these using the built-in functions "$" and "$length".

Tuesday, April 07, 2009

EclEmma - Java Code coverage for Eclipse

This one is indeed handy to have in your Eclipse. It is a complete code-coverage tool. Run your JUnit tests with this plug-in instead of straight JUnit, and it'll let you know where your tests don't hit.

http://www.eclemma.org/

It's also pretty easy to use. When a coverage report is desired, run the appropriate JUnit test by using the new Coverage menu or context menu: coverage as...JUnit test. JUnit will run as normal, and when done, a coverage report will be generated, and the source will be highlighted showing the test coverage.

The coverage report and highlighting are configurable. Personally, I turn off the coverage of my test source (or it's incorrectly shown as not being tested), and I turn off the highlighting of covered lines leaving only the uncovered lines highlighted. The first requires a trip to the larger coverage dialog (open the Coverage as... dialog from the coverage button or menu). The second is in the editor formatting under Windows Preferences –> General –> Editors –> Text Editors –> Annotations –> Full Coverage. (Phew!!) Easy.

Now it's easy to tell what isn't tested with no noticeable difference in test run time.

Servlets testing using JUnit

Although this has been written by many and available on the net, I thought of sharing this anyways to make it easily available through google search for the people looking of this.

In one of my applications, we had written a servlet wrapper to existing Web Services to accept and convert the Web Service output as a JSON strings.

To test the functionality of the servlet proxy, of course, we had used commons httpclient library.

   1: HttpClient httpclient = new HttpClient();
   2: PostMethod httpPost = new PostMethod(baseUrl + "/ProxyClient");
   3: System.out.println("Testing Authentication - Executing request " + httpPost.getURI());
   4:  
   5: Map<String, String> map = new HashMap<String, String>();
   6:  
   7: map.put(JSONConstants.operation, JSONConstants.OPERATION_AUTHENTICATE);
   8: map.put(JSONConstants.userId, "ravi");
   9: map.put(JSONConstants.password, "ffss123");
  10: map.put(JSONConstants.imeiNo, "12345566");
  11: map.put(JSONConstants.pdaVersion, "3.1");
  12:  
  13: JSONObject jsonObject = JSONObject.fromObject(map);
  14:  
  15: NameValuePair[] data = { new NameValuePair("q", jsonObject.toString()) };
  16:  
  17: httpPost.setRequestBody(data);
  18:  
  19: httpclient.executeMethod(httpPost);
  20: responseBody = httpPost.getResponseBodyAsString();
  21: System.out.println("RESPONSE : " + responseBody);

Listing: 1

We actually wanted to write a JUnit test case for testing the various JSON service calls made to this servlet proxy.  After some searching we found that the Jetty servlet-container has a ServletTester class just for this purpose.

In our maven project we included the ServletTester using the following dependency information. If however, you don't use Maven, you will need to manually download all of the dependencies.

   1:  <dependency>
   2:    <groupId>org.mortbay.jetty</groupId>
   3:    <artifactId>jetty-servlet-tester</artifactId>
   4:    <version>6.1.6</version>
   5:    <scope>test</scope>
   6:  </dependency>

Listing: 2

With this in place the next step was writing the JUnit test cases. We wanted to initialise the servlet-container just once, then run a set of tests against it. In JUnit 4 you can use the @BeforeClass and @AfterClass annotations to mark methods that should be executed before and after all of the tests.

   1: public class TestJSON
   2: {
   3:     
   4:     private static ServletTester tester;
   5:     
   6:     private static String baseUrl;
   7:     
   8:     /**
   9:      * This kicks off an instance of the Jetty
  10:      * servlet container so that we can hit it.
  11:      * We register an echo service that simply
  12:      * returns the parameters passed to it.
  13:      */
  14:     @BeforeClass
  15:     public static void initServletContainer () throws Exception
  16:     {
  17:         tester = new ServletTester();
  18:         tester.setContextPath("/");
  19:         tester.addServlet(ProxyClient.class, "/ProxyClient");
  20:         baseUrl = tester.createSocketConnector(true); // This makes the jetty to bind the servlet container to a 
  21:                                                       // higher port value dynamically. Hence we need to retain 
  22:                                                       // the baseUrl reference to be used in our test methods.
  23:         tester.start();
  24:     }
  25:  
  26:     /**
  27:      * Stops the Jetty container.
  28:      */
  29:     @AfterClass
  30:     public static void cleanupServletContainer () throws Exception
  31:     {
  32:         tester.stop();
  33:     }
  34: }

Listing: 3

Now all we had to do is wrap the test code in Listing: 1 in a method and annotate it with @Test. And we were able to run the tests out-of-container along with other tests.

If you want to more comprehensively test your servlets and other JEE stuff then the following is a list of a few unit testing libraries that will help you a lot to make it easier.

1. Jakarta Cactus
2. Spring-Mock
3. HttpUnit

Tuesday, January 20, 2009

Tip: Single Session Control - Spring Security

If anyone wants to apply Single Session Control to logged in user do the following steps.


1) in web.xml add a listner.

 
   1:  <listener>
   2:      <listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>    
   3:  </listener>

2)In Spring security configuration
   1:  <http>
   2:      ...
   3:      <concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true"/>
   4:  </http>