Monday, April 18, 2011

Add dynamic Java code to your application

JavaServer Pages (JSP) is a more flexible technology than servlets because it can respond to dynamic changes at runtime. Can you imagine a common Java class that has this dynamic capability too? It would be interesting if you could modify the implementation of a service without redeploying it and update your application on the fly.

The article explains how to write dynamic Java code. It discusses runtime source code compilation, class reloading, and the use of the Proxy design pattern to make modifications to a dynamic class transparent to its caller.

An example of dynamic Java code

Let's start with an example of dynamic Java code that illustrates what true dynamic code means and also provides some context for further discussions. Please find this example's complete source code in Resources.

The example is a simple Java application that depends on a service called Postman. The Postman service is described as a Java interface and contains only one method, deliverMessage():

 public interface Postman {     void deliverMessage(String msg); }  


A simple implementation of this service prints messages to the console. The implementation class is the dynamic code. This class,PostmanImpl, is just a normal Java class, except it deploys with its source code instead of its compiled binary code:

 public class PostmanImpl implements Postman {

private PrintStream output; public PostmanImpl() { output = System.out; } public void deliverMessage(String msg) { output.println("[Postman] " + msg); output.flush(); } }


The application that uses the Postman service appears below. In the main() method, an infinite loop reads string messages from the command line and delivers them through the Postman service:

 public class PostmanApp {

public static void main(String[] args) throws Exception { BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in));

// Obtain a Postman instance Postman postman = getPostman();

while (true) { System.out.print("Enter a message: "); String msg = sysin.readLine(); postman.deliverMessage(msg); } }

private static Postman getPostman() { // Omit for now, will come back later } }


Execute the application, enter some messages, and you will see outputs in the console such as the following (you candownload the example and run it yourself):

 [DynaCode] Init class sample.PostmanImpl Enter a message: hello world [Postman] hello world Enter a message: what a nice day! [Postman] what a nice day! Enter a message:   


Everything is straightforward except for the first line, which indicates that the class PostmanImpl is compiled and loaded.

Now we are ready to see something dynamic. Without stopping the application, let's modify PostmanImpl's source code. The new implementation delivers all the messages to a text file, instead of the console:

 // MODIFIED VERSION public class PostmanImpl implements Postman {

private PrintStream output; // Start of modification public PostmanImpl() throws IOException { output = new PrintStream(new FileOutputStream("msg.txt")); } // End of modification

public void deliverMessage(String msg) { output.println("[Postman] " + msg);

output.flush(); } }


Shift back to the application and enter more messages. What will happen? Yes, the messages go to the text file now. Look at the console

0 comments: