Tuesday, April 23, 2013

Practical introduction to JRebel

In this post I would like to present my experiences with JRebel: from basics to more advanced stuff, where I had to dig through the Internet or ask ZeroTurnaround to find the answer.

Disclaimer: I wasn't paid for this post. All the information is based on my personal experience after using JRebel for the last 10 months. I tried to be honest and not to force any opinions. I think JRebel is cool, but as everything it is not perfect, so before buying it you should learn how it works.

What is JRebel?

JRebel instantly reloads changes to Java code. It works as a java agent on top of the JVM. It looks for changes in the folder with your compiled classes. If you compile a class, JRebel notices the change and compares the differences between class definitions. Then at the bytecode level it adds/removes/replaces fields/method bodies/etc. without restarting the JVM.

Example configuration

To configure JRebel you need two things:

  • place rebel.xml in the main folder of the package (jar/ear/war, etc.) that will be run as a standalone application or will be deployed to server
  • run your application or start your server with the -javaagent parameter specifying the path to the jar with JRebel

rebel.xml

Here is an example of the rebel.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns="http://www.zeroturnaround.com" 
                xsi:schemaLocation="http://www.zeroturnaround.com http://www.zeroturnaround.com/alderaan/rebel-2_0.xsd">
    <classpath>
        <dir name="/absolute_path_to_your_project/target/classes"></dir>
    </classpath>
    <web>
        <link target="/">
            <dir name="/absolute_path_to_your_project/src/main/webapp"></dir>
        </link>
    </web>
</application>
You should put absolute paths, not relative ones, as the working directory from which JRebel will run may be hard to specify.

The classpath element is used for the path to your compiled classes. If you use Eclipse and have ticked the option Project/Build Automatically, after you save the source file Eclipse will automatically compile your code and overwrite the class file. Then JRebel will find out that the class is changed and reload it.

The web/link element is for the web resources that you would like to have reloaded, i.e.: JSPs, image files, CSS files, JavaScript files, etc.

-javaagent

Next thing is the JVM launch configuration. In the simplest case you have to add the -javaagent parameter either to your launch script or to the server start script:

java
-javaagent:"/absolute_path_to_jrebel_installation/jrebel/jrebel.jar"
-Drebel.workspace.path="/absolute_path_to_eclipse_workspace"
-Drebel.log.file="/absolute_path_to_your_home_folder/.jrebel/jrebel.log"
-Drebel.properties="/absolute_path_to_your_home_folder/.jrebel/jrebel.properties"
...specific server options...
$SERVER_MAIN_CLASS

Again, remember to specify absolute paths.

Plugins

In addition to class reloading, JRebel provides a large variety of plugins that alter the way reloading works for different languages and libraries. The main idea behind plugins is that sometimes you may want to reload more files after compiling a class or changing a resource file. For example, if you change your Spring XML configuration file, you would also like to inform the Spring container that a class definition is outdated.

Personally, I used the Maven, Eclipse, IntelliJ, Spring, Struts and EJB plugins with minor issues.

What canNOT be reloaded?

From the major problems I encountered, the first one was the lack of JiBX plugin. It troubled me quite a lot, because it is heavily used in my current company. JRebel support team suggested writing a JiBX plugin myself (more info about creating plugins can be found here), but unfortunately JiBX does not provide incremental builds, so it would not add much value anyway.

The next problem I had with JRebel was web.xml. Reloading web.xml is not supported, which was confirmed by the JRebel support team. This is quite reasonable, as such reloading feature should be placed in the server logic, which is unreachable from java agents.

Besides this problems there are two well documented cases where your classes cannot be reloaded (for details check here):

  • Replacing superclass
  • Adding/removing implemented interfaces

Replacing superclass

Lets start with this set of classes:

class A {}
class B {}
class C extends A {}

If you replace the parent of C with B:

class C extends B {}

...then you will get the following error:

com.zeroturnaround.javarebel.SuperClassChangedError: 
JRebel: Class 'C' superclass was changed from 'A' to 'B' and could not be reloaded!
Adding/removing implemented interfaces

As for the new/removed interfaces lets start with this 2 interfaces and a class:

interface A {}
interface B {}
class C implements A {}

...and this piece of code using them:

A c = new C();

When we add a new interface implementation:

class C implements A, B {}

...and tweak our code a little bit:

B c = new C();

...we get this error:

java.lang.IncompatibleClassChangeError: 
Class C does not implement the requested interface B

As you can see JRebel is not a silver bullet and before buying it you should test it on your production projects first and learn about its limitations.

How to cope with reloading problems?

From time to time JRebel will spit out an error that it could not reload the classes. Another time you will change the source code and the change would not be reloaded, because of plugin limitation, some special case, server cached some objects, etc.

My approach here to this problem is very simple. I try not to restart the server as long as possible. When I encounter a situation where my class/resource was not reloaded (it happens from time to time, but in practice not very often), I just rebuild the application.

Licenses

JRebel is a commercial product and is not cheap, however take notice that you can use JRebel for free, if you are programming in Scala, working on a non-profit project or as a open-source developer.

As for the commercial licenses there are currently two options:

  • Enterprise
    • obviously more expensive as the name suggests
    • comes with a reporting server (reporting the usage/number of reloads/etc.)
    • licences are floating, which means that every license is blocked whenever a developer uses JRebel
    • because licenses are floating, you can buy less licenses (about 80% of the number of developers as suggested by the support team)
  • Base
    • cheaper than enterprise
    • you have to do reporting on your own (you can compute statistics based on ~/.jrebel/javarebel.stats, where timestamps of reloads are being stored)
    • named, which means attached to one developer at a time (the support team reassured us, that it does not mean that when a developer leaves the company the license is discarded, another programmer can still use it)
    • this is the one we have chosen

How ZeroTurnaround protects JRebel against abuse?

In order to prevent from cheating, i.e. buying 10 licences and giving them to 20 developers, ZeroTurnaround computes statistics of the usage of JRebel based on the IP numbers. If they notice any significant abnormalities, they will contact you to check whether it is an issue.

Trial period

A member of JRebel marketing team contacted me and offered my company about 5 licenses for free for a 30-day trial period. During this time my teammates and myself were using JRebel for our daily tasks. After the license expired we decided that the tool helps us being more productive and the company purchased a license for every developer in my development team.

Support

During the trial period I often asked questions by e-mail and the JRebel support team got back to me usually within one working day and sometimes even in a matter of minutes. I also know they have a forum, where you can get some help. Since buying JRebel we haven't encountered any issues, so fortunately there wasn't any need to contact the JRebel guys.

Final thoughts

I hoped you learned something new from my post and it helped you in making a decision, whether JRebel is a good choice for you.

No comments:

Post a Comment