Wednesday, 19 January 2011

Creating a Web Application Bundle Using Maven

Before explaining how to create a Web Application Bundle (WAB) it is worth reviewing what a WAB is. A WAB is basically a bundle that is structured like a WAR, but with OSGi classloading rules. It is a valid bundle, and also looks like a valid WAR (although it doesn't necessarily end in the .war extension, usually .jar is good enough).

A typical WAB might look like this:
META-INF/MANIFEST - containing all the normal OSGi info
WEB-INF/web.xml - the normal web deployment descriptor
WEB-INF/classes - class files and resources visible via the classloader
WEB-INF/lib/a.jar - a jar file
index.html
index.jsp
images/icon.png
style/style.css

The important thing about this is META-INF, WEB-INF (and OSGI-INF) are special in that content is not served up. As a result you want program metadata and classfiles to be in here, since they don't make up part of the web content. The web content goes into the root of the bundle.

Prior to the latest release of the maven-bundle-plugin you could either use the maven-war-plugin to generate a war with a manually created manifest, or you could create a maven-bundle-plugin at which point you would not end up with a valid WAB. You would get the classes, resources and static content mixed together in the root of the bundle. This did not produce good WABs.

With version 2.2.0 of the maven-bundle-plugin which was released this week by the Apache Felix project we have a new option. We can tell the plugin we want to create a WAB.

It is important to understand how the maven-bundle-plugin builds WABs to get this working. The maven-bundle-plugin under the covers makes use of the bnd tool. To get it to build you tell it you want to create a WAB and it relocates everything on the classpath so it is in WEB-INF/classes.

If you take the approach we did in the Apache Aries project for the 0.1 and 0.2 releases your project might be structured with java source in src/main/java and static content in src/main/resources. The upshot of this is if you just specify the following in the configuration for the maven-bundle-plugin:

<_wab/>

All the static content moves into WEB-INF, this is obviously a bad thing because it is no longer served by the web container.

So what we did for the 0.3 release was we moved the static content from src/main/resources and into the src/main/webapp directory. Then we added the following:
<_wab>src/main/webapp/</_wab>
This means everything in src/main/java is compiled and put in WEB-INF/classes. Everything in src/main/resources is put in WEB-INF/classes. This is pretty much what you would expect because these locations are used to put files that are loadable via the classloader. The content in src/main/webapp is then placed in the root. In fact in this scenario you put the web.xml in the src/main/webapp/WEB-INF directory, and if your WAB contains blueprint your blueprint would go in src/main/webapp/OSGI-INF/blueprint.

Alasdair

4 comments:

Matt Bishop said...

This is great, except for the part where you leave out exactly how to tell maven to build a WAB. Is it a new type like bundle?

Harsha Hegde said...

Yes, i agree to the previous point, but i could later figure out the packaging still will be bundle and the produced archive will have the extension .jar

Anonymous said...

Decided in the end to go for a 3-phase setup bound to a profile:

1) war:exploded on process-classes phase -> ${project.build.directory}/war_exploded
2) bundle:manifest on process-classes phase -> manifestLocation = ${project.build.directory}/war_exploded/META-INF
3) assembly:single -> assemblydescriptor that packages the war_exploded dir into a single jar file.

Devi.Angularjs said...

Hibernate Training Institutes in ChennaiHibernate Training Institutes in Chennai Hibernate Online Training Hibernate Online Training Hibernate Training in Chennai Hibernate Training in Chennai Java Online Training Java Online Training