Embeded Glassfish for Integration Tests

Sun Glassfish server can be run in embeded mode, very useful for automated integration tests. Here’s how:

Maven Dependencies:

<dependency>
  <groupId>org.glassfish.distributions</groupId>
  <artifactId>web-all</artifactId>
  <version>10.0-build-20080430</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.glassfish.embedded</groupId>
  <artifactId>gf-embedded-api</artifactId>
  <version>1.0-alpha-4</version>
  <scope>test</scope>
</dependency>

If you are not using maven then add the above libs to you classpath. Getting the server started in simple

final URI APP_URI= UriBuilder.fromUri("http://localhost/").port(8888).path("myapp").build();
GlassFish server= new GlassFish(BASE_URI.getPort());
ScatteredWar war = new ScatteredWar(APP_URI.getRawPath(),
   new File("src/main/webapp"),
   new File("src/main/webapp/WEB-INF/web.xml"),
   Collections.singleton(new File("target/classes").toURI().toURL()));
server.deploy(war);

You can then use any HTTP Client to send a HTTP Request to the server on a defined port. For automated integration tests use TestNG “dependsOnMethods” feature to ensure that the server was started before executing you integration test group(s). You can then have anther test which depends on your integration test group(s) to ensure that the server is stopped when tests have finished.

You can stop the server with server.stop(). Note: If you are using Maven then using cargo to bring up the server may be more advisable.

Maven Mutli-Project Thoughts and Guidelines

Maven multi-project stucture can get quite difficult to manage once you have a relatively deep hierarchy and more than a few projects. Looking at one such complex structure I found that much of this complexity can be avoided by carefully looking at the relation between parent and child projects and understanding why the projects have been split in the first place.

Maven allows composition and association type relationships between parent and children POMs (projects). The composition relation is expressed by including the child in the <modules> element of the parent POM and refering to the parent from the child POM. The association type relation is expressed by only refering to the parent from the child POM.

This all seams fairly straight forward until you start thinking about your release strategy. In a composition relationship all child modules must be released with the parent so that if you want to release changes in a child module then ideally you should release it as part of a full release of it’s parent. Notice I say “must” even though maven allows you to release the children individually. Well, if you can think of scenarios where the child may be released independently of the parent then surely a composition type relationship is not appropriate?

Another guideline I find useful is to maintain exactly the same versions for all projects in a composition relationship since they must be released together. Assosiation type releasions ships should always refer to a released version of it’s parent.

Lastly project hierarchies are not the only way to share common POM setups and dependencies. The other option is to use maven profiles. Typically you’d have a combination of a hierarchical project simplified by use of maven profiles.

Creating and using a maven archetype

The best way to create a maven archetype is to start with an existing project. In the maven project (simple or multiple-module) directory execute:

mvn archetype:create-from-project

The archetype is created under target/generated-sources/archetypes with the following directory structure:

+---src
    +---main
        +---resources
            +---archetype-resources
            ¦   +---src
            ¦       +---main
            ¦           +---java (directory containing your java sources)
            ¦           +---resources (directory containing your non-java sources)
            ¦           +---webapp
            ¦               +---META-INF
            ¦               +---WEB-INF
            ¦                   +---jsp
            ¦
            +---META-INF
                +---maven (directory containing archetype-metadata.xml)

The archetype-metadata.xml can used used to further tune the archetype. This file describes filesets of the following format:

<fileSets>
  <fileSet filtered="true" packaged="true" encoding="UTF-8">
    <directory>src/main/java</directory>
    <includes>
      <include>**/*.xml</include>
      <include>**/*.java</include>
    </includes>
  </fileSet>
</fileSets>

If the filtered property is set to true then all ${reference} are resolved. The built-in references are: groupId,version,artifactId,rootArtifactId,package .... If packaged is set to true then a directory tree representing the package is created before the resources are copied. Remember these are Velocity templates so you should be able to use Velocity control statements (note: I’ve not tried these yet)

Once you are happy with the archetype you can execute mvn install to install the archetype. This archetype should now appear in the list when you execute mvn archetype:generate. You can release the archetype if you have your own remote repository. You will however need to create a achetype-catalog.xml if you want other users to use this archetype from your own remote repository. The archetype-catalog.xml file should look like the following:

<?xml version="1.0" encoding="UTF-8"?><archetype-catalog>
  <archetypes>
    <archetype>
      <groupId>my.group</groupId>
      <artifactId>an-archetype</artifactId>
      <version>0.0.1</version>
      <description>my example archetype</description>
      <repository>http://repository-host/nexus/content/repositories/releases</repository>
    </archetype>
  </archetypes>
</archetype-catalog>

You can then use this archetype to create a project using the following command:

mvn archetype:generate -DarchetypeCatalog=http://<uri-path>/archetype-catalog.xml