The GlassFish container is rather special, given that GlassFish itself runs on top of an OSGi framework and lets you deploy not only Java EE modules but also OSGi bundles.

Pax Exam's GlassFish container is an extended version of the OSGi Native Test Container. GlassFish is running in pure OSGi mode in an OSGi framework launched by Pax Exam.

The Pax Exam driver, the OSGi framework and GlassFish all run in the same Java VM, so this is an embedded usage of GlassFish. However, this setup is sigificantly different from using an Embedded GlassFish distribution, where GlassFish is contained in a shaded JAR running in a plain old Java SE environment without any OSGi support.

Thus, Pax Exam lets you test and explore hybrid applications, a mixture of traditional Java EE modules and OSGi bundles.

This is the standard lifecycle of the GlassFish container:

  1. If the directory configured in pax.exam.glassfish.home is empty or does not exist, the GlassFish 3.1.2 distribution Maven artifact is downloaded and installed in that directory.
  2. All files from the directory configured in pax.exam.glassfish.config.dir (defaulting to src/test/resources/glassfish-config) are copied to glassfish/domains/domain1/config/.
  3. If pax.exam.glassfish.home is non-empty, Pax Exam does not copy any configuration files and works with the existing installation in that directory, throwing an exception if the GlassFish bootstrap bundle cannot be found in the expected place.
  4. An OSGi framework is launched.
  5. The GlassFish bootstrap bundle is installed and started, thus starting the GlassFish server.
  6. Any additional bundles configured by the user are installed and started.
  7. Any Java EE modules configured by the user are deployed.
  8. In OSGi mode, a bundle probe is built, installed and started.
  9. In Java EE mode, a WAR probe is built and deployed.
  10. All tests contained in the probe are executed within the container.
  11. All Java EE modules (including the WAR probe, if any) are undeployed.
  12. GlassFish is stopped.
  13. All OSGi bundles are uninstalled.
  14. The OSGi framework is stopped.
  15. The framework storage is deleted (depending on the configuration options).

Current restrictions:

  • GlassFish container runs on Equinox by default. There is no configuration option to use Felix.
  • Since SLF4J + logback is the preferred logging solution in Pax Exam 3, the default java.util.logging of GlassFish is redirected to SLF4J. There is no way to use Pax Logging or the default GlassFish JUL.
  • You can only deploy WAR modules. EARs, EJB JARs or RARs are not supported.
  • Pax Exam uses the default GlassFish domain domain1. This cannot be changed.
  • Any domain-level libraries (e.g. JDBC drivers) need to be installed manually in the appropriate subdirectory of pax.exam.glassfish.home.
<!-- Pax Exam -->
<dependency>
    <groupId>org.ops4j.pax.exam</groupId>
    <artifactId>pax-exam-container-glassfish</artifactId>
    <version>${exam.version}</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.ops4j.pax.exam</groupId>
    <artifactId>pax-exam-junit4</artifactId>
    <version>${exam.version}</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.ops4j.pax.exam</groupId>
    <artifactId>pax-exam-servlet-bridge</artifactId>
    <version>${exam.version}</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.ops4j.pax.exam</groupId>
    <artifactId>pax-exam-cdi</artifactId>
    <version>${exam.version}</version>
    <scope>test</scope>
</dependency>

<!-- OSGi runtime dependencies -->
<dependency>
    <groupId>org.ops4j.pax.exam</groupId>
    <artifactId>pax-exam-link-assembly</artifactId>
    <version>${exam.version}</version>
    <scope>test</scope>
</dependency>

<!-- protocol handlers -->
<dependency>
    <groupId>org.ops4j.pax.url</groupId>
    <artifactId>pax-url-link</artifactId>
    <version>${url.version}</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.ops4j.pax.url</groupId>
    <artifactId>pax-url-aether</artifactId>
    <version>${url.version}</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.ops4j.pax.url</groupId>
    <artifactId>pax-url-classpath</artifactId>
    <version>${url.version}</version>
    <scope>test</scope>
</dependency>

<!-- OSGi framework -->
<dependency>
    <groupId>org.eclipse.tycho</groupId>
    <artifactId>org.eclipse.osgi</artifactId>
    <version>3.6.2.R36x_v20110210</version>
    <scope>test</scope>
</dependency>

<!-- Java EE APIs -->
<dependency>
    <groupId>org.apache.geronimo.specs</groupId>
    <artifactId>geronimo-atinject_1.0_spec</artifactId>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.apache.geronimo.specs</groupId>
    <artifactId>geronimo-jpa_2.0_spec</artifactId>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.apache.geronimo.specs</groupId>
    <artifactId>geronimo-ejb_3.1_spec</artifactId>
    <scope>provided</scope>
</dependency>

<!-- Logging -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>0.9.29</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>0.9.29</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
    <scope>test</scope>
</dependency>

The GlassFish Container downloads and install a GlassFish 3.1.2 server or uses an existing one to deploy and run your tests.

In addition, you need pax-exam-junit4 as a driver to run your tests, pax-exam-servlet-bridge for driver-probe communication and pax-exam-cdi to provide dependency injection for your tests.

pax-url-aether is only required if you use the mvn: protocol or if you want the container to download GlassFish.

The subset of Java EE APIs depends on your application and your tests. We recommend using the Geronimo API artifacts instead of the official javax:javaee-api:6.0, since the latter contains mutilated byte code which causes exception when this artifact is used at runtime.

Finally, there is a group of logging artifacts, redirecting all log output both from Pax Exam and from GlassFish to logback via SLF4J.