Category: Java

  • Property substitution in web.xml and the Jetty Plugin

    Many web applications are configured via web.xml.

    Primary examples of this are Comet web application, which are configured via a ServletContextAttributeListener: you may want different listener classes depending on the enviroment you’re working in.

    Another example is where Spring configuration files are provided via the contextConfigLocation context parameter.

    Here I want to show how to do property substitution in web.xml based on Maven2 profiles.

    Let’s start from the case where you don’t need property substitution.
    These are your web.xml and pom.xml files:

    // web.xml
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
    <listener>
    <listener-class>com.acme.CometInitializer</listener-class>
    </listener>
    </webapp>
    // pom.xml
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <build>
    <plugins>
    <plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>maven-jetty-plugin</artifactId>
    <version>6.1.15</version>
    <configuration>
    <scanIntervalSeconds>10</scanIntervalSeconds>
    <connectors>
    <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
    <port>8080</port>
    </connector>
    </connectors>
    <webAppConfig>
    <contextPath>/</contextPath>
    </webAppConfig>
    </configuration>
    </plugin>
    </plugins>
    </build>
    </project>
    

    As you can see, the pom.xml file specifies the Jetty plugin configuration, with no particular configuration needed: default values are good.
    The web.xml file specifies a listener class that initializes your Comet web application.

    Often times, however, you want your initializer to configure the application differently, for example by stubbing some functionality; as the initializer is complex, you write a different class.

    At this point, you want to be able to specify a Maven2 profile that modifies the web.xml with the suitable class (default or stubbed).
    Here’s how you do it:

    // web.xml
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
    <listener>
    <listener-class>${initializer.class}</listener-class> (1)
    </listener>
    </webapp>
    // pom.xml
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <build>
    <resources> (2)
    <resource>
    <directory>${basedir}/src/main/resources</directory>
    </resource>
    <resource>
    <directory>${basedir}/src/main/webapp/WEB-INF</directory>
    <includes>
    <include>web.xml</include>
    </includes>
    <filtering>true</filtering>
    <targetPath>${project.build.directory}</targetPath>
    </resource>
    </resources>
    <plugins>
    <plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>maven-jetty-plugin</artifactId>
    <version>6.1.15</version>
    <configuration>
    <scanIntervalSeconds>10</scanIntervalSeconds>
    <connectors>
    <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
    <port>8080</port>
    </connector>
    </connectors>
    <webXml>${project.build.directory}/web.xml</webXml> (3)
    <webAppConfig>
    <contextPath>/</contextPath>
    </webAppConfig>
    </configuration>
    </plugin>
    <plugin> (4)
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
    <webXml>${project.build.directory}/web.xml</webXml>
    </configuration>
    </plugin>
    </plugins>
    </build>
    <profiles> (5)
    <profile>
    <id>default</id>
    <activation>
    <activeByDefault>true</activeByDefault>
    </activation>
    <build>
    <filters>
    <filter>${basedir}/src/main/filters/default.properties</filter>
    </filters>
    </build>
    </profile>
    <profile>
    <id>stubs</id>
    <build>
    <filters>
    <filter>${basedir}/src/main/filters/stubbed.properties</filter>
    </filters>
    </build>
    </profile>
    </profiles>
    </project>
    // default.properties
    initializer.class=com.acme.CometInitializer
    // stubbed.properties
    initializer.class=com.acme.CometStubbedInitializer
    

    Let’s review the changes step by step.

    1. We replaced the listener class with a property in the web.xml file.
    2. We added a resources section in the pom.xml file to reference both the standard resource location and the web.xml file.
      For the web.xml file we specified that the property-substituted version of the file must go in the standard maven output directory (by default ${basedir}/target, referenced as ${project.build.directory}).
    3. We added the <webXml> element in the Jetty plugin configuration, referencing the property-substituted version of web.xml.
    4. We added the configuration for the war plugin, so that building the war will reference the property-substituted version of web.xml.
    5. We created two profiles that reference different filter files, which will contain the property values to be substituted. The standard Maven2 location for filter files is src/main/filters.

    Now you can build your project as before by specifying the profile if you need the stubbed version, like this:

    // Normal build
    $ mvn clean install
    // Stubbed build
    $ mvn -Pstubbed clean install
    // Stubbed build with Jetty plugin
    $ mvn -Pstubbed jetty:run
    

    Enjoy !

  • GWT 1.6 HostedMode now using Jetty

    GWT 1.6 RC is out and a new feature shines: the new HostedMode is based on Jetty.

    From the release notes:
    “Although the legacy GWTShell still uses an embedded Tomcat server, the new HostedMode runs Jetty instead. There is also a new “Restart Server” button on the main hosted mode window. Clicking this button restarts the internal Jetty server, which allows Java code changes to take effect on the server without having to completely exit and restart hosted mode. This is useful when making code changes to RPC servlets, or when serializable RPC types are modified and the server and client are out of sync.”

  • Cometd + Wicket

    First off, I think I like wicket, its a pretty neat framework and it has some pretty solid integration with ajax which is interesting. I have to say though that having spent a lot of time on the whole long polling, ajax push, cometd type of communication approach the whole idea of ajax polling back to a server for a bit of content seems kinda quaint.
    Some things I like about wicket are that you work in java for all the pages and models, etc and you still let html pages and css and all that kinda stuff work for those people that like working with them for layout, etc. There is no xml configuration for anything, things are woven together in the java which is pretty nice to work with. I did have a chuckle at Martijn Dashorst’s ApacheCon08 presentation where a major feature of wicket was that there was no xml configuration. Seems like not long ago that was a preeminent feature of coolness in application frameworks.
    After playing around with a few wicket examples I had to start looking into how wicket and cometd could work together. Enter the awesome wicketstuff project and the recent efforts of Rodolfo Hansen with the wicketstuff-push project. This is a pretty neat initial foray into meshing two great things together. For the cometd integration, the current status of things is that cometd is being used as a notification mechanism more then anything, not really a conduit for information transfer as in more traditional cometd apps. In the chat example provided, you click on the message and it makes a wicket ajax post back to the server, where the response has listeners attached for cometd notification, the message is taken in and cometd pushes out to all of the attached clients that something has happened and then the browser makes a wicket ajax request to get the updated information.
    So its a chatty endeavor, but as for melding the convenience of a more traditional web framework like wicket with cometd its not _terrible_ by any means. It really does highlight one of the fundamentally hard problems with something like cometd in my mind. It is not hard to use cometd and get the benefits of the server push to client when your working with a lot of javascript on the client, that environment is very suitable for processing json based information returned in cometd messages from a server. Javascript is simply awesome for that kind of processing, but when most of your brains (web framework) live on the server is it harder to ‘push’ out that sort of information since formatting and data presentation isn’t specifically managed on the browser. For example, the wicketstuff-push example doesn’t use cometd to bring the actual text of any chats from the server, instead it ‘wakes up’ the client and the client calls back with wicket ajax and gets back dom statements to execute to ‘update’ the chat box. In the normal cometd examples all of that information is getting returned in json markup and then evaluated by javascript.
    I am not really sure what the answer is there, perhaps as cometd continues to gain more momentum as a protocol then we’ll end up with generic cometd enabled ajax components for web frameworks like wicket. That might be pretty cool…

  • Jetty and OSGI at Eclipse

    The last several months have brought a lot oof hangs with the jetty OSGI bits and piecesa of things at eclipse. We have finally standardized the way we distribute our binaries within our various p2 repositories. We have a honest to goodness WTP adaptor for jetty that people can use. We have contributed to both Helios and indigo and have had at least one of our other bundles picked up and contributed to another project (the junit pde testing bundle)
    First a bit about how we are distributing the bundles. Underneath the normal download location of http://download.eclipse.org/jetty we have the updates directory which has jetty-bundles-7.x and jetty-wtp underneath which are composite p2repositories. This location will be the standard place to consume our eclipse signed bundles from. There will be a jetty-bundles-8.x location once we iron out the source locations of the jsp-2.2 dependencies in jetty8. Underneath these top level composite p2repositories we have a development directory which is populated from the hudson.eclipse.org buld server. For the WTP bundles the development repository is being populated with each build. We do this in part so we are certain that our bundles are successfully making it through the whole eclipse signing and packing process. Since the velocity of change in these bundles are not extreme it seems minor to be doing the signing and packing process like is. The benefit is that once tested the development directory can be renamed into a proper version and added into the composite metadata.