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>

Monday, September 08, 2008

TIP: JAX-WS Knowing Client IP (Requester IP)

To find out the client IP (the invoker) in JAX-WS Webservice one will need to use WebServiceContext

   1: import com.sun.xml.ws.transport.Headers;
   2: import javax.annotation.Resource;
   3: import javax.jws.WebMethod;
   4: import javax.jws.WebService;
   5: import javax.xml.ws.WebServiceContext;
   6: import javax.xml.ws.handler.MessageContext; 
   7:  
   8: @WebService
   9: public class XYZService 
  10: { 
  11:  
  12:     @Resource
  13:     WebServiceContext wsContext; 
  14:  
  15:     /**
  16:      * Web service operation
  17:      */
  18:     @WebMethod(operationName = "doOperation")
  19:     public String doOperation() 
  20:     {
  21:         MessageContext mc = wsContext.getMessageContext();
  22:         HttpServletRequest req = (HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST);
  23:         String clientIP = req.getRemoteAddr();
  24:         System.out.println("Client IP = " + clientIP); 
  25:         .....
  26:     } 
  27:  
  28: }

Wednesday, September 03, 2008

Tip: Hibernate Annotations - Default Column Values

If you wanted to set the default value using hibernate annotations, you’ve probably had some difficulties, as it was the case for me. Some posts on the web talk about default values to the members of the Java class. That is, if you declare

   1: class AEntity { 
   2:  
   3:     private Integer count = 3; 
   4:  
   5:     @Column(name = "count", nullable = false) 
   6:     public Integer getCount() {
   7:         return count;
   8:     }
   9: }

you should have the default value set in the database.

Well, this does not seem to work (at least not for me). So I tried the usage of “columndefinition”. This ofcourse is database dependent, since Hibernate specifies the usage of “columndefinition” attribute for database specific declarations. The following will work well with MySQL - the database of choice for my current project:

   1: class AEntity { 
   2:  
   3:     private Integer count = 3; 
   4:  
   5:     @Column(name = "count", nullable = false, columnDefinition = "bigint(20) default 0") 
   6:     public Integer getCount() {
   7:         return count;
   8:     }
   9: }

NOTE that this is database dependent, so use it if your project is db dependent.

Another way to do it would be to set the property value in the default constructor of that entity as follows:

   1: class AEntity { 
   2:  
   3:     private Integer count; 
   4:  
   5:     public AEntity(){
   6:         count=3;
   7:     }
   8:  
   9:     @Column(name = "count", nullable = false)
  10:     public Integer getCount() {
  11:         return count;
  12:     }
  13: }

Remember though, whenever you create an instance of this entity, the property will have that default value and will need to be overwritten by calling its respective setter method.

*Source: another blog

Tuesday, August 26, 2008

Tip: How to convert Oracle BLOB to VARCHAR for temporary viewing - SQL

 

   1: SELECT
   2: utl_raw.cast_to_varchar2
   3: (
   4:     dbms_lob.substr
   5:     (
   6:         BLOB_COLUMN, dbms_lob.getLength(BLOB_COLUMN), 1
   7:     )
   8: ) BLOB_AS_VARCHAR
   9: FROM THE_TABE 

Interesting huh?...

Friday, August 01, 2008

Multi-project with Maven

-- PARENT Application Holder
mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=BrokerGateway -DartifactId=BrokerGateway -DpackageName= -Dversion=1.0

# Create a new simple project BrokerGateway inside the workspace with eclipse (From the menu bar, select File >New >Project. Select Simple >Project). Eclipse will create a simple .project-file for your BrokerGateway Project and you should be able to see the pom.xml-file.
# Delete the src-folder and open the pom.xml - file to change the packaging of your parent project to pom

  <packaging>pom</packaging>

GO INSIDE PROJECT FOLDER ON COMMAND LINE AND ISSUE THE FOLLOWING COMMANDS

-- Endpoint Module
mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=BrokerGateway.EndpointManager -DartifactId=BrokerGatewayEndpointManager -DpackageName=com.reliable.fbs.brokergateway.endpointmanager -Dversion=1.0

-- Entity Module
mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=BrokerGateway.EntityManager -DartifactId=BrokerGatewayEntityManager -DpackageName=com.reliable.fbs.brokergateway.business.entity -Dversion=1.0

-- Util Module
mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=BrokerGateway.Utils -DartifactId=BrokerGatewayUtils -DpackageName=com.reliable.fbs.brokergateway.utils -Dversion=1.0

-- Web Module
mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=BrokerGateway.Web -DartifactId=BrokerGatewayWeb -DpackageName=com.reliable.fbs.brokergateway.web -Dversion=1.0

===========================================================

# Add the newly created modules to your parent pom.

  <modules>
    <module>guide-ide-eclipse-site</module>
    <module>guide-ide-eclipse-core</module>
    <module>guide-ide-eclipse-module1</module>
  </modules>

# Add the parent to the POMs of the new modules:

  <parent>
  <groupId>BrokerGateway</groupId>
  <artifactId>BrokerGateway</artifactId>
  <version>1.0</version>
  </parent>

# Add dependencies to respective modules from module1 to the core-module:

    <dependency>
      <groupId>BrokerGateway.Utils</groupId>
      <artifactId>BrokerGatewayUtils</artifactId>
      <version>1.0</version>
    </dependency>

===========================================================

mvn install
mvn eclipse:eclipse
mvn site -- to generate the documentation website for the app

===========================================================

Check in your project using the eclipse team support (select from the context menu Team >Share Project). Note: Don not check in the generated eclipse files. If you use CVS you should have a .cvsignore-file with the following entries for each module:

---------------------------------------------
target
.classpath
.project
.wtpmodules
---------------------------------------------

Even the parent project should have this .cvsignore-file. Eclipse will automatically generate a new simple .project-file when you check out the project from the repository.

From now on you have different options to proceed. If you are working on all modules simultaneously and you rather have eclipse project dependencies than binary dependencies, you should set up a new workspace and import all projects form step-by-step/guide-ide-eclipse. Note, you have to delete the .project-file of your parent project before. The result is equals to checking out the whole project from the command line, running mvn eclipse:eclipse and finally importing the projects into your eclipse workspace. In both cases you will be able to synchronize your changes using eclipse.

In case of large projects with many people it can be quite tedious to check out all modules and keep them up to date. Especially if you are only interested in one or two modules. In this case using binary dependencies is much more comfortable. Just check out the modules you want to work on with eclipse and run mvn eclipse:eclipse for each module (see also Maven as an external tool). Of course all referenced artifacts have to be available from your maven repository.

Tip: Formatting Numbers in DisplayTag Columns

Displaytag supports easy display of formatted number columns using the format attribute on <display:column> - however, it’s not really well documented on the Displaytag site. Here’s how to do simple number formatting without requiring a decorator class:

<displaytag:column property="amount" title="$ Amount" format="{0,number,#.##}"/> 

This will display a decimal formatted to a maximum of 2 decimal places!