Saturday, July 23, 2011

Context 0.8.3 gets live class reloading and other things

This is really exiting. Context 0.8.3 has just been released and it just keeps getting better. Live class reloading has been a long dream and one weekend I decided that I will now try to make it happen.

I have used JRebel for code-hot-swapping and it has worked great. But because it is a separate commercial product, it cannot be the only option.

So after finding information about class loading etc, about eight hours later live class loading became alive. :-D And in quite elegant way actually.

Now, in Context every page load gets own set of objects to handle the page state. So, what I actually did was to attach a throwaway class loader to that process. When page is reloaded and class changes are detected a new class loader is created for new page loads.

The especially nice thing about this approach is that even classes from service-layer can be reloaded.

Basically the only concern is that live class reloading creates a two set of classes; those that are reloadable and those that are not. If class can be handled purely by annotations and Guice then it is probably reloadable.

This separation means that classes that are non-reloadable must not depend on reloadable classes. Otherwise there will be linkage errors. But with reasonable organizing that should not be a problem.

Remote method interception and data validation

In Context page update requests are translated into component method calls which creates a good question. Can that call be intercepted in AOP-like manner? This is important, because method execution may require certain privileges or parameter validation.

The normal approach would be to create proxies that handle the AOP-stuff. This is however, problematic because it prevents using new-operator and I have never liked that restriction.

Now, because the remote call is translated from certain url to method call, it is actually called via reflection. So, the solution was simple. I simply added a new method to LifeCycleListener-interface, that is called every time when method should be invoked. All data validation and other checks can be done in that method.