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.