Developing Liferay Core and plugins using JRebel
General Blogs August 7, 2013 By Miguel Ángel Pastor Olivar
I guess all of you already know what JRebel is so I guess it doesn't deserve an exhaustive introduction. In a few words, JRebel is a JVM agent which allows you to reload your class definitions "on the fly" so you don't need to restart your applications once it has been started/deployed. You can think of it as a kind of the native HotSwap ability offered by the JVM but "on steroids": you can redefine "whatever" you want and the JRebel agent will reload your new class definition.
Here at the Liferay engineering team have been thoroughly using it for the core development during the last year and a half and the results have been very good. However, we have been dealing with a small problem during all the time we have been using it: if we have the JRebel enabled in the Liferay core we can not deploy Liferay applications because the hot deployer it is not being invoked. As you know, here at Liferay we make an extensive use of "classloading tricks" (hopefully it is going to change in the near future :) ) in order to get a fully working implementation of our hot deployment mechanism so I guess the problem was something related to this, but I have never had the enough time to go through a thoroughly debug session. Finally, last week I was able to get some free time and I just decided to start a funny debugging session.
I don't want bother you with all the technical details but, as a quick summary, I ended up with two JRebel configuration files: one for the portal-service classes (the one we put in a common classloader for all the webapps in the app servers) and one for the rest of the Liferay portal stuff and the docroot of the web application. All the classes you monitor in a JRebel configuration file end up in the same classloader and it was the root cause of our problem: an static field (remeber static fields are unique per classloader, not the whole JVM) of a class which was supposed to be loaded in a common classloader was being loaded in the portal classloader, and this issue was the reason that prevented the hot deploy events were fired.
I have decided to automate the generation of your whole JRebel configuration in order to prevent any kind of misconfigurations. So, once you get a copy of the Liferay core git repo in your file system you can run "ant setup-rebel"; this task will configure your development environment (it doesn't matter what app server you are using), enabling the JRebel development mode. The only thing that is left to you is the configuration of the startup process of your app server, in order to define the JRebel JVM agent path.
One more thing I would like to highlight is that this automatically generated configuration is IDE agnostic, and use the folders used by our standard build system tool, Ant. If you need to reconfigure JRebel in order to define custom folders (pointing to the compilation folders of your preferred IDE) you can overwrite the default configuration files (using the -overwrite.xml extension) and rerun the setup-rebel task.
In addition, I have added the same task to our Plugins SDK, so if you run ant setup-jrebel in the plugin of your choice this will get the JRebel configuration automatically generated. At the time of this writing the portal core stuff is already in the master branch of the public repo but the Plugins SDK stuff is still pending in Brian's pulls queue.
Feel free to ping me if you have any doubt or if you want a more detailed description about the internals of the process.