Groovy Example with Hot Class Reload based on RelProxy

This example shows how we can use a dynamic language like Groovy to code the view logic instead of using Java of an ItsNat application including hot class reload fast and avoiding the tedious context reload

With Groovy you are going to code less like this snippet:

             { Event evt -> def text = textInput.getText(); resultsElem.setTextContent(text); } as EventListener, false)

A simple running example

Say something to Groovy:

You said:

Can I change Groovy source code and automatically reload it on the fly in runtime in production or development time?


You know Groovy can automatically reload your Groovy classes in certain circumstances, unfortunately this is not the case when a Groovy object is passed to a Java method for instance when registering in ItsNat a listener coded in Groovy.

Groovy is a dynamic language but not a fully pure dynamic, Groovy compiles on the fly the source code generating conventional Java objects (with a Class associated), because Java code receives a conventional Java object created by Groovy there is no built-in way by Groovy to replace the object with a new one with different code when Groovy reloads the class.

RelProxy is a Java and Groovy hot class reloader library, in spite of it is a general purpose tool it was conceived to provide hot class reload to ItsNat. In Groovy case RelProxy delegates to the built-in class reload mechanism of Groovy.

GProxy is a Java class to provide a simple proxy for Groovy objects. When GProxy is used a java.lang.reflect.Proxy is passed instead of the original Groovy object, the original Groovy object is retained under the hood and method calls to the proxy are redirected to the real object calling the corresponding method using reflection, when the source code of the Groovy class changes GProxy automatically reloads the Groovy class and creates a new object to replace the old one, the fields of the original object are got and re-set to the new object to keep the state (number of fields and types must be the same otherwise reloading is not possible and a redeploy is required).

GProxy part of RelProxy is not so sophisticated like products like JRebel but it could dramatically reduce the number of redeploys in an ItsNat project.

With a simple boolean enabled param set to false in initialization time, GProxy does nothing and your original objects are returned instead of proxies with 0 performance penalty in production.

ItsNat, Groovy, GProxy and automatic reload

GProxy can easily be applied to an ItsNat-Groovy project to provide a proxy instead of the original Groovy object when registering an ItsNatServletRequestListener associated to a page template. When a document (page) is loaded calling processRequest, GProxy re-creates this listener object if the source code of this object or any other dependent class has changed, and re-set all fields to restore the current state.

Field values of the class implementing ItsNatServletRequestListener are not reloaded to the new possible source but because cascade dependent classes when executing processRequest are reloaded, any new object created by processRequest is fresh with the last source and registering on Java ItsNat classes happens after reloading so then no GProxy is needed.

This solution is not perfect because only affects to view-logic (not to classes of global objects provided to ItsNatServletRequestListener page loaders), that is, code for ItsNatDocument processing, anyway this is very much code.

This is an example of using a GProxy when registering a ItsNatServletRequestListener associated to a template for document loading:

ItsNatServletRequestListener listener = inexp.groovyex.GProxy.create(new inexp.groovyex.GroovyExampleLoadListener(db), ItsNatServletRequestListener.class);

How to test automatic reload in this example?

Change GroovyExampleDocument and groovyex.html, and reload this page, no redeploy is needed. You can change also GroovyExampleLoadListener if needed for instance to change parameters provided to GroovyExampleDocument but do not add/remove/change fields. Changes to FalseDB (a field of GroovyExampleLoadListener) are not automatically reloaded.

How to include Java source code into the WAR file below WEB-INF?

Check JProxy for build configuration in Maven and NetBeans Ant.