RSS feed
<< Back from a fantastic Java Posse Roundup 2009 | Home | Introducing lightning talks in your organization >>

Make your war file executable with the Jetty Console Maven plugin

A while back I made a little Maven plugin that takes a war file and makes it executable. With executable I mean that it embeds a Jetty servlet container. Running java -jar myapp.war will deploy your war with the embedded Jetty instance.

This provides a very convenient distribution method for Java web applications. It lets you distribute your application as a single artifact. Your users are no longer forced to install a big and ugly app server just to run your app.

But if they really want to, the war is still a war file that can be deployed the "normal" way in Tomcat, Glassfish, Weblogic, Websphere or any servlet compliant web server. (You tell me you actually use Websphere? Seriously!?).

With a single distribution in a single file, there's also less chance of your users getting confused about how to get your application running.

Jan Bartel of Jetty fame asked for a link describing this plugin and since I didn't really have any thing useful, here's a blog post:

An example: The Puffin Secrets Webapp

Meet the Puffin Secrets webapp. This very small, yet very useful web application let us listen in on the puffins while they chat about Jetty:


Since puffins are a bit shy, we need to click the button to see what they really think about Jetty:


To make this war file executable, we need to add a bit of plugin configuration to our Maven pom.xml:

<plugin>
<groupId>org.simplericity.jettyconsole</groupId>
<artifactId>jetty-console-maven-plugin</artifactId>
<version>1.23</version>
<executions>
<execution>
<goals>
<goal>createconsole</goal>
</goals>
</execution>
</executions>
</plugin>

After running mvn clean install, we should now have a target directory looking like this:


Notice the -jetty-console.war version of your war file. This war file is now runnable with java -jar (On a Mac it's actually double-clickable!). Running the war will start a little Swing console (unless run on a server):


The flies are there to remind you that you probably have bugs in your code. Still you might want to use a less generic background image. This can be done by adding the following configuration:


<plugin>
<groupId>org.simplericity.jettyconsole</groupId>
<artifactId>jetty-console-maven-plugin</artifactId>
<version>1.23</version>
<executions>
<execution>
<goals>
<goal>createconsole</goal>
</goals>
<configuration>
<backgroundImage>${basedir}/src/main/jettyconsole/puffin.jpg</backgroundImage>
</configuration>
</execution>
</executions>
</plugin>


This gives us a much more puffin-relevant background:


The console is currently pretty simple. It allows the user to select a port and start the application. As a convenience the console will open a browser with the correct URL. This saves the user some seconds. (When demoing a product, seconds matter!)

Command line options

While the graphical console is nice for demoing an application or distributing it to testers, for installation on a server we need some command line interaction. You can see a list of available options by typing java -jar myapp.war --help

Usage: java org.simplericity.jettyconsole.JettyConsoleStarter [--option=value] [--option=value]

Options:
--sslProxied - Running behind an SSL proxy
--port n - Create an HTTP listener on port n (default 8080)
--bindAddress addr - Accept connections only on address addr (default: accept on any address)
--forwarded - Set reverse proxy handling using X-Forwarded-For headers
--contextPath /path - Set context path (default: /)
--headless - Don't open graphical console, even if available
--help - Print this help message
--tmpDir /path - Temporary directory, default is /tmp

Plugins

The core of the Jetty console is intentionally kept as small as possible. Additional functionality can be included by adding plugins to your plugin configuration. You might want to add the log4j plugin:

<configuration>
<backgroundImage>${basedir}/src/main/jettyconsole/puffin.jpg</backgroundImage>
<additionalDependencies>
<additionalDependency>
<artifactId>jetty-console-log4j-plugin</artifactId>
</additionalDependency>

</additionalDependencies>
</configuration>

This should give you an extra option when running --help :

Usage: java org.simplericity.jettyconsole.JettyConsoleStarter [--option=value] [--option=value]

Options:
--sslProxied - Running behind an SSL proxy
--port n - Create an HTTP listener on port n (default 8080)
--bindAddress addr - Accept connections only on address addr (default: accept on any address)
--forwarded - Set reverse proxy handling using X-Forwarded-For headers
--contextPath /path - Set context path (default: /)
--headless - Don't open graphical console, even if available
--help - Print this help message
--tmpDir /path - Temporary directory, default is /tmp
--logConfig file - Read log4j configuration from file

The other plugins currently available are:

ajp: Lets you configure an AJP connector in Jetty
requestlog: Allows you to log requests to an access log for traffic analysis
jsp: Adds JSP support to your application
jettyxml: Allows you to apply arbitrary Jetty XML configurations to your Server or WebAppContext
gzip: Compresses your HTML, CSS and Javascript for bandwidth savings

If the available plugins don't match your needs, it's quite easy to make your own and include it with in <additionalDependencies/>. <additionalDependencies/> can also be used to add normal Maven dependencies, such as a database driver referred to in jetty.xml

Maven repository configuration

Since this plugin is not (yet) in the Maven Central repository, you'll need to add a pluginRepository to your pom.xml:

<pluginRepositories>
<pluginRepository>
<id>kos</id>
<url>http://opensource.kantega.no/nexus/content/groups/public/</url>
</pluginRepository>
</pluginRepositories>

<repositories>
<repository>
<id>kos</id>
<url>http://opensource.kantega.no/nexus/content/groups/public/</url>
</repository>
</repositories>

The complete puffin example webapp is available in Subversion here:

http://simplericity.org/svn/simplericity/trunk/jetty-console-example/



Re: Make your war file executable with the Jetty Console Maven plugin

Nice work. I've done similar things, but not packaged it together like this. Looks cool.

Re: Make your war file executable with the Jetty Console Maven plugin

Simple
Non-intrusive
Visual
Extendable

Re: Make your war file executable with the Jetty Console Maven plugin

That's a great plug-in and a nice write up of it. Just reason 23,410 NOT to complain about Maven. I'll be using this in the future for sure. Nice work!

One thing though, you can double click and open it in Windows if you have .jar files set to "Open With" Java.exe.

Re: Make your war file executable with the Jetty Console Maven plugin

Joseph: Glad you liked the plugin!

I usually pretend not to know much about Windows. It saves me from doing a lot of friends and family tech support :-)

Re: Make your war file executable with the Jetty Console Maven plugin

Hi,
nice plugin, but i have one problem on startup. I getting an exception:Exception in thread "main" java.lang.NoClassDefFoundError: org/simplericity/macify/eawt/ApplicationAdapter
i add macify as dependency but it doesnt help :/

Re: Make your war file executable with the Jetty Console Maven plugin

Mustafa,

What operating system and JVM version are you on? I'd like to be able to reproduce your problem

Could it be OS X Snowleopard?

Re: Make your war file executable with the Jetty Console Maven plugin

Wow!
This plugin totally rocks! Great work!
Thanks you saved my day!

Re: Make your war file executable with the Jetty Console Maven plugin

Love the plugin. Fantastic!

One question: is there a way to incorporate custom manifest information? In my case, I need to include the build time, as I would with the maven-war-plugin:

                    <archive>
                        <manifestEntries>
                            <Implementation-Build>${build.timestamp}</Implementation-Build>
                        </manifestEntries>
                    </archive>

Thanks,
Dave

Re: Make your war file executable with the Jetty Console Maven plugin

Great plugin.
I wish it was possible to specify a URL for the background image though

Re: Make your war file executable with the Jetty Console Maven plugin

It would also be nice if it started the default browser instead of IE

Re: Make your war file executable with the Jetty Console Maven plugin

Never mind this last comment about default browser, my environment was screwed up.

Re: Make your war file executable with the Jetty Console Maven plugin

Any progress on getting this into Maven Central?

don't you want to setup some kind of project page?

would like to see a site for this project with links and some documentation. also link to source.

Re: Make your war file executable with the Jetty Console Maven plugin

This is a great utility. Please consider placing on a mvn repository that keeps up-to-date indexes of its contents. That way your project will get the benefit of being able to be proxied by other repositories and users will not be forced to keep a repository URL in their poms.
Thanks,
Dan

Re: Make your war file executable with the Jetty Console Maven plugin

A very helpful utility, thanks for sharing it.

Re: Make your war file executable with the Jetty Console Maven plugin

Note the executable-war-archetype <http://goo.gl/S1cyI>, used as starting-point in the http://Mifos.org WAR, see http://goo.gl/nwZNE.

Re: Make your war file executable with the Jetty Console Maven plugin

Great Work!!

But, the configuration of manifest and manifest entries in maven-war-plugin are not copied over to the MANIFEST.mf of the war generated by this plugin.. hence one has to specify the same configuration of these to get the same MANIFEST.MF

Yes, there are scenarios even in war, where you might want to set manifest

Re: Make your war file executable with the Jetty Console Maven plugin

Great plugin thanks! You might want to change the default running location from /tmp to . because on Redhat systems, /tmp is cleaned of items older than 30 days - so your application will crash after 30 days as I have discovered!

Re: Make your war file executable with the Jetty Console Maven plugin

Very nice work! There are a number of tutorials/artefacts/hacks out there to accomplish the same, however none is so neatly packaged and polished. Thanks!

Re: Make your war file executable with the Jetty Console Maven plugin

An outstanding plugin - that's one Sprint story that got finished a lot more quickly than estimated ;-)

It's always nice to achieve something significant without introducing a single extra line of code.

Thank you very much!

Thank you

Just to let you know, your plugin now helps tango dancers in Oslo know what they are dancing to. Thank you!

Re: Make your war file executable with the Jetty Console Maven plugin

Hi, I was wondering whether it's possible to embed the options that you'd like to start with, so instead of runing: java -jar org.simplericity.jettyconsole.JettyConsoleStarter --headless --port 8181 you could run: java -jar org.simplericity.jettyconsole.JettyConsoleStarter and have the port and headless options included by default?

Re: Make your war file executable with the Jetty Console Maven plugin

Brian, I'd suggest you create your own plugin which sets the options you want to set. JettyConsole's --port and --headless options are already implemented as plugins, see: http://simplericity.org/svn/simplericity/trunk/jetty-console/jetty-console-core/src/main/java/org/simplericity/jettyconsole/plugins/ConnectorConfigurationPlugin.java and http://simplericity.org/svn/simplericity/trunk/jetty-console/jetty-console-core/src/main/java/org/simplericity/jettyconsole/plugins/HeadlessConfigurationPlugin.java for inspiration. Good luck!

Re: Make your war file executable with the Jetty Console Maven plugin

I had a look at the project in maven, does: <properties> headless port=9090 </properties> not do the trick?

Re: Make your war file executable with the Jetty Console Maven plugin

sorry, I meant the project in SVN. specifically : http://simplericity.org/svn/simplericity/trunk/jetty-console-example/webapp/pom.xml

Re: Make your war file executable with the Jetty Console Maven plugin

That's because the puffin-example project does indeed have a custom plugin which will read that property and set the contextPath accordingly.

See http://simplericity.org/svn/simplericity/trunk/jetty-console-example/plugins/context-path-plugin/ for implementation details.

Re: Make your war file executable with the Jetty Console Maven plugin

so theres no way I can just use the pre-written headless and port plugins that are already written? I have to create a custom one?

Re: Make your war file executable with the Jetty Console Maven plugin

Nope, unfortunately, these plugins do not support overriding default values. I see no reason why they should not, but they just don't :-)


Add a comment Send a TrackBack