Latest news

JavaRebel 1.2.1 and Spring Plugin 1.0-M2 Released

We are very proud to present not one, but two simultaneous releases....

JavaRebel used to develop LinkedIn

LinkedIn, Corp. has purchased JavaRebel licenses for all its Java engineers to use in the well-known social networking website dev...

JavaRebel 1.2: Now With Full Spring Support

The latest stable release of the JavaRebel code reloading agent includes a plugin for Spring that reloads Spring configuration on-...

Zero turnaround with unexploded development

April 11th, 2008 by Toomas Römer
The latest release of JavaRebel introduced two new approaches for achieving zero turnaround. Firstly if you have deployed your EAR/WAR/JAR as single archives you can still make the application use the classes that you are compiling on-the-fly with your IDE. This is what we are calling unexploded development. The other method is hot JAR replacement which is considered experimental at this point.

In this article we will look at how to setup the development environment to support unexploded development. We will take the Spring Framework sample named PetClinic. We will deploy this to JBoss as a WAR archive and then start modifying the classes in Eclipse IDE and see the changes on-the-fly from the browser.

Before we continue lets look how it works. Once an application is deployed to the container (in this case JBoss) it will start loading the application classes. JBoss is running the JavaRebel agent that will intercept the calls and load those classes from the preconfigured IDE output directory.

Note however, that this means that if a new class is added in the IDE but not present in the JAR files, the JAR files needs to be updated. Why? We are still talking about the classloaders of the container. Container only knows and looks for classes that are present in the EAR/WAR/JAR files and these zip archives are cached. So adding classes still requires the redeployment of the zip archives.

The normal development model in unexploded development looks like this:

  1. Code modifications
  2. Build the archives
  3. Update the EAR/WAR/JAR in the container
  4. Restart the container or redeploy the application
  5. Check the modification

We will change this into:

  1. Code modifications
  2. Background compiling
  3. Check the modification

We assume you have downloaded the Spring Framework (in this case the version number is 2.5.3) and created a Java project from the folder spring-framework/samples/petclinic. We have enabled the IDE to build automatically the source files. Eclipse will by default start building classes to the spring-framework/samples/petclinic/.classes folder.

Lets build the WAR archive. Open up a console and change directory to spring-framework/samples/petclinic. Issue the command ant warfile. It will produce a petclinic.war in spring-framework/samples/petclinic/dist. Copy this file to your JBoss’s deploy folder.

Start the database server for the application. Open up a console and change directory to spring-framework/samples/petclinic/db/hsqldb/ and issue the command server.sh (on Linux) or server.cmd (on Windows). This will start the database server. You should see something like this:

[Server@8813f2]: [Thread[main,5,main]]: checkRunning(false) entered
[Server@8813f2]: [Thread[main,5,main]]: checkRunning(false) exited
[Server@8813f2]: Startup sequence initiated from main() method
[Server@8813f2]: Initiating startup sequence...
[Server@8813f2]: Server socket opened successfully in 4 ms.
, alias=] opened successfully in 259 ms.0, db=file:petclinic
[Server@8813f2]: Startup sequence completed in 268 ms.
[Server@8813f2]: 2008-04-10 16:00:59.471 HSQLDB server 1.8.0 is online
[Server@8813f2]: To close normally, connect and execute SHUTDOWN SQL
[Server@8813f2]: From command line, use [Ctrl]+[C] to abort abruptly

Now lets add a configuration option to the JBoss startup script. We presume you have already installed JavaRebel. We will modify the JBoss/bin/run.sh (on Linux) or JBoss/bin/run.cmd (on Windows). First lets find the full path of the folder that your IDE is compiling the classes to. In my case it is /home/demo/projects/spring-framework/samples/petclinic/.classes. Lets add this as a Java -Drebel.dirs option to the JBoss startup script. So JBoss will have the flag -Drebel.dirs=/home/demo/projects/spring-framework/samples/petclinic/.classes on startup in addition to the usual JavaRebel flags. See JBoss installation for details on modifying the startup scripts.

Lets start the server. As the petclinic.war has been copied to the deploy folder, JBoss will deploy the application on startup. Depending on the server port visit http://localhost:PORT/petclinic. You should see the petclinic application homepage.

Petclinick Homepage

Now lets verify that everything got configured correctly. We’ll make a modification to a Petclinic class and see the output. We’ll test this by changing the validation of adding owners. In the browsers naviagate to “Find Owner” » “Add Owner”. Click “Add Owner” without filling any of the fields. You will see a page where it is stated that all fields are required.

PetClinick Required Fields

Open the file org.springframework.samples.petclinic.validation.OwnerValidator in your just configured IDE project. We will modify the validate method. You will see validation rules:

JAVA:
  1. public void validate(Owner owner, Errors errors) {
  2.     if (!StringUtils.hasLength(owner.getFirstName())) {
  3.         errors.rejectValue(“firstName”, “required”, “required”);
  4.     }
  5.     if (!StringUtils.hasLength(owner.getLastName())) {
  6.         errors.rejectValue(“lastName”, “required”, “required”);
  7.     }
  8.     if (!StringUtils.hasLength(owner.getAddress())) {
  9.         errors.rejectValue(“address”, “required”, “required”);
  10.     }
  11.     if (!StringUtils.hasLength(owner.getCity())) {
  12.         errors.rejectValue(“city”, “required”, “required”);
  13.     }
  14.     String telephone = owner.getTelephone();
  15.     if (!StringUtils.hasLength(telephone)) {
  16.         errors.rejectValue(“telephone”, “required”, “required”);
  17.     }
  18.     else {
  19.         for (int i = 0; i <telephone.length(); ++i) {
  20.             if ((Character.isDigit(telephone.charAt(i))) == false) {
  21.                 errors.rejectValue(“telephone”, “nonNumeric”, “non-numeric”);
  22.                 break;
  23.             }
  24.         }
  25.     }
  26. }

Lets remove the last name, address and city validations. The method will look like this now:

JAVA:
  1. public void validate(Owner owner, Errors errors) {
  2.     if (!StringUtils.hasLength(owner.getFirstName())) {
  3.         errors.rejectValue(“firstName”, “required”, “required”);
  4.     }
  5.  
  6.     String telephone = owner.getTelephone();
  7.     if (!StringUtils.hasLength(telephone)) {
  8.         errors.rejectValue(“telephone”, “required”, “required”);
  9.     }
  10.     else {
  11.         for (int i = 0; i <telephone.length(); ++i) {
  12.             if ((Character.isDigit(telephone.charAt(i))) == false) {
  13.                 errors.rejectValue(“telephone”, “nonNumeric”, “non-numeric”);
  14.                 break;
  15.             }
  16.         }
  17.     }
  18. }

Now when you click “Add Owner” button again you will see that the requirement for the last name, address and city are gone now.

PetClinic Less Required Fields

You should also see the line JavaRebel: Reloading class 'org.springframework.samples.petclinic.validation.OwnerValidator'. in JBoss server log.

If the validation rules have been reloaded, you have successfully configured the unexploded development format. You have deployed a WAR file and made the container aware of the location from where to find the modified classes.

If you have multiple locations to look for the classes you can specify a comma separated list of location to the -Drebel.dirs option.

If you have any comments, suggestions or questions don’t hesitate to ask either in the comments section or via support at zeroturnaround dot com

5 Responses to “Zero turnaround with unexploded development”

  1. ZeroTurnaround.com » Blog Archive » JavaRebel 1.1 Released Says:

    […] Unexploded development. Now you can run JavaRebel without having to change your build cycle in the least. See the installation manual and this article. […]

  2. Peter Says:

    I’ve tried using this feature with latest nightly build and it doesn’t seem to work on OC4J 9.x.

    The exploded build works fine when Eclipse builds directly into oc4j/lib but once everything is packaged in JARs JR doesn’t reload classes.

    I’ve specified Drebel.dirs param to the top dir where Eclipse builds all classes.

    Has anyone succeeded using unexploded feature on OC4J 9.x?

  3. Toomas Römer Says:

    The comments have not been sending email updates to us. Could you repost your comment to the forum and we can look into it.

  4. Rob Sinner Says:

    This works great, this is awesome, Just what was needed. I was tryign to setup alternate poms with special commands for creating symbolic links and it was too painful , especially on windows with Tomcat and windows file locking issues. With this you can use the same build config file (Im using maven pom.xml) and just add some extra configuration options to the tomcat monitor and your off to the races. Well done. I guess I can postpone learning groovy for awhile.

  5. Anders Bergquist Says:

    Took me 10 minutes to get it to work. It got great potential.

Leave a Reply