Sunday, December 26, 2010

Play with your byte-code using Javassist

I came to know about this nice tool named javassist which is a cool java byte code manipulation tool.It provides users with a very easy to use API to modify / create java classes in the Runtime. It provides some API to do that using a Java like syntax so that we can easily hack the byte code without knowing any thing in-depth about the byte code structure.

In this blog post I'll explain you a simple example on how to use this tool.This will show how we can use javassist to change the byte code of a compiled class to change a method implementation in Runtime.

Step 1

Step 2

Create a new directory and copy javassist.jar to that directory.

Step 3

Create Two java source file named HelloWorld.java and ByteCodeInjector.java in that directry

HelloWorld.java


public class HelloWorld {


public static void main(String[] args) {
new HelloWorld().sayHello();
}

public void sayHello(){
System.out.println("Hello!!! This is the original version!!!");
}
}


ByteCodeInjector.java



import javassist.CannotCompileException;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;

import java.io.IOException;

import static javassist.ClassPool.getDefault;


public class ByteCodeInjector {

public static final String CLASS_NAME = "HelloWorld";
public static final String METHOD = "sayHello";

public static void main(String[] argos) throws Exception{
modifyByteCode(CLASS_NAME,METHOD);
}

public static void modifyByteCode(String className ,String methodName)
throws NotFoundException, CannotCompileException, IOException {
//Get the Class implementation byte code
CtClass ctClass = getDefault().get(className);

//Get the method from the Class byte code
CtMethod method= ctClass.getDeclaredMethod(methodName);

/**
* Creating the new Method implementation
*/
StringBuffer content = new StringBuffer();
content.append("{\n System.out.println(\"Hello!!! This is the Modified version!!!\");\n } ");

/**
* Inserting the content
*/
method.setBody(content.toString());
System.out.println("Replacing Method \' sayHello\' s body with new implementation : " + content);
//modify the actual class File
ctClass.writeFile();
}
}

Step 4

Compile the two java sources adding the javassist.jar to your class path
$javac -cp javassist.jar:. HelloWorld.java ByteCodeInjector.java 

Step 5

Run the HelloWorld class and see the out put
$java HelloWorld

Hello!!! This is the original version!!!

Step 6

Now Run the ByteCodeInjector class. That class will change the method implementation of the Helloworld:sayHello()

$java -cp javassist.jar:. ByteCodeInjector
Replacing Method ' sayHello' s body with new implementation : {
System.out.println("Hello!!! This is the Modified version!!!");
}

Now if you run the HelloWorld class you must see a output like
Hello!!! This is the Modified version!!!

Enjoy!!!

References
[1]http://www.csg.is.titech.ac.jp/~chiba/javassist/tutorial/tutorial.html

Friday, November 12, 2010

How to write a Axis2 Message Builder

Apache Axis2 is a open source SOAP/ Web services engine which consists of many extension points. Message Builders and Message Formatters are two ways we can extend the axis2 transport framework.In this post i’m going to explain the idea of Message builders and how we can implement a custom message builder and use it.

As i mentioned above Axis2 is a SOAP engine. So it only accept SOAP messages for processing. So then a problem comes that how we can use axis2 with non-soap invocations like REST. So to convert row non soap content coming from a transport to a SOAP content we can use Message builders.

This can really be useful when your in coming message have a non-xml format and you need to invoke a web service or process it with the axis2 engine with the given content information.

Its simple to Write your own Message builder.
First what you have to do is write a class implementing org.apache.axis2.builder.Builder interface in the Axis2 Kernal module.

The Builder method signature we need to implement look like this.



public OMElement processDocument(InputStream inputStream, String contentType,
MessageContext messageContext) throws AxisFault

As we see here we have three input parameters
  1. input stream : Stream of the raw payload
  2. content type : content type of the message that Builder is registered with.
  3. message context : axis2 message context


Here we can use input stream to create the SOAP info set from the coming message and its not a must to consume the input stream inside the builder.And we can use Axis2 message context to set any message context property information we get from the content or to get information from the message context that we need to build the message.

After we implement the Message builder we need to register it in the axis2 configuration (axis2.xml) with a content type. So messages that comes with that content type will be intercepted by the registered Message builder .

Example configuration in axis2.xml of that will look like this

< messageBuilder contentType="application/xml"
class="org.apache.axis2.builder.ApplicationXMLBuilder"/>

For a recent project i had to implement a custom Message builder to parse a Email coming in a plan text format and create a SOAP Info set out of it to processing.The Message builder solution become ideal for that problem since i had no control over the system that send the Mails.

Saturday, April 17, 2010

Dead Letter Channel Enterprise Application Integration Pattern

Dead Letter Channel Pattern belongs to the Category of Message Channel patterns which describes the Message transport level attributes.






Idea of having a dead letter channel is to handle Message failures. Message failures can be occurred due to several reasons.


  • Transport level failures

  • Due to bad Configuration

  • Message Expiration

  • Problem with Message Consumer end


In a failure Message will be routed to the dead letter channel. So that it can act as a Message archive mechanism , Re router or a special channel to process the bad messages.

Having a Message archive system will be useful since later a Dead message can be viewed and re-delivered to the intended end point manually by a admin console.This will be useful to identify the Configuration problems

Message Re-delivery is also a major part of a dead letter channel implementation. If we take a normal scenario like simple DB quarries or web-service calls some times a message will fail because of the endpoint have a higher load or some other temporary issues with the endpoint . So simply re -delivering the message after a certain time interval will cause message to be delivered successfully.

Apache Synapse is a Open source esb and a message Mediation framework that support several Enterprise application integration patterns. For this summer(2010) Google Summer of code program I applied for the proposal of Implementing A Dead Letter Channel for Apache synapse. This is the link to my proposal .