TomEE + Arquillian: upgrade EE API
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: