Executable jar with TomEE and Tomcat Maven Plugin


Tomcat Maven plugin has a goal to allow you to create an executable jar: http://tomcat.apache.org/maven-plugin-2.0/tomcat7-maven-plugin/exec-war-mojo.html

It is nice but integrated with Tomcat so if you do JavaEE it doesn’t work…excepted if you use TomEE.

Since TomEE is Tomcat we should be able to reuse it and define TomEE as target. Actually this is not as easy as expected but after a little discussion with Tomcat Maven plugin developers it should be soon easily doable.

However this is not a blocking point since the plugin already allows to do it. In my sample I’ll use TomEE JAXRS. The idea is to add as extra dependencies TomEE dependencies to build a tomcat-EEsed container. I used unitary dependencies but it is doable with shades to make it easier.

Here are the main points to take care:

  • Deactivate openejb internal webapp (I’ll use the system property to do so but a scan.xml can do the trick too)
  • Use CXF bundle jar and not unitary dependencies otherwise CXF config files are kind of merged and it breaks CXF
  • Use very recent TomEE version since Tomcat Maven plugin uses embedded Tomcat in a particular way which is only compatible with last TomEE
  • Don’t use tomee embedded shade to avoid conflicts between tomcat provided by the plugin and tomee-embedded one
  • add TomEE listener in server.xml

Here what it looks like:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>quicktest</groupId>
  <artifactId>quicktest</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <dependencies>
    <dependency>
      <groupId>org.apache.openejb</groupId>
      <artifactId>javaee-api</artifactId>
      <version>6.0-5</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <properties>
    <openejb.version>4.6.1-SNAPSHOT</openejb.version>
    <openwebbeans.version>1.2.2</openwebbeans.version>
    <tomee.version>1.6.1-SNAPSHOT</tomee.version>
    <cxf.version>2.6.11</cxf.version>
    <sxc.version>0.8</sxc.version>
    <xbean.version>3.16</xbean.version>
    <slf4j.version>1.7.5</slf4j.version>
    <bval.version>0.5</bval.version>
  </properties>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.4</version>
        <configuration>
          <failOnMissingWebXml>false</failOnMissingWebXml>
        </configuration>
      </plugin>

      <!-- to use java -Dopenejb.system.apps=false -jar target/quicktest-1.0-SNAPSHOT-war-exec.jar -->
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.1</version>
        <executions>
          <execution>
            <id>tomcat-run</id>
            <goals>
              <goal>exec-war-only</goal>
            </goals>
            <phase>package</phase>
            <configuration>
              <path>ROOT</path>
              <tomcatConfigurationFilesDirectory>src/main/tomee/conf</tomcatConfigurationFilesDirectory>
              <serverXml>src/main/tomee/server.xml</serverXml>
              <enableNaming>true</enableNaming>
              <extraDependencies>
                <extraDependency>
                  <groupId>org.apache.cxf</groupId>
                  <artifactId>cxf-bundle-jaxrs</artifactId>
                  <version>${cxf.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.codehaus.jettison</groupId>
                  <artifactId>jettison</artifactId>
                  <version>1.3.4</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.codehaus.woodstox</groupId>
                  <artifactId>woodstox-core-asl</artifactId>
                  <version>4.2.0</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.codehaus.woodstox</groupId>
                  <artifactId>stax2-api</artifactId>
                  <version>3.1.1</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.ws.xmlschema</groupId>
                  <artifactId>xmlschema-core</artifactId>
                  <version>2.0.3</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-cxf-rs</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-cxf-transport</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-rest</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-http</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-loader</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-core</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-client</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-server</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-ejbd</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-jpa-integration</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-api</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-javaagent</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-jee</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>openejb-jee-accessors</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.metatype.sxc</groupId>
                  <artifactId>sxc-jaxb-core</artifactId>
                  <version>${sxc.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.metatype.sxc</groupId>
                  <artifactId>sxc-runtime</artifactId>
                  <version>${sxc.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>mbean-annotation-api</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>tomee-jaxrs</artifactId>
                  <version>${tomee.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>tomee-embedded</artifactId>
                  <version>${tomee.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>tomee-common</artifactId>
                  <version>${tomee.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>tomee-catalina</artifactId>
                  <version>${tomee.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>tomee-jdbc</artifactId>
                  <version>${tomee.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>tomee-myfaces</artifactId>
                  <version>${tomee.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>tomee-loader</artifactId>
                  <version>${tomee.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.commons</groupId>
                  <artifactId>commons-lang3</artifactId>
                  <version>3.1</version>
                </extraDependency>
                <extraDependency>
                  <groupId>commons-beanutils</groupId>
                  <artifactId>commons-beanutils-core</artifactId>
                  <version>1.8.3</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.geronimo.components</groupId>
                  <artifactId>geronimo-transaction</artifactId>
                  <version>3.1.1</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.xbean</groupId>
                  <artifactId>xbean-asm4-shaded</artifactId>
                  <version>${xbean.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.xbean</groupId>
                  <artifactId>xbean-finder-shaded</artifactId>
                  <version>${xbean.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.xbean</groupId>
                  <artifactId>xbean-reflect</artifactId>
                  <version>${xbean.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.xbean</groupId>
                  <artifactId>xbean-naming</artifactId>
                  <version>${xbean.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.xbean</groupId>
                  <artifactId>xbean-bundleutils</artifactId>
                  <version>${xbean.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>commons-dbcp</groupId>
                  <artifactId>commons-dbcp</artifactId>
                  <version>1.4</version>
                </extraDependency>
                <extraDependency>
                  <groupId>commons-pool</groupId>
                  <artifactId>commons-pool</artifactId>
                  <version>1.5.7</version>
                </extraDependency>
                <extraDependency>
                  <groupId>commons-logging</groupId>
                  <artifactId>commons-logging</artifactId>
                  <version>1.1.1</version>
                </extraDependency>
                <extraDependency>
                  <groupId>commons-lang</groupId>
                  <artifactId>commons-lang</artifactId>
                  <version>2.6</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb.shade</groupId>
                  <artifactId>openejb-shade-quartz</artifactId>
                  <version>${openejb.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.slf4j</groupId>
                  <artifactId>slf4j-api</artifactId>
                  <version>${slf4j.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.slf4j</groupId>
                  <artifactId>slf4j-jdk14</artifactId>
                  <version>${slf4j.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openjpa</groupId>
                  <artifactId>openjpa</artifactId>
                  <version>2.3.0</version>
                </extraDependency>
                <extraDependency>
                  <groupId>net.sourceforge.serp</groupId>
                  <artifactId>serp</artifactId>
                  <version>1.14.1</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openwebbeans</groupId>
                  <artifactId>openwebbeans-impl</artifactId>
                  <version>${openwebbeans.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openwebbeans</groupId>
                  <artifactId>openwebbeans-spi</artifactId>
                  <version>${openwebbeans.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openwebbeans</groupId>
                  <artifactId>openwebbeans-ejb</artifactId>
                  <version>${openwebbeans.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openwebbeans</groupId>
                  <artifactId>openwebbeans-ee</artifactId>
                  <version>${openwebbeans.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openwebbeans</groupId>
                  <artifactId>openwebbeans-ee-common</artifactId>
                  <version>${openwebbeans.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openwebbeans</groupId>
                  <artifactId>openwebbeans-web</artifactId>
                  <version>${openwebbeans.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openwebbeans</groupId>
                  <artifactId>openwebbeans-el22</artifactId>
                  <version>${openwebbeans.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.bval</groupId>
                  <artifactId>bval-core</artifactId>
                  <version>${bval.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.bval</groupId>
                  <artifactId>bval-jsr303</artifactId>
                  <version>${bval.version}</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.apache.openejb</groupId>
                  <artifactId>javaee-api</artifactId>
                  <version>6.0-5</version>
                </extraDependency>
                <extraDependency>
                  <groupId>org.hsqldb</groupId>
                  <artifactId>hsqldb</artifactId>
                  <version>2.2.8</version>
                </extraDependency>
              </extraDependencies>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Finally just execute:

java -Dopenejb.system.apps=false -jar target/quicktest-1.0-SNAPSHOT-war-exec.jar

Just as a reminder here is the server.xml (in src/main/tomee/server.xml with previous config):

<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
	<Listener className="org.apache.tomee.catalina.ServerListener" />
	<Listener className="org.apache.catalina.core.JasperListener" />

	<GlobalNamingResources>
		<Resource name="UserDatabase" auth="Container"
				  type="org.apache.catalina.UserDatabase"
				  description="User database that can be updated and saved"
				  factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
				  pathname="conf/tomcat-users.xml" />
	</GlobalNamingResources>


	<Service name="Catalina">
		<Connector port="8081" protocol="HTTP/1.1"
				   connectionTimeout="20000"
				   redirectPort="8443" />
		<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
		<Engine name="Catalina" defaultHost="localhost">
			<Realm className="org.apache.catalina.realm.LockOutRealm">
				<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
					   resourceName="UserDatabase"/>
			</Realm>

			<Host name="localhost"  appBase="webapps"
				  unpackWARs="true" autoDeploy="true">
				<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
					   prefix="localhost_access_log." suffix=".txt"
					   pattern="%h %l %u %t &quot;%r&quot; %s %b" />

			</Host>
		</Engine>
	</Service>
</Server>

6 thoughts on “Executable jar with TomEE and Tomcat Maven Plugin

    1. rmannibucau Post author

      Hi

      you mean the pom in example? I didnt upload it AFAIK (and switch of computer since i wrote it :() but since tomee maven plugin has a comparable goal it is really easier to maintain (this solution would be hard when upgrading dependency versions)

      Reply
      1. Juliano Santos

        I am with some troubles, to make a jar application with embedded container, first I was try to make it without maven, with tomcat-embedded-core.jar, was work until build the project, because I was using the webapp directory inside source package files, but for my surprise, when I built the application the tomcat didn’t found the webapp directory, off cource because the directory to the webapp only exists in jar file.
        Then I was trying to use maven, but when I built the application and try to execute the jar file, I receive an error: No mainfest file to jar application, or something else.
        I sorry, by the way that I was repply to you, I am very nervous because this, there is some advice for me?

      2. rmannibucau Post author

        not sure what’s your setup but it should be a config issue. Push a mail on tomcat mailing list, it is clearly the place to discuss it.

  1. Juliano Santos

    Another thing, seriously, I ever hate java, because this things, but it is only language, that I can distribute my application to anny SO.

    Reply
    1. rmannibucau Post author

      others languages are not good too, take js or ruby, you distribute most of the time sources and rely on environment which means your app is broken 80% of the time.

      Good thing with open source is *you* can fix it if you really want instead of crying (only thing you can do with proprietary solution)

      Reply

Leave a reply to Juliano Santos Cancel reply