Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HotSwaping code into "mvnDebug tomcat:run"

Usually i start tomcat using mvnDebug tomcat:run.

After Code-change i need to use mvn tomcat:redeploy.

This is sub-optimal because i often only change content of existing method-bodys.

Can I HotSwap the method's body into the runtime, and hot-redeploy as a fallback?

I have unfortunatally nothing found like a maven-hotswap-plugin.

faces-config.xml

... <application>
  <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
  <locale-config>
   <default-locale>de_DE</default-locale>
  </locale-config>
  <resource-bundle>
   <base-name>Message</base-name>
   <var>message</var>
  </resource-bundle>
  <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
 </application>
</faces-config>

web.xml:

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
    <listener-class>
        org.springframework.web.context.request.RequestContextListener
    </listener-class>
</listener>

pom.xml:

<dependencies>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-envers</artifactId>
        <version>4.3.0.Final</version>
    </dependency>
    <dependency>
        <groupId>net.java.dev.ajax4jsf</groupId>
        <artifactId>ajax4jsf</artifactId>
        <version>1.0.6</version>
    </dependency>

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>3.6.6.Final</version>
    </dependency>
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.myfaces.core</groupId>
        <artifactId>myfaces-api</artifactId>
        <version>1.2.10</version>
        <scope>compile</scope>
    </dependency>

    <dependency>
        <groupId>org.apache.myfaces.core</groupId>
        <artifactId>myfaces-impl</artifactId>
        <version>1.2.10</version>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>org.apache.myfaces.tomahawk</groupId>
        <artifactId>tomahawk12</artifactId>
        <version>1.1.9</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>com.sun.facelets</groupId>
        <artifactId>jsf-facelets</artifactId>
        <version>1.1.14</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>3.1.0.GA</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring</artifactId>
        <version>2.5.6</version>
    </dependency>
    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>9.2-1004-jdbc41</version>
    </dependency>

    <dependency>
        <groupId>servletapi</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.4</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <contextReloadable>true</contextReloadable>
            </configuration>
        </plugin>
    </plugins>
</build>
like image 631
Grim Avatar asked Feb 04 '14 09:02

Grim


4 Answers

You can use Jrebel - it works exactly as you expect. You just need to specify javaagent and it will reload all classes and framework changes during runtime. It also works with remote servers

To integrate it with maven project you have to add jrebel-maven-plugin, which will generate all configuration (rebel.xml) files.

Without JRebel you can use standard HotSwap mechanism but it only allows to reload method bodies

like image 97
Jakub Kubrynski Avatar answered Oct 16 '22 23:10

Jakub Kubrynski


One of the best solutions for your situation is JRebel

  • What you need to do is make the appropriate changes to the framework and integrate it using a jrebel-maven-plugin.
    It allows to reload all the method bodies.
  • Once you are done with the link-up a auto xml configuration file will be generated which will be used as a config file for the plugin.
  • Mention Your Java Agent as well.
  • After the successful test you can also integrate it with a build
like image 33
D3X Avatar answered Oct 17 '22 01:10

D3X


JRebel is a good option. It isn't cheap but there are open source licences available. The installation instructions for Maven are here: http://zeroturnaround.com/software/jrebel/learn/maven/

We get this working through a specific run profile and embedded Tomcat. This is a specific sub-module that depends on the other projects that build the web application wars. So if you configure something like the following in the runner submodule:

<profiles>
         <profile>
             <id>run</id>
             <build>
                 <plugins>
                     <plugin>
                         <groupId>org.apache.tomcat.maven</groupId>
                         <artifactId>tomcat7-maven-plugin</artifactId>
                         <executions>
                             <execution>
                                 <id>run-wars</id>
                                 <goals>
                                     <goal>run-war-only</goal>
                                 </goals>
                                 <phase>integration-test</phase>
                             </execution>
                         </executions>
                         <configuration>
                            <warDirectory>theWar</warDirectory>
                            <path>/relativepath</path>
                            <systemProperties>
                            <webapps>
                                <webapp>
                                    <groupId>${project.groupId}</groupId>
                                    <artifactId>myArtifact</artifactId>
                                    <version>${project.version}</version>
                                    <type>war</type>
                                    <asWebapp>true</asWebapp>
                                    <contextPath>myContext</contextPath>
                                 </webapp>
                             </webapps> 
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
</profiles>

You can run this with mvn package -Prun which you should be able to shut down with Ctrl+C.

Then, whilst this is running in one terminal, make your code changes, open a new terminal and run mvn compile. With JRebel going the changes should be reflected virtually instantly in your web app.

There should be nothing preventing you from running these same goals through Eclipse's m2e plugin.

like image 1
Mardoz Avatar answered Oct 16 '22 23:10

Mardoz


It seems that you may be using some old version of the maven tomcat plug-in, because newer versions should be referred as tomcat6 or tomcat7, e..g. mvnDebug tomcat7:run. I'm on 2.2 and hot swap from Eclipse works just fine.

To clarify a little more, that's what I see in the command prompt when starting the app with mvn tomcat:run:

...
[INFO] >>> tomcat-maven-plugin:1.1:run (default-cli) @ tomcatMvnDebug >>>
...

Notice the 1.1.

And that's what I see when starting the app with mvn tomcat7:run:

...
[INFO] >>> tomcat7-maven-plugin:2.2:run (default-cli) @ tomcatMvnDebug >>>
...

Notice that this time maven uses tomcat plug-in version 2.2.

like image 1
maksim_khokhlov Avatar answered Oct 16 '22 23:10

maksim_khokhlov