Sunday, November 18, 2012

Save Time - Integrating JRebel Development with Alfresco Customization


For the past two months or so, my team has been using JRebel 5.0.1 with our custom Alfresco development to minimize application redeploys during development.    It has been a LIFESAVER TIMESAVER!  I am hooked and won't ever go back to doing Java development without it!  Personally for the past 30 days, JRebel has prevented at least 314 redeploys/restarts saving me about 12.7 hours. (Which it tells you each time you start your application server locally).

I'm working on an Alfresco 4.0.2 customization project built with Alfresco web scripts where we store content in the Alfresco repository, Spring configuration to inject our custom Java-backed web scripts, and Spring's JDBC template to store and retrieve metadata about the content.  In conjunction with debug options turned on and attaching to the remote java app, multiple JUnit integration tests for each of the 18 custom web scripts we are writing, and the key - JRebel development integration - this has started being one of the most awesome development experiences I've only just had the opportunity to enjoy!

Here's a small blurb from the JRebel page on what it does:
"Save. Refresh. Enjoy. And stop redeploying in Java!
JRebel is a JVM-plugin that makes it possible for Java developers to instantly see any code change made to an app without redeploying. JRebel lets you see code changes instantly, versioning classes and resources individually and updating one at a time instead of as a lump application redeploy. When developers make a change to any class or resource in their IDE, the change is immediately reflected in the deployed application, skipping the build and redeploy phases and preventing an average of 5.25 work weeks per year in redeploys!"
For a detailed list, please refer here.

JRebel has detailed instructions on how to install with your IDE of choice, here's what I had to do:
  • View the instructions to install the plugin for your IDE (eclipse in our case) - http://zeroturnaround.com/software/jrebel/download/installing-jrebel-plugin-for-eclipse/
  • Install with Eclipse update manager
  • Restart Eclipse, window should pop up to Activate JRebel license.  Can also Open JRebel perspective and go to ‘Activation’ tab
  • Point to JRebel license, or use the link from the JRebel server, download client.lic and point to that file
  • Open JRebel perspective, navigate to ‘Overview’ tab, choose the project to have JRebel recognize
  • Right click on project root, JRebel, ensure that ‘Automatically generate jrebel.xml’ is enabled.  This creates the jrebel.xml file (tells what classes to auto deploy) in /src/main/resources
  • Ensure Project -> Build Automatically is enabled
  • Configure tomcat server where Alfresco is deployed.  In JRebel perspective, navigate to ‘Overview’ tab.  If you use 'External Server', click there to get the JVM options you will need to add to your tomcat JVM.  I have an alfresco.bat file that starts up my local tomcat server.  Add the JRebel JVM options to your JAVA_OPTS.
rem set debug options
set DEBUG_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,address=1044,server=y,suspend=n

rem set jrebel options
set JREBEL_OPTS=-javaagent:"C:\Apps\springsource\sts-2.9.2.RELEASE\plugins\org.zeroturnaround.eclipse.embedder_5.0.1.RELEASE-201207191833\jrebel\jrebel.jar" -Drebel.workspace.path="C:\workspaces\opm-team" -Drebel.log.file="C:\Users\jhsu\.jrebel\jrebel.log" -Drebel.properties="C:\Users\jhsu\.jrebel\jrebel.properties"

rem Set any default JVM options
set JAVA_OPTS=%DEBUG_OPTS% -Xms512m -Xmx512m -Xss512k -XX:MaxPermSize=256m -XX:NewSize=256m -server -Dalfresco.home=%ALF_HOME% -Dcom.sun.management.jmxremote %JREBEL_OPTS%
  • Deploy once more from scratch so the jrebel.xml will be on the target
  • NOTE:  Refreshes anything that goes in target/classes or target/test-classes (as defined in rebel.xml)
  • NOTE: Won’t refresh the web script descriptor files yet, have to do that manually
NOTE: There is a bug that I noticed with version 5.0.1 last week when I changed code inside the constructor.  Since both adding / removing constructors and changes to method bodies are claimed to be supported by JRebel, I was surprised at this.  *Edit:  We are using spring's default scope of singleton for this particular spring bean definition.*
  • We're not using Spring constructor injection so it's not this: http://zeroturnaround.com/forums/topic/does-jrebel-see-constructor-implementation-change-for-spring-component/
  • This article says re-invoking the constructor will break the existing bean’s state so this is very unlikely that this will ever be implemented, then why does JRebel state say adding / removing constructors is supported? http://zeroturnaround.com/forums/topic/jrebel-5-0-x-does-it-invoke-constructor-on-spring-bean-on-reloading-of-it/

2 comments:

  1. You can add a new constructor and it will work when you create the new instance of the class (as well as with the changed constructor). The old instance of the class are preserved - JRebel will try hard to avoid any initializers to be executed on the existing class instances.

    It is not a bug. It is the way it works.

    ReplyDelete
  2. Hi Anton, appreciate your comment.

    - Your response to article 1 (referenced from zeroturnaround above) is only discussing spring constructor injection. I am not using spring constructor injection for this particular bean.

    - Your response to article 2 discusses that re-invoking the constructor will break the existing bean's state, so that will unlikely to be implemented. This sounds like what I am doing now, so your response says that it is unlikely to be implemented.

    - Your response to my blog says that JRebel tries hard to avoid any initializers to be executed on the existing class instances. Since I'm using Spring's default scope of singleton, is there any solution to this? If not, maybe it will be clearer to add a note in the JRebel functions that singleton constructor method body changes are not supported.

    Thoughts?

    Thanks,
    Judy

    ReplyDelete

I appreciate your time in leaving a comment!