Reputation: 127
I have a war project that depends on another jar project in the same directory. Now I want to start the war project in jetty with maven, and want it to hot swap changes in the dependent project so that the chagnes take effect immediately. My plugin config looks like this:
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<configuration>
<webAppSourceDirectory>${project.basedir}/src/main/resources</webAppSourceDirectory>
<classesDirectory>${project.basedir}/src/main/java</classesDirectory>
<webApp>
<contextPath>/</contextPath>
<descriptor>${basedir}/src/main/resources/WEB-INF/web.xml</descriptor>
</webApp>
</configuration>
</plugin>
How can i do it please? any pointer is appreciated.
Upvotes: 0
Views: 5937
Reputation: 49515
First thing to point out...
You don't want to do this, as JAR reloading is poorly supported by Java itself, it will tend to want to cache the JAR and its contents on first use (standard behavior of the URLClassLoader). Replacing the JAR at runtime requires extra work, and sometimes even that is not possible without incurring some sort of memory leak (see the the various Leak Preventers that Jetty ships with for some hidden nasties in this area). Be prepared for OOM or other issues if you rely on this.
Now, with that out of the way ...
Hot Deployment on Jetty works by detecting/scanning for changes in the webapp and performing a webapp restart.
This works great with content, like html, js, css, etc.
Project JAR dependencies, which will wind up as part of the WEB-INF/lib
structure, are part of the Jetty WebAppContext's [WebAppClassLoader
].
This WebAppClassLoader is populated from information provided by Maven's artifact resolution system, which on a normal command line build resolves to content via the Maven local repository system. If you are using maven from Eclipse, the resolution of these artifacts might be other projects in your Eclipse workspace (more on this later)
To demonstrate, this is the minimal configuration for scanning for changes every 2 seconds on your webapp.
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.1.0.v20131115</version>
<configuration>
<scanIntervalSeconds>2</scanIntervalSeconds>
<webAppConfig>
<contextPath>/</contextPath>
</webAppConfig>
</configuration>
</plugin>
Lets say you have a dependant project, a jar file under the maven artifact coordinates of com.company:component:jar:1.0-SNAPSHOT
.
That means the WebAppContext was loaded with a WebAppClassLoader reference to a URL of file://${user.dir}/.m2/repository/com/company/component/1.0-SNAPSHOT/component-1.0-SNAPSHOT.jar
and only changes to that file will cause a hot deploy / reload.
Its simple enough on a command line in your /component/
directory to just issue a mvn clean install
and see your webapp reload, but under Eclipse and its m2e
plugin, a code change to the component
project does not automatically represent a change to the jar file in your local repository.
In fact, m2e can be configured to swap out maven artifact references via the local repository for ones in your eclipse workspace. You need to be aware of theses settings to have success with your hot deploy / reload efforts.
Tip for figuring out your active WebAppClassloader contents
Add the following file to your war project.
src/main/jetty/dump.xml
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
"http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Set name="dumpAfterStart">true</Set>
</Configure>
And change your jetty-maven-plugin
configuration to add ...
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
...
<jettyXml>src/main/jetty/dump.xml</jettyXml>
</configuration>
</plugin>
Now when your server starts, look for the extra output, particularly the WebAppClassLoader references.
...(snip)...
| | |
| | +> WebAppClassLoader=Web App Live@39714203
| | | +- file:/home/joakim/code/stackoverflow/samples/webapp-live/target/classes/
| | | +- file:/home/joakim/.m2/repository/org/eclipse/jetty/demo/component/1.0-SNAPSHOT/component-1.0-SNAPSHOT.jar
| | | +- ClassRealm[plugin>org.eclipse.jetty:jetty-maven-plugin:9.1.0.v20131115, parent: sun.misc.Launcher$AppClassLoader@77fe0d66]
...(/snip)...
You can see that my jetty:run
has a reference to the component
via the local repository.
Upvotes: 2