I don’t know if we’ll get a film after the international success of it but since few months the world is all about microservices.
Whatever your opinion on it is you will surely have to work with it a little bit. One common way to go to production with microservices is to do a shade of your application and simply deploy an executable jar.
Let go through common Microservice solutions which work with TomEE flavors.
TomEE Shades
A shade is a Maven plugin to aggregate project dependencies in a single jar. It can be done with Maven dependency plugin with some hack (basically unpacking all dependencies in target/classes) but Maven shade plugin provides more control over the merge policy thanks to Transformer
API.
To do an executable jar using Maven shade plugin you need to know two information:
- what is the main class
- what files need a specific merging and which policy it needs
All TomEE flavors share the same second point, which we’ll develop just after having tackled the first one.
Specify your Main Class
Depending which flavor of TomEE you use the main will be different but in all cases it will boot your application.
In all cases once you have the main class you will rely on you’ll be able to specify it in Maven shade plugin using the following configuration:
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.myapp.Main</mainClass>
</transformer>
ApplicationComposer
Since TomEE 2.x you can start manually an ApplicationComposer application as a standalone main:
@EnableServices(jaxrs = true)
@Classes(context = "/", value = { MyResource.class, MyService.class })
public class MyApp {
public static void main(String[] args) {
ApplicationComposers.run(MyApp.class, args);
}
}
Just write your own main using ApplicationComposers
and specify it in shade configuration to boot your application.
TomEE Embedded
TomEE embedded is surely one of the best choices for a TomEE shade since it provides a Main class out of the box. Just specify org.apache.tomee.embedded.Main
as the mainClass
in the shade ManifestResourceTransformer
configuration and you are done.
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.apache.tomee.embedded.Main</mainClass>
</transformer>
If you don’t use JSF you should exclude META-INF/faces-config.xml
to ensure JSF is not automatically started. Add the following to your maven-shade-plugin
configuration.
<filters>
<filter> <!-- we don't want JSF to be activated -->
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/faces-config.xml</exclude>
</excludes>
</filter>
</filters>
TomEE (remote)
TomEE remote can be controlled using OpenEJB RemoteServer
class and this is mainly what does tomee:exec
goal. You can also use catalina.sh
commands to start/stop your application.
In all cases the fact TomEE remote needs as a plain Tomcat a particular layout – it is not embedded, it makes it a bit harder to shade.
My advice would be to not try to rely on TomEE remote for an executable jar without using tomee:exec
(detailed later).
Merging of conflicting resources
When using the maven-shade-plugin
and taking the contents of several jars and turning them into one larger jar, it can be common to run into file conflicts that need to be handled.
Some cases, such as META-INF/services/
service providers, are solved smoothly with by shade plugin our of the box with the default configuration. Others require explicit action.
CXF and TomEE need META-INF/cxf/bus-extensions.txt
extensions. Here you’ll get conflicts and you need to ensure merging is the same as the one done automatically for service providers. For it you can just rely onAppendingTransformer
in your plugin config as shown below:
<transformer implementation="org.apache.Maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/cxf/bus-extensions.txt</resource>
</transformer>
Recent OpenWebBeans versions need the build-in configuration files to be merged. Specifically, META-INF/openwebbeans/openwebbeans.properties
files. Even if TomEE tries to ensure defaults are in place it is better to configure it:
<transformer implementation="org.apache.Maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/openwebbeans/openwebbeans.properties</resource>
</transformer>
AppendingTransformer
to ensure we don’t miss any default key but if you want a full control of it in your application you can also merge it manually and provide the file (put it in META-INF/openwebbeans/openwebbeans.properties
in src/main/resources
in your project.Put it all together
So finally Maven shade configuration should look like:
<plugin>
<groupId>org.apache.Maven.plugins</groupId>
<artifactId>Maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.Maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.apache.tomee.embedded.Main</mainClass>
</transformer>
<transformer implementation="org.apache.Maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/cxf/bus-extensions.txt</resource>
</transformer>
<transformer implementation="org.apache.Maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/openwebbeans/openwebbeans.properties</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Then just run:
mvn package
And you can run your application:
java -jar myapp.jar
Feeling Lazy? Try tomee:exec
If you already used tomee-maven-plugin
you are surely use to the tomee:run
command but do you know about tomee:exec
?
The tomee:exec
goal is interesting since it will create an executable jar which will package a tomee distribution already set up with your application and a runner able to unpack it and run it. This works with any Maven war
project, no Maven Shade Plugin or special setup required beyond adding the TomEE Maven Plugin to your pom.xml.
<build>
<plugins>
<plugin>
<groupId>org.apache.openejb.maven</groupId>
<artifactId>tomee-maven-plugin</artifactId>
<version>${tomee.version}</version>
<configuration>
<tomeeVersion>$1.7.1</tomeeVersion>
<tomeeClassifier>jaxrs</tomeeClassifier>
</configuration>
</plugin>
</plugins>
</build>
Once you packaged your application with a mvn clean install tomee:exec
you can run it as easily as:
java -jar target/mytomeeapp.jar
If you want to override or configure the runtime properties passed to TomEE on start, you can use the additionalSystemProperties
system property. So if you provided a server.xml
setting the http port via my.http.port
system property you can run it with:
java -DadditionalSystemProperties=-Dmy.http.port=7080 -jar mytomeeapp.jar
The TomEE Maven Plugin the plugin is also able to attach the produced artifact to the build so you can even publish it.
However as described earlier tomee:exec
relies on two processes:
- The TomEE process itself
- A runner process which waits for the server to shutdown
The runner is a very light process but this is still something you might wish to avoid. Still, very useful and for demos it is just awesome!.
Test it yourself
If you want to go further two samples are available on github: https://github.com/tomitribe/50-shades-of-tomee
One uses ApplicationComposer and the other one is using TomEE Embedded. Both have a README with getting started instructions.
One Comment