TomEE comes with a bundle for the EE API. It means all EE API not provided by Tomcat (JSP, EL, Jaspic, Servlet...) are in a single jar called javaee-api.jar. This is fine and actually nice cause it allows to identify the jar easily and avoids to have ~28 mode jars in tomee lib folder.

However how can you upgrade a specification API with such a choice?

Side note: the solutions presented there are explained in the context of Arquillian but can be used for a standalone instance.

common.loader: quick and dirty

A first quick and dirty solution is to configure common.loader to list the new API before TomEE libraries:

  • Create a catalina.properties in conf folder
common.loader="location/to/the/new/spec.jar","${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
  • Then in arquillian.xml set conf property to this conf folder, for instance:
<?xml version="1.0"?>
<arquillian xmlns="http://jboss.org/schema/arquillian"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="
              http://jboss.org/schema/arquillian
              http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
  <container qualifier="tomee" default="true">
    <configuration>
      <property name="conf">src/test/conf</property>
    </configuration>
  </container>
</arquillian>

Why is it dirty? Cause we rely on the fact Tomcat (so TomEE) uses a URLClassLoader and that the order is generally respected. There is no guarantee about that actually but it is often enough.

The clean way: remove/add the spec you don't want

What's the need? Replace a (specification) jar. If you check, javaee-api is actually a bundle of N jar and TomEE has the nice idea to deliver a zip of these jars on central. It means you can grab a zip, extract all but a few jar from there and replace javaee-api.jar bundle by a set of jars.

How to do it?

  • With maven, start by unpacking in target/ee-api the zip excluding jars already present in Tomcat and the jars you want to replace:
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <version>2.10</version>
  <executions>
    <execution> <!-- override some ee api -->
      <id>unpack-ee-api</id>
      <phase>generate-test-resources</phase>
      <goals>
        <goal>unpack</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/ee-api</outputDirectory>
        <artifactItems>
          <artifactItem>
            <groupId>org.apache.tomee</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0-1</version>
            <type>zip</type>
            <!--
            in this sample we want to replace geronimo-json_1.0_spec (JSON-P),
            other jars are tomcat ones
            -->
            <excludes>
              LICENSE,NOTICE,README.txt,
              geronimo-jaspic_1.0_spec*jar,
              geronimo-jsp_2.2_spec*.jar,
              javaee-api*.jar,
              tomcat-el-api*.jar,
              tomcat-servlet-api*.jar,
              tomcat-websocket-api*.jar,
              geronimo-json_1.0_spec*.jar
            </excludes>
          </artifactItem>
        </artifactItems>
      </configuration>
    </execution>
  </executions>
</plugin>
  • Then configure TomEE to add this folder to tomee lib folder:
<?xml version="1.0"?>
<arquillian xmlns="http://jboss.org/schema/arquillian"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="
              http://jboss.org/schema/arquillian
              http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
  <container qualifier="tomee" default="true">
    <configuration>
      <property name="lib">${project.build.directory}/ee-api</property>
    </configuration>
  </container>
</arquillian>
  • Finally remove javaee-api bundle and add your new API jar (geronimo-json one there)
<property name="additionalLibs">
  remove:javaee-api
  mvn:org.apache.geronimo.specs:geronimo-json_1.1_spec:${geronimo-jsonp.version}
</property>

Here we see something really nice about TomEE Arquillian adapter: additionalLibs allows to add container libraries by path but also by maven coordinates and to remove built-in ones!

The not explained solutions

Of course there are other ways to achieve it but they are a bit more complex generally, at least if your goal is just to upgrade a specification:

  • build a custom TomEE distribution and use it instead of the plain TomEE
  • wrap TomEE arquillian adapter in a custom adapter to do this job automatically or with custom configuration
  • customize the CLASSPATH to add the library automatically at the beginning when TomEE adapter will launch the TomEE process
  • ...

All these solutions work but require more setup so the previous solution is likely the most flexible and reliable.

Conclusion

With such setup you can now start using EE 8 libraries without waiting TomEE to upgrade and release!

Tip: all tips of this post are also doable with tomee-maven-plugin which will also offer you to build a custom TomEE distribution which can open you some doors ;).

From the same author:

In the same category: