Sunday, 8 June 2014

Java power tools series - Steps to setup Hotswap Agent in Eclipse

I hope, you have already read "Preface" of my java power tools series.

HotSwapAgent
  • Hotswap agent provides Java unlimited runtime class and resource redefinition.
  • Hotswap agent supports all major frameworks, it is free, open source and extensible.

What does it mean to you?

The main purpose of such tools is to avoid traditional java development methodology --- change -> restart and wait -> check. So developers can do java code changes and check those immediately without the need of app redeploy or JVM  bouncing process. That means, developers can focus more on writing code. Well, you can read my previous post on Tips to boost Java Developers Productivity for more detail.

You are lucky, if you use JRebel during development. But if your company cannot buy JRebel for you, then don't be sad. Alternatively you can try open source and free Hotswap Agent project which has similar goals, but few key differences are (at the time of writing this post):
  • JRebel is currently highly mature and has many plugins to support broad ecosystem.
  • JRebel provides good reporting like time you saved by using it.
  • JRebel is neither open source nor free.

To summarize, at present Hotswap Agent is in beta release and not mature enough like JRebel, but it is FREE. So just by spending your few minutes to setup Hotswap Agent in your development environment, you will be able to save your hours of efforts from server restarts during development.

Steps to setup Hotswap Agent in IDE

Important note:[ Vladimir(skybber) took initiative and used below mentioned steps with my consensus to write wiki documentation on Github about HotswapAgent setup in Eclipse IDE. Besides this, steps are also available to setup HotswapAgent in Intellij and NetBeans on wiki. Therefore, I recommend you to refer latest GitHub wiki page for HotswapAgent setup in IDE instead of below. ]

Hotswap Agent Quick Start page already has provided simple steps to setup it, and the page also has reference urls for setup guide of IntelliJ Idea and NetBeans IDEs.

As Eclipse and Tomcat are widely used for development, I thought to try Hotswap Agent with those and finally it worked when I disabled “Auto Reload” in Tomcat modules (Note - This is not specified in quick start page of Hotswap Agent site).

I followed to below steps setup Hotswap Agent in Eclipse IDE.

Step-1: Install “jvm.dll” DCEVM patch in JDK

I followed the same steps which are mentioned on HotswapAgent quick start page - Install section to patch Java Hotspot(r) file in JDK 1.7_55 and download HotswapAgent.jar file.

Step-2: In Eclipse - Tomcat Server - Runtime Environment - JRE must be mapped to the same JRE of JDK in which DECVM is patched in step-1

Step-3: Tomcat - Add “-XXaltjvm="dcevm" -javaagent:<PATH>\HotswapAgent.jar” in VM Arguments

Step-4:Disable “Auto Reload” in Tomcat web modules
This is most important step, otherwise you will not see power of Hotswap Agent in step-5.

Step-5: Run Tomcat in Debug mode and Enjoy java coding.
When you start your server in debug mode, you should see messages like below in Eclipse Console.

Now if you do code changes in java as well as configuration files of supported plugins (i.e. logback.xml), those would be ready for unit testing immediately without server restart.

Final Note
Overall Hotswap Agent works excellent, however the supported plugins are limited at present. So it may not work as expected when you do some of framework specific code/configuration changes. For example - when I changed value in one of Spring's annotation @RequestMapping, that didn't reload and reflected for unit testing instantly without server restart.

Updates History
  • 14/Jan/2015 - Added important note to refer HotswapAgent wiki on GitHub.
  • 14/Feb/2015 -  Now changes in @RequestMapping Spring annotation are supported, so I did strikethrough my earlier experience with that in final note section. 
Disclaimer
I am not biased to particular free or commercial tools, rather my objective is about sharing my own experience on set of tools.

Also Refer

22 comments:

  1. hi. this blog is very helpful. It just solved my problem. Thanks a ton.
    We have a liferay server in our project which internally uses tomcat. So can you please tell me what settings i need to do for liferay server?

    ReplyDelete
    Replies
    1. Appreciate your feedback. Thanks.

      Have you configured liferay server (which internally uses tomcat) in Eclipse/Liferay IDE? Or your liferay server runs in isolated mode, i.e. not attached to IDE?

      Delete
  2. Thanks a lot !! it Works

    Muchas gracias

    ReplyDelete
  3. I was using JRebel trial and switched to DCEVM after trial has ended. The difference i observed is, JRebel just reloads the class that is modified whereas DCEVM is almost restarting my tomcat that takes good amount of time (2min in my case, my server total startup time is 7min).

    Is there any setting in DCEVM to just load modified class? I have installed DCEVM as Alternate JVM.

    ReplyDelete
    Replies
    1. Some configuration should be missing in your hotswapagent setup. Because it doesn't reload all classes, rather reloads only those which are modified.

      Did you setup tomcat as embedded server in Eclipse IDE? Or your tomcat server runs in isolated mode, i.e. not attached to IDE?

      Delete
    2. This comment has been removed by the author.

      Delete
    3. I setup tomcat in isolated mode still it is taking time

      Delete
  4. I can't seem to get this working with Tomcat 8 while deploying a Spring webapp. Has anyone else had any luck? It throws this exception in the beginning

    InvocationTargetException in transform method on plugin 'class org.hotswap.agent.plugin.tomcat.TomcatPlugin' class 'org/apache/catalina/loader/WebappClassLoader'

    ReplyDelete
    Replies
    1. I didn't try with tomcat 8. Which spring version do you use? I'll give it a try, when I get chance.

      Delete
    2. Hi Tirthal, here's what I'm using
      Tomcat - 8.0.30 (I've tried with 8.0.23 as well but got the same error), Spring Boot - 1.2.7.RELEASE (Spring Core version is 4.1.8.RELEASE), JDK - 1.8u66, dcevm light for Java 8u66 and HotSwap 0.3. I'm also using Vaadin but I don't think that is the problem

      Delete
    3. With Spring Boot, one can enable "Spring Boot Dev tools" for similar purpose. See http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html

      Delete
  5. I can't select localhost tomcat server 8 while working with liferay 7.
    for liferay 6.2(tmcat server 7) it is easily enabled.
    but i am facing problem with tomcat server 8.

    ReplyDelete
    Replies
    1. When you say, you can't select tomcat server 8, there could be two possibilities (i) Your IDE doesn't support you to opt tomcat 8. In that case, try with latest IDE version and see, if you can (ii) Hotswap Agent Tomcat Plugin (http://www.hotswapagent.org/ha-plugins/tomcat-plugin) may have compatibility issue with tomcat 8. I didn't try it with tomcat 8 yet, so I'll not be able to comment on this. You may try and share your experience.

      Delete
  6. This comment has been removed by the author.

    ReplyDelete
  7. I am also not able set it up properly with java 7u79 and tomcat 7. Whenever I change any java files, tomcat is getting restarted.The funny thing is, I was able to configure it properly with Jdk1.8.0_91 and tomcat 8.0. But I wanna run it with jdk1.7.0_79 and tomcat 7. I downloaded 'DCEVM-full-7u79-installer.jar' from their site. Still no luck in running that.

    ReplyDelete
  8. hi tirthal can you help with DCEVM on lifreay server.I have integrated liferay on eclipse ide.It does not give me an option to disable web module.

    ReplyDelete
    Replies
    1. Hi Megha,

      As per my knowledge, HotswapAgent framework plugins http://hotswapagent.org/index.html) doesn't have Liferay support. Anyway with which version of Liferay are you trying? Is it bundled with tomcat or jboss or which server?

      Rather I suggest to consider Liferay IDE's ability for the same. For example, for Liferay 6.2, see "Figure 6: Deploying projects is a drag and drop process." @ https://dev.liferay.com/develop/tutorials/-/knowledge_base/6-2/writing-your-first-liferay-application

      In short, without configuring DCEVM, you can use Liferay IDE's plugin drag and drop to server feature to improve productivity.

      Delete
  9. Hi Tirthal, I followed all the steps. I am using java 7 with tomcat 7. Started tomcat in debug mode. made a change to my java file and saved it. Nothing happened. Dont see any message in console. "Build Automatically" of eclipse is enabled. Even on refreshing my web page, i dont see updated change. What am I missing. Here are the agent's logs from server start up logs.
    HOTSWAP AGENT: 16:55:40.377 INFO (org.hotswap.agent.HotswapAgent) - Loading Hotswap agent {1.1.0-SNAPSHOT} - unlimited runtime class redefinition.
    HOTSWAP AGENT: 16:55:40.697 INFO (org.hotswap.agent.config.PluginRegistry) - Discovered plugins: [Hotswapper, WatchResources, AnonymousClassPatch, ClassInitPlugin, Hibernate, Hibernate3JPA, Hibernate3, Spring, Jersey1, Jersey2, Jetty, Tomcat, ZK, Logback, Log4j2, MyFaces, Mojarra, Seam, ELResolver, WildFlyELResolver, OsgiEquinox, Owb, Proxy, WebObjects, Weld, JBossModules, ResteasyRegistry, Deltaspike, JavaBeans]

    HOTSWAP AGENT: 16:55:41.798 INFO (org.hotswap.agent.config.PluginRegistry) - Plugin 'org.hotswap.agent.plugin.tomcat.TomcatPlugin' initialized in ClassLoader 'WebappClassLoader
    context:
    delegate: false
    repositories:
    ----------> Parent Classloader:
    java.net.URLClassLoader@5bf7253e
    '.
    HOTSWAP AGENT: 16:55:41.798 INFO (org.hotswap.agent.plugin.tomcat.TomcatPlugin) - Tomcat plugin initialized - Tomcat version '7.0.75.0'
    Mar 09, 2017 4:55:42 PM org.apache.catalina.startup.TldConfig execute
    INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
    HOTSWAP AGENT: 16:55:42.345 INFO (org.hotswap.agent.config.PluginRegistry) - Plugin 'org.hotswap.agent.plugin.tomcat.TomcatPlugin' initialized in ClassLoader 'WebappClassLoader
    context: /DCEVM_Project
    delegate: false
    repositories:
    /WEB-INF/classes/
    ----------> Parent Classloader:
    java.net.URLClassLoader@5bf7253e
    '.
    HOTSWAP AGENT: 16:55:42.345 INFO (org.hotswap.agent.plugin.tomcat.TomcatPlugin) - Tomcat plugin initialized - Tomcat version '7.0.75.0'

    ReplyDelete
    Replies
    1. So, I modified the arguments to include autoHotSwap=true in this way
      -XXaltjvm="dcevm" -javaagent:C:\Users\sk032e\Desktop\Softwares\hotswap-agent-1.1.0-SNAPSHOT.jar=autoHotswap=true
      The logs have updated info on HotSWap now


      and when I make a change to any Java file, I see the below message in logs(console view of eclipse)

      HOTSWAP AGENT: 17:13:12.468 RELOAD (org.hotswap.agent.config.PluginManager) - Reloading classes [com.sachin.servlets.TestServlet] (autoHotswap)

      But still on refresh of webpage, I dont see update.

      Delete
  10. After following the steps when I'm running the Spring Application in debug mode the following error appears..
    HOTSWAP AGENT: 12:51:56.330 INFO (org.hotswap.agent.HotswapAgent) - Loading Hotswap agent {1.1.0-SNAPSHOT} - unlimited runtime class redefinition.
    HOTSWAP AGENT: 12:51:57.017 ERROR (org.hotswap.agent.config.PluginRegistry) - Error in plugin initial processing for plugin package 'org.hotswap.agent.plugin'
    java.lang.ClassNotFoundException: org/hotswap/agent/plugin/hotswapper/HotswapperPlugin
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:278)
    at org.hotswap.agent.config.PluginRegistry.scanPlugins(PluginRegistry.java:89)
    at org.hotswap.agent.config.PluginManager.init(PluginManager.java:125)
    at org.hotswap.agent.HotswapAgent.premain(HotswapAgent.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:382)
    at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:397)

    Can somebody help me out.

    ReplyDelete