In a project I’m currently working on we use the OSGi platform in order to achieve higher modularity (the project is about building a framework for massive data ingestion and processing for a high-availability service, and the processing is dealt with via workflows that are composed of a number of plugins that we don’t develop, hence the need for modularity).

We use the Apache Karaf framework, which offers neat extension points and means to customize it. One of the nice features is the WebConsole that can also be extended, which would provide the means to add a GUI for the users. However, this happens through providing a Servlet implementation, which isn’t really handy these days when wanting to develop a bit more complicated GUIs.

Since I’ve got some experience with Google Web Toolkit I thought of using this instead for coding the GUI (and eventually integrate it with the WebConsole later on, not sure at which level of depth yet). And the first thing necessary in order to do this is to get the GWT application to run on the Karaf platform.

Here’s how I managed to get it work:

Step 1: create a vanilla GWT application with the gwt-maven-plugin

I used the gwt-maven-plugin archetype in order to create a new GWT module. At the time at which I am writing this post, I had some issues with the unit tests that are generated by default, so I just trashed them for the moment.

Step 2: make the GWT application ready for deployment via Pax Exam Runner

Karaf can leverage Pax Runner in order to deploy OSGified WARs. For that, you need to have a MANIFEST.MF generated and attached to the WAR maven generates. There’s two things required for this.

First, configure the Apache Felix maven-bundle-plugin to generate the manifest for you (you could do it by hand, but why bother):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

<plugin>
 <groupId>org.apache.felix</groupId>
 <artifactId>maven-bundle-plugin</artifactId>
 <version>2.1.0</version>
 <extensions>true</extensions>
 <executions>
  <execution>
   <id>bundle-manifest</id>
   <phase>process-classes</phase>
   <goals>
    <goal>manifest</goal>
   </goals>
  </execution>
 </executions>
 <configuration>
  <supportedProjectTypes>
   <supportedProjectType>jar</supportedProjectType>
   <supportedProjectType>bundle</supportedProjectType>
   <supportedProjectType>war</supportedProjectType>
  </supportedProjectTypes>
  <instructions>
   <Bundle-ClassPath>.,WEB-INF/classes</Bundle-ClassPath>
   <Embed-Directory>WEB-INF/lib</Embed-Directory>
   <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
   <Embed-Transitive>true</Embed-Transitive>
   <Import-Package>*;resolution:=optional</Import-Package>
  </instructions>
 </configuration>
</plugin>  

This will generate a manifest which takes into account the required dependencies that come with the WAR, so that it can be deployed by Pax Runner. Note that this isn’t just a configuration for GWT itself, but in theory for any kind of WAR.

Update: I figured out how to customize the webapp name, by adding the following in the manifest instructions:

1
2
3
4
5
<!- OSGi spec config option ->
  
<Web-ContextPath>gui</Web-ContextPath>  
<!- Pax Runner knows this option ->  
<Webapp-Context>gui</Webapp-Context>  

Pax Runner does not understand the OSGi spec instruction, so it needs to be given the instruction.

Next, you need to tell the maven-war-plugin to add the generated manifest file to the WAR:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<plugin>
  <groupId>org.apache.maven.plugins</groupId>  
  <artifactId>maven-war-plugin</artifactId>  
  ...  
  <configuration>  
  ...  
    <archive>  
      <!-- add the generated manifest to the war -->  
      <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>  
    </archive>  
  </configuration>  
...  
</plugin>

Step 3: Activate war deployment support on Karaf

Fire up the Karaf console and type:

1
features:install war

This will activate everything needed in order to deploy WARs on the platform.

Step 4: Deploy the WAR

Now you just need to deploy the WAR on Karaf. You can do this in several ways:

  • by copying the WAR file to the deploy/ directory of the Karaf platform
  • by defining a feature descriptor and adding the war artifact to it

Since we already had a feature descriptor (because we have many bundles that need to be deployed, I just added the artifact to the feature descriptor XML like this:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
  <features name="uim-features">  
    <feature name="uim-core" version="1.0.0.SNAPSHOT">  
      ...  
      <bundle>mvn:eu.europeana/europeana-uim-gui-gwt/1.0.0-SNAPSHOT/war</bundle>  
      ...  
    </feature>  
  </features>  

Note that you need to explicitly reference the “war” classifier, or this won’t work. Now, re-install the feature in order for the changes to take effect.

Step 5: Enjoy

You should see something like this (amongst others) in the log:

1
2
3
4
14:42:50,487 | INFO l Console Thread | WebXmlObserver
| nder.war.internal.WebXmlObserver  128
| 581 - org.ops4j.pax.web.pax-web-extender-war - 0.7.3
| Using [gui] as web application context name</pre>

That’s it, you can access your GWT module at http://localhost:8181/