Archiv für den Monat: Januar 2012

DynamicProxies – The magic behind OR-mappers and mocking frameworks

Did you ever wonder how mocking frameworks “create” instances of you interfaces? Or how OR-mappers like Hibernate give you entities with lazily loaded references to another of your entities that throw the well known LazyInitializationException when the session is already closed?

The answer is: Dynamic proxies.

As part of the reflection package in the JDK, the classes around java.lang.reflect.Proxy allow you to create instances of interfaces – even if there is no implementation of that interface present in the classpath. These instances are called “proxy-instances”.

Each proxy-instance has assigned an implementation of the interface java.lang.reflect.InvocationHandler. The handler gets informed about every method that is called on the proxy-instance (including arguments, return types etc.). This allows you to dynamically create “runtime implementations” of interfaces, giving them a custom behavior (testing frameworks like JUnit – record, replay, etc.) or just to intercept/modify calls to a “real” instance (AOP-like behavior).

Here is an example to get an idea of how (easy) it works:

Main class

package de.perdoctus.examples;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
 
/**
 * This class contains a main method that creates a dynamic proxy.
 * 
 * @author Christoph Giesche
 */
public class ProxySample {
 
    public static void main(String[] args) {
 
        //Create an instance of our InvocationHandler
        InvocationHandler handler = new UselessHandler();
 
        //Create a "dynamic proxy" of our useless interface
        Object proxy = Proxy.newProxyInstance(
                Useless.class.getClassLoader(), 
                new Class[] {Useless.class}, 
                handler);
 
        //Cast the proxy instance to our Useless interface
        Useless uselessProxy = (Useless) proxy;
 
        //Call some methods on our instance
        uselessProxy.getStatus();
        uselessProxy.setSomeValue("foobar");
        uselessProxy.toString();
    }
}

Interface that is used to create proxy-instance

package de.perdoctus.examples;
 
/**
 * Just a useless interface to demonstrate dynamic proxies.
 * 
 * @author Christoph Giesche
 */
public interface Useless {
    void getStatus();
    void setSomeValue(String value);
}

An invocation handler telling you what is going on

package de.perdoctus.examples;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
/**
 * UselessHandler will handle all method calls to our dynamic proxy. This
 * handler can be assigned to different proxy instances.
 * 
 * @author Christoph Giesche
 */
public class UselessHandler implements InvocationHandler {
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 
        StringBuilder sb = new StringBuilder();
 
        sb.append("Method '")
          .append(method.getName())
          .append("' was called ");
 
        if (args != null) {
            sb.append("with arguments:");
            for (Object arg : args) {
                sb.append('\n');
                sb.append(arg.getClass().getSimpleName())
                  .append(" = ")
                  .append(arg.toString());
            }
        } else {
            sb.append("without arguments.");
        }
 
        sb.append("\nThe method has the return type '")
          .append(method.getReturnType())
          .append("'\n");
 
        System.out.println(sb.toString());
        return null;
    }
 
}

Result when running main class

Method 'getStatus' was called without arguments.
The method has the return type 'void'

Method 'setSomeValue' was called with arguments:
String = foobar
The method has the return type 'void'

Method 'toString' was called without arguments.
The method has the return type 'class java.lang.String'

How to REST – Useful articles

If you are planning to use REST in your projects, I strongly recommend you to get in touch with it’s principles. As REST makes excessive use of the standard HTTP protocol, aspects like caching can be delegated to one of the various HTTP caching products.

Below, you can find some very useful articles about the principles of REST including versioning and common mistakes when implementing a REStful service.

After having read all of those articles, you may have a more precise understanding of what RESTful interfaces should look like and what advantages you have due to the fact that it is based on HTTP.

Evaluating JavaScript from within your Java application

Sometimes you may wish to include JavaScript, Groovy or other scripting languages features within your Java application. The package javax.script offers an API for exactly that purpose.

The JRE provides a JavaScript engine (Mozilla’s Rhino) by default. Additional engines are listed here.

A simple example of how to evaluate a JavaScript in Java is shown below. If needed, you have access to the complete Java API from within your script.

package de.perdoctus.examples;
 
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
 
/**
 * @author Christoph Giesche
 */
public class ScriptManagerExample {
 
    public static void main(String[] args) {
        //create a ScriptEngineManager
        ScriptEngineManager sem = new ScriptEngineManager();
 
        //obtain a JavaScript engine from the manager
        ScriptEngine engine = sem.getEngineByName("JavaScript");
 
        //put some attributes to the engine's context
        ScriptContext context = engine.getContext();
        context.setAttribute("netPrice", 10.92, ScriptContext.ENGINE_SCOPE);
        context.setAttribute("vat", 19, ScriptContext.ENGINE_SCOPE);
 
        //Execute some JavaScript using our attributes.
        try {
            engine.eval("var price = netPrice + (netPrice * vat / 100)");
        } catch (ScriptException ex) {
            System.err.println(ex);
        }
 
        //retrieve attribute "price" from engine's context
        Double price = (Double) context.getAttribute("price");
 
        System.out.println("Price including vat: " + price);
    }
}