I have a love/hate relationship with Eclipse. It's a great editor with sane default key mappings, but it tries to be too much. One thing that never worked all that well is the WTP plugin for managing application servers.
How many times have you refreshed/published/republished Tomcat in Eclipse? Sometimes the configuration files get out of sync and you have to clean it. And since all the wars end up in the same Tomcat instance the start up time is horrendous.
An alternative to WTP is the Tomcat Maven plugin. It allows you to manage Tomcat servers, but what I want to show you is how use it to run a war project in an embedded Tomcat instance.
Unfortunately our war projects are not fully Mavenized (yet), but we can get around that by using the fact it is just a war in the end. This allows us to use the Maven War plugin to create an overlay over our war projects and then run that in Tomcat.
So enough pre-amble, show me the code! Let’s get com.elasticpath.sf running using the Tomcat Maven plugin and MySQL.
First we need to get some environment specific settings out of the way. Since we are doing a war overlay we won’t have access to any of the settings in env.config. Instead we’ll put our environment specific settings in ~/.m2/settings.xml:
<?xml version="1.0"?>
<settings>
<activeProfiles>
<acitveProfile>mysql-dev-db</activeProfile>
<activeProfile>storefront-tomcat-properties</activeProfile>
<activeProfile>keystore-properties</activeProfile>
</activeProfiles>
<profiles>
<profile>
<id>storefront-tomcat-properties</id>
<properties>
<storefront.context>/storefront</storefront.context>
<storefront.http.port>8080</storefront.http.port>
<storefront.https.port>8443</storefront.https.port>
</properties>
</profile>
<profile>
<id>keystore-properties</id>
<properties>
<keystore.file>/your/very/own/.keystore</keystore.file>
<keystore.pass>changeit</keystore.pass>
</properties>
</profile>
</profiles>
…
</settings>
Other war projects will need their own profile. The profile mysql-dev-db will come from the grandparent pom. It is available since 6.3 and the source is included under elasticpath-grandparent/pom.xml. If the default properties defined in the mysql-dev-db profile are unsuitable for your needs, they can be overriden using another profile in ~/.m2/settings.xml and activate it after the mysql-dev-db profile.
We then create a new Maven project called storefront which will overlay com.elasticpath.sf. Here we will use the released version of the grandparent pom and define the parent of the storefront project as the grandparent pom:
<?xml version="1.0" encoding="UTF-8"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.elasticpath</groupId>
<artifactId>grandparent</artifactId>
<version>16</version>
<groupId>com.elasticpath.extensions</groupId>
<artifactId>storefront</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>Storefront Extension</name>
<dependencies>
<dependency>
<groupId>com.elasticpath</groupId>
<artifactId>com.elasticpath.sf</artifactId>
<version>...your Elastic Path version...</version>
<type>war</type>
</dependency>
</dependencies>
Now define the Tomcat Maven plugin configuration. The path and port configuration is defined in the settings profile. And finally we choose the JDBC driver. Yes this means you never again have to figure out where is Tomcat’s shared library folder. All the epdb.* properties are defined in the mysql-dev-db profile.
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>tomcat-maven-plugin</artifactId>
<version>1.1</version>
<configuration>
<path>${storefront.context}</path>
<port>${storefront.http.port}</port>
<httpsPort>${storefront.https.port}</httpsPort>
<keystoreFile>${keystore.file}</keystoreFile>
<keystorePass>${keystore.pass}</keystorePass>
</configuration>
<dependencies>
<dependency>
<groupId>${epdb.maven.groupId}</groupId>
<artifactId>${epdb.maven.artifactId}</artifactId>
<version>${epdb.maven.version}</version>
</dependency>
</dependencies>
</plugin>
We need to define the jdbc/epjndi resource as a MySQL datasource. This is done with META-INF/context.xml. To get our settings into context.xml we’ll filter it using the Maven War plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<webResources>
<resource>
<directory>src/main/webapp-filtered</directory>
<filtering>true</filtering>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
That will filter any file in src/main/webapp-filtered and put the result in the root of the built war. This allows us to create src/main/webapp-filtered/META-INF/context.xml with the contents:
<Context>
<Resource auth="Container" name="mail/Session" type="javax.mail.Session" />
<Resource
name="jdbc/epjndi"
auth="Container"
scope="Shareable"
type="${epdb.datasource.classname}"
maxActive="100"
maxIdle="30"
maxWait="10000"
removeAbandoned="true"
username="${epdb.username}"
password="${epdb.password}"
driverClassName="${epdb.jdbc.driver}"
url="${epdb.url}" />
</Context>
...and have it filled out by the mysql-dev-db profile.
Our storefront project depends on com.elasticpath.sf so make sure it's in your local repo by running ant install under com.elasticpath.sf.
Since we are running Tomcat with Maven in order to pass JVM arguments to Tomcat you’ll need to configure the environment variable MAVEN_OPTS instead of CATALINA_OPTS. Note for Java 6 users to copy over their special JVM args to MAVEN_OPTS. This also means remote debugging parameters should be set in MAVEN_OPTS. For more information on remote debugging see: http://java.dzone.com/articles/how-debug-remote-java-applicat
Finally we run our storefront project with
mvn tomcat:run-war
Storefront is now running under http://localhost:8080/storefront and can be killed with ^C.
Repeat for the remaining wars and you can have each war project running in a separate embedded Tomcat instance. Just remember to give each instance its own port and update settings like COMMERCE/SYSTEM/SEARCH/searchHost. See http://mojo.codehaus.org/tomcat-maven-plugin/index.html for more details on how to configure the run-war goal. Special care is needed to ensure each project has its own remote debugging ports. This is accomplished by setting different MAVEN_OPTS for each project. Simply use
MAVEN_OPTS=”$MAVEN_OPTS <project specific opts>” mvn tomcat:run-war
This will temporary append project specific options to MAVEN_OPTS. There is no semicolon before mvn because we only want to set this variable for this process and not back to the shell.
This gives you great control to start and stop individual wars. Only changed com.elasticpath.sf? Just ant install and restart that Tomcat instance.
While it took a little bit of work to get the environment specific settings in the right place this now gives us a platform to use more Maven without having to wait for the full Mavenization of our projects. Let’s get cracking!


