Terracotta and SpringSource Application Platform

I thought I would share this with the rest of the world and maybe save humanity a few hours of trial and error. I have managed to make Terracotta play along with SpringSource Application Platform (S2AP).

There are three things that needs to be done: first we need to start up S2AP with Terracotta enabled, then we need to make Terracotta classes visible to OSGi bundles and finally we have to baptize the class loader in your bundle so that Terracotta can properly identify your clustered objects.

I assume that both Terracotta 2.6.2 and SpringSource Application Platform RC-1 is installed.

Wrap the Startup Script

In order to enable Terracotta in the platform we need to start the JVM with some additional arguments. The easiest way is to wrap the start up script with another script that set the JAVA_OPTS variable. I created a script called startup-dso.bat in %PLATFORM_HOME%/bin:

setlocal
set TC_INSTALL_DIR=<path_to_local_Terracotta_home>
set TC_CONFIG_PATH=<path\to\tc-config.xml>
call %TC_INSTALL_DIR%\bin\dso-env.bat -q
set JAVA_OPTS=%TC_JAVA_OPTS%
call startup.bat
endlocal

Remember to generate a Terracotta boot jar for you environment.

If you run the script it will look promising until you see java.lang.ClassNotFoundException: com.tc.object.bytecode.Manageable in the console. This is because the OSGi bundle class loader cannot see the Terracotta classes that are loaded by the boot class loader.

Delegate Loading of Terracotta Classes

We need to tell the OSGi container in S2AP to delegate the loading of Terracotta classes to the boot class loader. This is achieved by modifying the java5-platform.profile or java6-platform.profile (as appropriate for the level of Java which you’re using) found in the platform’s lib directory and adding Terracotta’s packages (com.tc.*) to the list under the org.osgi.framework.bootdelegation key.

Naming class loaders

Now only one more thing remains to do: the class loader for the bundle that contains the objects you want to cluster needs to be named and registered:

static {
   NamedClassLoader ncl = (NamedClassLoader) myClass.getClassLoader();

   ncl.__tc_setClassLoaderName("bundle_name");

   ClassProcessorHelper.registerGlobalLoader(ncl);
}

The code above have to be run when your bundle is loaded, I just added it to the Spring managed bean that i wanted to cluster. This is a hack as you introduce compile time dependencies to Terracotta and you can only cluster objects from bundles that you can modify. But we will have to do with this until Terracotta get better support for OSGi.

Add the terracotta boot jar to you build path to satisfy the compile time dependency. Make sure that your ordinary runtime classpath doesn’t contain the boot jar.

Thats it!