Friday, February 12, 2010

E.T. phone home

Using some extra facilities it should be possible to call EJBs deployed on JBoss 4 from JBoss 5 (or calling 5 from 6, and even calling WebSphere from JBoss). The end result should be:
InitialContext ctx = new InitialContext();
GreeterRemote bean = (GreeterRemote) ctx.lookup("java:externalContext/Greeter");
String result = bean.sayHi("testPositive");
Now the first step should be to be able to have complete isolation of the outgoing calls, so that any existing class in the application server doesn’t collide with any client class.

// we want the client classes of the receiving application server
URL clientUrl = new URL(jbossHomeDir.toURI().toURL(), "client/jbossall-client.jar");
// don't set a parent, so we run in complete isolation.
URLClassLoader urlCl = new URLClassLoader(urls, null);
// since we're running in isolation my own interface needs to be added.
ClassLoader cl = new AluniteClassLoader(urlCl, ClassLoader.getSystemClassLoader());
ClassLoader previous = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(cl);
try
{
InitialContext ctx = new InitialContext();
GreeterRemote bean = (GreeterRemote) ctx.lookup("Greeter");
String result = bean.sayHi("testPositive");
assertEquals("Hi testPositive", result);
}
finally
{
Thread.currentThread().setContextClassLoader(previous);
}
The most important bit is the AluniteClassLoader which has no parent class loader and delegates to the given class loaders in turn. Thus can the above code work out.

As Jaikiran correctly pointed out, the current bean proxy needs to be called within the correct context class loader. So we would also need a specialized external context which return wrappers to allow setting the thread context class loader at the right moment.

Lastly it needs code to correctly setup and install the external context in the local JNDI.

The code so far can be found here.