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 Website: http://tomee.apache.org TomEE Examples: http://tomee.apache.org/examples-trunk/index.html

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-10.1-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 as 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`.
Doc is on http://tomee.apache.org/tomee-maven-plugin.html.

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
     }
    }