Pages

Maven and Jetty: A Perfect fit

The jetty-maven-plugin is a real life saver when it comes to developing web applications. In the past I had such horrible experiences with the eclipse WTP plugin that I banned it from my toolset forever.
For a year now I use the jetty-maven-plugin and it makes developing so much easier. In this blog I will give an overview how you can setup your development environment using Maven and Jetty.

When developing webapps on my local machine I set myself the following requirements:

1. I want to be able to edit classes and views (Wicket html files or jsp’s) and see the results in the browser fast without having to build a war file and manually redeploy.
2. I want to be able to switch between an in memory database, typically a Hsqldb and the real target database (Oracle). Since I am using Hibernate as ORM I also need to be able to switch settings like the hibernate.dialect property to match my database.
3. The WAR file produced should also run on the target application server, JBoss in my case.

Let’s see how Jetty fulfills these requirements.

The example project consist of a webapplication using Spring, Hibernate and Wicket. The target platform is JBoss with an Oracle database.

To get started we first need to add the jetty-maven-plugin in the pom.xml of the war project.

[/xml]

  jetty-maven-plugin
	org.mortbay.jetty
	7.0.0pre3
	
		/example-app
		3
		
			
8090
				0.0.0.0
			
		
	

[xml]

That’s it. When running mvn jetty:run the webapplication is available under http://localhost:8090/example-app. For a complete reference of all possible configuration settings I suggest you read http://jetty.mortbay.org/jetty/maven-plugin/run-mojo.html

Fast redeploying.
In my experience, I have no evidence, Jetty is the fastest starting servlet container out there, especially when you compare it with full blown application servers such as JBoss. JBoss is perfect for production and acceptance environments but when developing I have different needs. This is where Jetty gets a big plus.
Regarding redeploying: By default the jetty-maven-plugin automatically reloads/redeploys the webapplication whenever it detects a change. You can use the scanIntervalSeconds and scanTargets configuration properties to tweak change detection. Downside of this automatic reloading is that it will always reload, even if you are just developing for a couple of minutes and save changes in between. Not only does this consume unnecessary resources, it will eventually lead to full PermGen space which results in an OOME.
A way to counter this is to set the reload option of the jetty-maven-plugin to manual. Now reloading will only occur on a linefeed (hitting enter) in the console where you started jetty.

Switching databases
When developing a webapplication I want to be flexible. I want to be able to connect to a fast in memory database, to the target database and to a database that is for instance on a test machine. How can we achieve this with jetty? In my case I have two local databases: a Hsql database and an Oracle database installed on a VMWare image.
Since my Spring context uses a JNDI configured datasource I need to add those in Jetty as well. For this you need to create set the jettyEnvXml property in the jetty-maven-plugin. This property points to the jetty configuration file, called jetty-env.xml, containing the datasource in our case. But we also need to be able to switch hibernate dialect. Since we are using Spring we have the PropertyPlaceHolderConfigurer in our applicationContext in SYSTEM_PROPERTIES_MODE_OVERRIDE mode. This means that system properties override values defined in the applicationContext or the property file (if any). Together with Maven’s profiles we can now configure the jetty-maven-plugin so we can switch databases as needed.

The relevant parts of our pom now look like this:

[/xml]
...

  jetty-maven-plugin
	org.mortbay.jetty
	7.0.0pre3
	
		/example-app
		manual
                ${jetty.env.file}
		
			
8090
				0.0.0.0
			
		
		
			
				hibernate.dialect
				${hibernate.dialect}
			
		
	

...


		jetty-oracle

			${basedir}/src/test/resources/jetty-env-oracle.xml
			org.hibernate.dialect.Oracle10gDialect
		
	

		jetty-hsql

			${basedir}/src/test/resources/jetty-env-hsqldb.xml
			org.hibernate.dialect.HSQLDialect
		
	

[xml]

The contents of the jetty-env-hsqldb.xml is as follows:

[/xml]



	
		jdbc/example
		
			
				org.hsqldb.jdbcDriver
				jdbc:hsqldb:mem:test
				sa
				
			
		
	

[xml]

Via this configuration we are able to switch between Oracle and Hsqldb by specifying the profile at the commandline. For example mvn jetty:run -Pjetty-hsql in case we want the Hsqldb.

Servlet container compatibility
We are almost there. As said before, the example application is using a JNDI configured datasource and refers to it in the applicationContext using a jee:jndi lookup:

[/xml]

[xml]

When deploying the produced WAR file in JBoss it gives an error saying that jdbc is not bound. To get the application up and running in JBoss as well you to follow the steps as described in http://forums.sun.com/thread.jspa?threadID=626778. This is caused by the fact that not all servlet containers have the same way of registering jndi values.

Conclusion
Jetty and Maven go well together. The jetty-maven-plugin provides an easy way to use Jetty in development and enough flexibility to switch for instance databases when developing. I gihly recommend using the jetty-maven-plugin when developing. But make sure you check that the WAR file also runs on your target application server on a daily basis.

4 comments to Maven and Jetty: A Perfect fit

  • Anders M

    Hey!

    Thanks for good guide, but you have written an error. Maybe you copy and pasted. Where it says: manual, shouldn’t it be
    ${jetty.env.file}?

  • lvonk

    Hi Anders, Thanks for spotting the error. I have fixed it in the blog.

    Lars

  • Nice article!

    I was getting annoyed by jetty reloading itself after every save operation. I immediately added the manual to my jetty configuration, but it didn’t work. After upgrading Jetty to the version you mentioned in your article everything worked fine.

  • Pablo

    Nice article. The PermGen space error is not jetty’s fault, it’s your application that has a classloader leak. In one project I worked I managed to solve it and we were able to reload jetty as many times as we wanted.

    Regards.

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>