Many applications running on TomEE interact with other services, such as databases or 3rd party REST APIs. As an administrator, we need to be able to tell the application how to connect to these systems. TomEE provides a couple of different strategies for configuration and in this article, we’ll explore the different packaging and deployments.

Separating configuration from your application

This is probably the most common way of working with TomEE. Any resources that are used in the application are defined in the application server and mapped to a unique name in a JNDI directory. To improve the portability of applications between different servers, global JNDI resources are mapped to a namespace for the application and looked up from the java:comp/env namespace. If this sounds complicated, well, it is.

This has been greatly simplified in more recent versions of Java EE through the use of dependency injection and annotations. With TomEE you can define a resource, for example, a datasource, in TomEE’s conf/tomee.xml file like this:


<tomee>
  <Resource id="moviefun" type="DataSource">
    JdbcDriver com.mysql.jdbc.Driver
    JdbcUrl jdbc:mysql://localhost:3306/moviefun
    JtaManaged true
    UserName username
    Password password
  </Resource>
</tomee>

And use this configuration by injecting a javax.sql.DataSource into any managed component:

public class Example {
    @Resource(name="moviefun")
    private DataSource dataSource;

    protected void runQuery() {
        try {

            try (final Connection connection = dataSource.getConnection();
                 final PreparedStatement ps = connection.prepareStatement("");
                 final ResultSet rs = ps.executeQuery()) {

                // process resultset

        } catch (Exception e) {
            // handle error
        }
    }
}

Providing configuration with your application

As an alternative to providing the configuration in the server, with TomEE, it is possible to include the configuration and any necessary jars in the application itself. To do this, include a WEB-INF/resources.xml file in the war file. Handily, the format for this file is the same as the conf/tomee.xml file, with the exception of the top-level tag being <resources> as opposed to <tomee>:

Let’s take a look at an example:


<resources>
  <Resource id="moviefun" type="DataSource">
    JdbcDriver com.mysql.jdbc.Driver
    JdbcUrl jdbc:mysql://localhost:3306/moviefun
    JtaManaged true
    UserName username
    Password password
  </Resource>
</resource>

The advantage of this setup is that the war file is completely self-contained and simply needs to be deployed by dropping it in TomEE’s webapps directory.

Bundling it all together

TomEE Maven plugin

If you haven’t come across the TomEE Maven plugin yet, it is worth trying it out. Irrespective of whether you prefer to configure things at the server or application level, the Maven plugin enables you to run or debug your application in TomEE using Maven goals, and (this is one of my personal favorite features) actually creates a zip file with a complete TomEE build including your application, configuration and any additional jars that you require.

The plugin is documented on the TomEE website here: http://tomee.apache.org/developer/tools/maven/tomee.html, but the following config should be enough to help you get started:

<plugin>
  <groupId>org.apache.tomee.maven</groupId>
  <artifactId>tomee-maven-plugin</artifactId>
  <version>8.0.0-M1</version>
  <configuration>
    <tomeeClassifier>plus</tomeeClassifier>
  </configuration>
</plugin>

You can specify additional libraries to include in TomEE’s lib directory by adding a <lib> section under <configuration>. For example, to include the MySQL JDBC driver:


<plugin>
  <groupId>org.apache.tomee.maven</groupId>
  <artifactId>tomee-maven-plugin</artifactId>
  <version>8.0.0-M1</version>
  <configuration>
    <tomeeClassifier>plus</tomeeClassifier>
    <args>-Xmx512m -XX:PermSize=256m</args>
    <libs>
      <lib>mysql:mysql-connector-java:8.0.13</lib>
    </libs>
  </configuration>
</plugin>

By default, if you create a src/main/tomee/conf directory in your build, any files placed there will override what’s in TomEE’s out-of-the-box conf directory. For example, if you add a server.xml or tomee.xml, you can customize server ports, threadpools, realms and any server resources.

To build the server, run mvn clean install tomee:build.

Substitutions for just about everything

Of course, while including configuration inside the application, or building the entire server complete with the configuration may have some advantages, there is a disadvantage that the configuration is somewhat hardcoded. Irrespective of whether you use tomee.xml at the server level or resources.xml at the application level, you can use ${variable} placeholders in these files, and also in conf/server.xml too. The variables used in the placeholders are read from system properties. These can be specified using -Dproperty=value JVM arguments, in conf/system.properties, or conf/catalina.properties.

Overriding resource properties

In addition to being able to substitute values, you can also override any resource attribute using a system property. For example, to override the JdbcUrl attribute of this resource you can do the following:

<resources>
  <Resource id="moviefun" type="DataSource">
    JdbcDriver com.mysql.jdbc.Driver
    JdbcUrl jdbc:mysql://localhost:3306/moviefun
    JtaManaged true
    UserName username
    Password password
  </Resource>
</resource>

Use this system property:

moviefun.JdbcUrl=jdbc:mysql://server:3306/moviefun

In this example, I’ve switched the host on the URL.

Docker

If you’re a Docker user, you can provide system properties by specifying the CATALINA_OPTS environment variable. We could, for example, provide the configuration in the application and use the following Dockerfile to copy the .war file to the Docker container:

FROM tomee:8-jre-8.0.0-M1-plus
COPY target/moviefun.war /usr/local/tomee/webapps/moviefun.war

And then provide some settings to substitute into WEB-INF/resources.xml using the CATALINA_OPTS environment variable when starting the container:


docker run -e CATALINA_OPTS="-Ddb.host=my-database -Ddb.port=3306 -Ddb.username=root -Ddb.password=my-secret-pw" <container id>

Conclusion

TomEE provides a variety of ways to configure your application. Each solution has its advantages and disadvantages but the latest methods, discussed here, are far simpler than using the convention JNDI directory system.

Jonathan Gallimore

Jonathan Gallimore

Jonathan Gallimore is a passionate Apache TomEE committer, developer and trainer at Tomitribe. He started contributing to Apache TomEE in 2007, working on EJB 3.1 compliance, OpenEJB Eclipse Plug-in, early Tomcat 7 integration (that became the basis for TomEE) and the first version of the TomEE Arquillian adapter. Jon has worked as a developer and architect on Java EE projects across the media, banking, and sports industries.
jongallimore

Leave a Reply