TomEE RefCard

Apache TomEE is a JavaEE 6 application server.

This RefCard tries to sum up basic things to know.

TomEE Philosophy

Apache TomEE, pronounced "Tommy", is an all-Apache Java EE 6 Web Profile certified stack where Tomcat is top dog. Apache TomEE is assembled from a vanilla Apache Tomcat zip file. We start with Tomcat, add our jars and zip up the rest. The result is Tomcat with added EE features - TomEE.

Its core values are:

  • Be Tomcat

  • Be certified

  • Be small

TomEE Links
TomEE ClassLoading
bootstrap ($JAVA_HOME/jre/lib/ext)
      |
    system (bin/boostrap.jar:bin/tomcat-juli.jar)
      |
    common (lib/*.jar)
    /    \
webapp1 webapp2

Classloading configuration (properties):

  • openejb.classloader.forced-load=<comma separated list of class name prefixes>: classes to load from the webapp first whatever is in the container

  • openejb.classloader.forced-skip=<idem>: classes to load from the container whatever is in the application

TomEE Basic Operation

Start and wait Ctrl+C

./bin/catalina.sh run

Start and forget

./bin/catalina.sh start

Stop

./bin/catalina.sh stop

Deploy manually a webapp

copy war over webapps/

Redeploy manually a webapp

delete exploded war then deploy

TomEE Distributions
  • TomEE Web Profile: JavaEE 6 Web profile sever (certified)

  • TomEE JAX-RS: previous one + JAX-RS (certified)

  • TomEE+: previous one + JAXWS + JMS + Connectors

TomEE Directory Layout

bin

contains script to manage (start/stop/…) TomEE

conf

server global configuration

endorsed

override JVM API because too old for JavaEE

lib

server libraries

logs

logs directory (using default configuration)

temp

default tmp directory

webapps

default folder which aims to contain webapps

work

folder used by Tomcat to store "work" binaries (compiled jsp…)

Scanning/Loader configuration, conf/catalina.properties
# the main server classloader configuration,
# JDBC drivers go here in general
common.loader=${catalina.base}/lib,\
${catalina.base}/lib/*.jar,\
${catalina.home}/lib,${catalina.home}/lib/*.jar

# other defaults are generally fine
TomEE system properties, conf/system.properties
# handle global configuration
# this file is an alternative
# to JVM system properties -Dxxxx=yyyy

# check libraries
openejb.check.classloader = false

# deploy internal application
# only relevant in dev
openejb.system.apps = true

# deactivate JMX
openejb.jmx.active = false

# where to find the TomEE config file
openejb.conf.file = conf/tomee.xml

# force inclusion/exclusion of packages during classloading
openejb.classloader.forced-load = my.pack1,my.pack2
openejb.classloader.forced-skip = my.pack3,my.pack4

# app ones
my.system.property.config = my value

# more on http://tomee.apache.org/properties-listing.html
Logging configuration, conf/logging.properties
# available handlers for logging: console, file...
handlers = 5tomee.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler

# file handler configuration
# 3 main items: level of the handler, where to log, with wich prefix
5tomee.org.apache.juli.FileHandler.level = FINEST
5tomee.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
5tomee.org.apache.juli.FileHandler.prefix = tomee.

# each category can be configured (ex: OpenEJB)
## level: FINEST > FINE > INFO > WARNING > SEVERE
OpenEJB.level = WARNING

## handler
OpenEJB.handlers = 5tomee.org.apache.juli.FileHandler,\
java.util.logging.ConsoleHandler

# more on tomcat website:
# http://tomcat.apache.org/tomcat-7.0-doc/logging.html
Daemons configuration, conf/conf.d/*.properties

OpenEJB and TomEE rely on daemons for extensibility.

Typically JAXWS and JAXRS uses this feature to be added to the server.

Each daemon can get configuration.

It is configurable through:

  • system properties: <daemon name.<attribute>=value

  • conf/conf.d/<daemon name>.properties

All daemons have a property disabled which can be set to true to deactivate it.

Server configuration, conf/server.xml
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
 <!-- TomEE integration with Tomcat -->
 <Listener className="org.apache.tomee.catalina.ServerListener" />

 <Service name="Catalina">

  <!-- Connectors are entry points (HTTP, AJP...) -->
  <Connector port="8080" protocol="HTTP/1.1" />

  <Engine name="Catalina" defaultHost="localhost">
   <!--
    folder webapps will scanned for webapps
    and webapps will be deployed on localhost
   -->
   <Host name="localhost"  appBase="webapps" />
  </Engine>
 </Service>
</Server>
JAXWS WS Security configuration

It basically relies on openejb-jar.xml (in META-INF or WEB-INF):

A complete example can be found within TomEE examples: webservice-ws-security.

<?xml version="1.0" encoding="UTF-8"?>
<openejb-jar xmlns="http://www.openejb.org/openejb-jar/1.1">
 <ejb-deployment ejb-name="CalculatorImpl">
  <properties>
   # webservice.security.realm
   # webservice.security.securityRealm
   # webservice.security.transportGarantee = NONE
   webservice.security.authMethod = WS-SECURITY

   wss4j.in.action = UsernameToken
   wss4j.in.passwordType = PasswordText
   wss4j.in.passwordCallbackClass = org.superbiz.MyPwdHandler

   # automatically added
   wss4j.in.validator
   .{http://docs.oasis-open.org/wss/2004/01/oasis-200401
   -wss-wssecurity-secext-1.0.xsd}UsernameToken =
   org.apache.openejb.server.cxf.OpenEJBLoginValidator
  </properties>
 </ejb-deployment>
</openejb-jar>

wss4j.out.* properties exist too.

Scanning configuration

Scanning is used to find EE classes (EJB, CDI beans…).

It is common to not scan utility libraries like commons-lang for instance.

TomEE/OpenEJB support two main configurations regarding the scanning:

  • exclusions.list: can be in WEB-INF or in <tomee>/conf/: each line is a jar prefix which will not be included in the scanning. Defaults are in openejb-core/!default.exclusions. If you want to simply add your own exclusion you can use default-list which means the whole content of the default file.

  • scan.xml: in META-INF or WEB-INF it lists the classes/packages to scan. here is a sample:

<?xml version="1.0"?>
<scan>
 <packages>
  <package>org.foo1</package>
  <package>org.foo2</package>
 </packages>
 <classes>
  <class>org.bar.Bar1</class>
  <class>org.anotherbar.Bar2</class>
 </classes>
</scan>
TomEE application configuration, WEB-INF/resources.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
  <!--
    mainly a tomee.xml embed in the application
    (META-INF or WEB-INF)
  -->
  <Resource id="name" type="DataSource">
      JdbcUrl = jdbc:hsqldb:mem:my-ds
  </Resource>
</resources>
JAXRS configuration

It basically relies on openejb-jar.xml (in META-INF or WEB-INF):

<?xml version="1.0" encoding="UTF-8"?>
<openejb-jar xmlns="http://www.openejb.org/openejb-jar/1.1">
 <!--
 class-name has to be the JAXRS application name
 or this one if no Application is defined
 -->
 <pojo-deployment class-name="jaxrs-application">
  <properties>
   cxf.jaxrs.providers = org.foo.BarProvider, id1
  </properties>
 </pojo-deployment>
</openejb-jar>

Values are either a class which will be instantiated (through new) or an id which will match a Service in a resources.xml file:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <Service id="json" class-name="org.foo.bar">
      Attribute1 = Value1
      Attribute2 = Value2
  </Resource>
</resources>

Here is the full list of available properties configurable in openejb-jar.xml with the prefix cxf.jaxrs:

  • properties

  • features

  • in-interceptors

  • out-interceptors

  • in-fault-interceptors

  • out-fault-interceptors

  • databinding

  • providers

Note
excepted providers configuration all these configuration are available for CXF endpoints (including JAXWS ones).
TomEE main configuration, conf/tomee.xml
<?xml version="1.0" encoding="utf-8"?>
<tomee>
  <!--
  resources can be declared here
  To lookup it directly just use openejb:Resource/<id> name
  -->
  <Resource id="name" type="DataSource>
      # here comes the configuration in properties like format
      JdbcUrl = jdbc:hsqldb:mem:my-ds
      UserName = SA
  </Resource>

  <!-- resource can be any class available in the container loader -->
  <Resource id="foo" class-name="org.foo.MyPojo">
    pojoAttr1 = value2
  </Resource>

  <!--
   if you want to deploy ear/jar,
   declare it + put the file in apps folder
  -->
  <Deployments dir="apps" />

  <!-- more on http://tomee.apache.org/containers-and-resources.html -->
</tomee>
Activating JAAS
Note
in the snippets o.a.o means org.apache.openejb

Basic JAAS configuration needs:

  • the system property:

-Djava.security.auth.login.config=<path to login.config>
  • the login.config file (see below)

Here is a sample JAAS config file using PropertiesLoginModule:

PropertiesLoginModule {
 o.a.o.core.security.jaas.PropertiesLoginModule
 required
 Debug=false
 UsersFile="users.properties"
 GroupsFile="groups.properties";
};

This login module needs 2 properties files, one for group and one for users.

Here is a users.properties file (should be in conf/):

user1=pwd1
user3=pwd2
user3=pwd3

Here is a groups.properties file (should be in conf/):

group1=user1
group2=user2, user3

To integrate JAAS with Tomcat just add/replace the default tomcat realm with:

<Realm className="org.apache.catalina.realm.JAASRealm"
 appName="PropertiesLoginModule"
 userClassNames="o.a.o.core.security.jaas.UserPrincipal"
 roleClassNames="o.a.o.core.security.jaas.GroupPrincipal" />
OpenEJB dependencies
<!-- core: embedded cdi, ejb, EJBContainer... -->
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>openejb-core</artifactId>
  <version>${openejb.version}</version>
</dependency>

<!-- for JAXWS webservices -->
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>openejb-cxf</artifactId>
  <version>${openejb.version}</version>
</dependency>

<!-- for JAXRS webservices -->
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>openejb-cxf-rs</artifactId>
  <version>${openejb.version}</version>
</dependency>

<!-- embedded arquillian adapter -->
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>arquillian-openejb-embedded-4</artifactId>
  <version>${openejb.version}</version>
</dependency>
TomEE dependencies
<!-- tomee zip -->
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>apache-tomee</artifactId>
  <version>${tomee.version}</version>
  <type>zip</type>
</dependency>

<!-- tomee arquillian adapter -->
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>arquillian-tomee-remote</artifactId>
  <version>${tomee.version}</version>
</dependency>
TomEE Embedded dependencies
<!-- tomee zip -->
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>tomee-embedded</artifactId>
  <version>${tomee.version}</version>
  <type>zip</type>
</dependency>

<!-- tomee embedded arquillian adapter -->
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>arquillian-tomee-embedded</artifactId>
  <version>${tomee.version}</version>
</dependency>

<!-- tomee jaxrs -->
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>tomee-jaxrs</artifactId>
  <version>${tomee.version}</version>
</dependency>

<!-- tomee jaxws -->
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>tomee-webservices</artifactId>
  <version>${tomee.version}</version>
</dependency>
TomEE maven plugin configuration
Note
Configuration block is optional all attributes have defaul values.
<plugin>
 <groupId>org.apache.openejb.maven</groupId>
 <artifactId>tomee-maven-plugin</artifactId>
 <version>${tmp.version}</version>
 <configuration> <!-- all is optional -->
  <tomeeVersion>1.5.0</tomeeVersion>
  <tomeeClassifier>plus</tomeeClassifier> <!-- webprofile, jaxrs -->

  <!-- remote debugging -->
  <debug>false</debug>
  <debugPort>5005</debugPort>

  <!-- http port - same exists for ajp and https -->
  <tomeeHttpPort>8080</tomeeHttpPort>

  <!-- remove default tomee webapp -->
  <removeDefaultWebapps>true</removeDefaultWebapps>
  <!-- remove even tomee webapp - if you don't use it -->
  <removeTomeeWebapp>true</removeTomeeWebapp>

  <!-- add some libs to the server -->
  <libs>
   <lib>mysql:mysql-connector-java:5.1.20</lib>
  </libs>

  <!-- deploy another webapp, same exists for ear with <apps /> -->
  <webapps>
   <webapp>org.superbiz:my-simple-webapp:1.0.0</webapp>
  </webapps>

  <!-- auto update of the app -->
  </configuration>
   <!-- can the app be redeployed after update -->
   <reloadOnUpdate>true</reloadOnUpdate>
   <synchronization>
    <!-- extensions updating and redeploying -->
    <extensions>
     <extension>.class<extension>
    </extensions>
    <!-- extensions updating without redeploy -->
    <updateOnlyExtensions>
     <updateOnlyExtension>.html<updateOnlyExtension>
     <updateOnlyExtension>.js<updateOnlyExtension>
     <updateOnlyExtension>.jcss<updateOnlyExtension>
    </updateOnlyExtensions>
   </synchronization>
   <!-- <synchronizations/> exist to handle multiple source/target -->
  </configuration>
 </configuration>
</plugin>
TomEE maven plugin information

Compatibility matrix:

TomEE

Maven plugin

1.0.0

1.0-alpha-1

1.5.0

1.0.0

1.5.1

1.0.1

>= 1.5.2

same as TomEE

Main goals:

  • tomee:run: run and wait for the server

  • tomee:debug: run in debug mode and wait for the server (alias of run)

  • tomee:start: run the server

  • tomee:stop: stop the server (to use with start)

  • tomee:configtest: run configtest tomcat command

  • tomee:deploy <path>: deploy path archive

  • tomee:undeploy <path>: undeploy path archive. Note it should be the same path than the one used in deploy command

  • tomee:list: list ejbs deployed

  • tomee:build: build tomee but does not start it

  • tomee:help: this

Note
almost all properties can be set as maven system properties prefixed by tomee-plugin..
Tip
to debug use mvn tomee:debug instead of mvn tomee:run.

OpenEJB embedded adapter configuration
<?xml version="1.0" encoding="UTF-8"?>
<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="openejb" default="true">
  <configuration>
   <!-- container properties (~ conf/system.properties) -->
   <property name="properties">
    # you can declare a resource, container...
    db1 = new://Resource?type=DataSource
    db1.JdbcUrl = jdbc:hsqldb:mem:db1

    # special hook based on ShrinkWrap
    # to predeployed some archives at startup
    # (instead of by test)
    #
    # syntax is comma separated list
    # and multiple archives in the same package
    # can be aggregated: package.[A1|A2]
    openejb.arquillian.predeploy-archives = org.foo.SimpleArchive
   </property>
  </configuration>
 </container>
</arquillian>
TomEE Arquillian Adapters

TomEE arquillian adapters support the system property openejb.arquillian.adapter to select which adapter to use if multiple are at the classpath (Arquillian tolerate a single one by default).

This way you can run your test against several OpenEJB/TomEE adapters in the same build (no need of any maven profile). A complete sample can be found here: http://svn.apache.org/repos/asf/tomee/tomee/trunk/examples/multiple-arquillian-adapters/).

Simple Arquillian test
@RunWith(Arquillian.class)
public class SimpleArquillianTest {
 @Deployment(name = "archive")
 public static WebArchive war() {
  return ShrinkWrap.create(WebArchive.class, "test.war")
   .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
   .addClasses(MyBean.class);
  }

  @Inject
  private MyBean bean;

  @Test
  public void testRunningInDep1() {
    assertEquals("foo", bean.foo());
  }
}
TomEE embedded adapter configuration
<?xml version="1.0" encoding="UTF-8"?>
<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="serverXml">conf/server.xml</property>

   <!-- port = -1 means random -->
   <property name="httpPort">-1</property>
   <property name="stopPort">-1</property>

   <!-- ssl -->
   <property name="httpsPort">-1</property>
   <property name="ssl">false</property>
   <property name="keystoreFile">keystore-path</property>
   <property name="keystorePass">changeit</property>
   <property name="keystoreType">JKS</property>
   <property name="clientAuth">false</property>
   <property name="keyAlias">alias</property>
   <property name="sslProtocol">protocol</property>

   <!-- where to create TomEE files -->
   <property name="dir">target/tomee-embedded</property>

   <!-- where to dump on disk applications to deploy -->
   <property name="appWorkingDir">target/working-dir</property>

   <!-- optional - limit the port allowed when random -->
   <property name="portRange">20001-30000</property>

   <!-- container config -->
   <property name="properties">
    # same as embedded case
   </property>
   
   <!-- Deployer config -->
   <property name="deployerProperties">
    # openejb.deployer.binaries.use=true
    # openejb.deployer.forced.appId=[name]
    # openejb.deployer.save-deployments=false
   </property>
  </configuration>
 </container>
</arquillian>
TomEE remote adapter configuration
<?xml version="1.0" encoding="UTF-8"?>
<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="serverXml">conf/server.xml</property>

   <!-- tomee zip to use -->
   <property name="groupId">org.apache.openejb</property>
   <property name="artifactId">apache-tomee</property>
   <property name="version">LATEST</property>
   <property name="type">zip</property>

   <!-- tomee provided files, ignored by default -->
   <property name="bin">src/test/tomee/bin</property>
   <property name="conf">src/test/tomee/conf</property>
   <property name="lib">src/test/tomee/lib</property>

   <!--
    remote debugging,
    -Dopenejb.server.debug can activate it too
   -->
   <property name="debug">false</property>
   <property name="debugPort">5005</property>

   <!-- nice one line logging -->
   <property name="simpleLog">true</property>

   <!-- jvm config -->
   <property name="catalina_opts">-XX:-UseParallelGC</property>

   <!-- remove if exist -->
   <property name="cleanOnStartUp">true</property>

   <!-- remove default webapps -->
   <property name="removeunusedWebapps">true</property>

   <!-- port = -1 means random -->
   <property name="httpPort">-1</property>
   <property name="stopPort">-1</property>

   <!-- where to create TomEE -->
   <property name="dir">target/apache-tomee</property>

   <!-- where to dump on disk applications to deploy -->
   <property name="appWorkingDir">target/working-dir</property>

   <!-- optional - limit the port allowed when random -->
   <property name="portRange">20001-30000</property>

   <!-- container config -->
   <property name="properties">
    # same as embedded case
   </property>
   
   <!-- Deployer config -->
   <property name="deployerProperties">
    # openejb.deployer.binaries.use=true
    # openejb.deployer.forced.appId=[name]
    # openejb.deployer.save-deployments=false
   </property>
   
  </configuration>
 </container>
</arquillian>
Multiple TomEE with Arquillian
<?xml version="1.0" encoding="UTF-8"?>
<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">
 <group qualifier="tomee-cluster">
  <container qualifier="tomee-1">
   <configuration>
    <property name="httpPort">-1</property>
    <property name="stopPort">-1</property>
    <property name="ajpPort">-1</property>
    <property name="dir">target/tomee1</property>
    <property name="appWorkingDir">target/wd1</property>
   </configuration>
  </container>
  <container qualifier="tomee-2">
   <configuration>
    <property name="httpPort">-1</property>
    <property name="stopPort">-1</property>
    <property name="ajpPort">-1</property>
    <property name="dir">target/tomee2</property>
    <property name="appWorkingDir">target/wd2</property>
   </configuration>
  </container>
 </group>
</arquillian>

Then in java just declare "as usual" multiple deployments and match them in your test methods:

@RunWith(Arquillian.class)
public class MultipleTomEETest {
 @Deployment(name = "war1", testable = false)
 @TargetsContainer("tomee-1")
 public static WebArchive war1() {
  return /* ... */;
 }

 @Deployment(name = "war2", testable = false)
 @TargetsContainer("tomee-2")
 public static WebArchive war2() {
  return /* ... */;
 }

 @Test
 @OperateOnDeployment("war1")
 public void testRunningInDep1(
    @ArquillianResource URL url) {
   // test on tomee 1, url is contextual
 }

 @Test
 @OperateOnDeployment("war2")
 public void testRunningInDep1(
    @ArquillianResource URL url) {
   // test on tomee 1, url is contextual
 }
}