Tomcat - Maven plugin: run webapps but not current project
Asked Answered
H

2

7

The tomcat7-maven-plugin allows running the current project as a Web application and additional <webapps> can be specified that will be simultaneously loaded into tomcat.

My project is not a Web application, but it accesses services that are provided by webapps. So how is it possible to deploy a number of webapps without running the project itself as a webapp? The following Maven snippet results in FileNotFoundExceptions because a context.xml cannot be found.

<plugin>
  <groupId>org.apache.tomcat.maven</groupId>
  <artifactId>tomcat7-maven-plugin</artifactId>
  <version>2.0</version>
  <executions>
    <execution>
      <id>run-tomcat</id>
      <phase>${tomcat.run.phase}</phase>
      <goals><goal>run-war-only</goal></goals>
      <configuration>
        <webapps>
          <webapp>
            <contextPath>/my/app1</contextPath>
            <groupId>...</groupId> 
            <artifactId>...</artifactId>
            <version>...</version>
            <type>war</type>    
            <asWebapp>true</asWebapp>
          </webapp>
          ... possibly more webapps ...
        </webapps> 
      </configuration>
    </execution>
    <execution>
      <id>tomcat-shutdown</id>
      <phase>${tomcat.shutdown.phase}</phase>
      <goals><goal>shutdown</goal></goals>
    </execution>
  </executions>
</plugin>

Workaround:

Even though your application itself is not a webapp, you need to configure a path and a contextFile for it:

<configuration>
    <path>/my/non/existing/webapp</path>
    <contextFile>src/test/resources/context.xml</contextFile>
    <webapps>
    ...

The specified context.xml file must exist. The following worked for me, even though the web.xml file does not exist:

<?xml version="1.0" encoding="utf-8"?>
<Context path="/my/non/existing/webapp">
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>
Hedi answered 18/3, 2013 at 15:13 Comment(5)
can you post the relevant logs of the maven output?Punishment
So, Dominik, you get a reply a little over an hour after you post your question but you don't have the courtesy to respond?Stagemanage
I added a workaround, which solves the problem. But I still hope there is a better way to do this...Hedi
Dominik, what did you put in the context file? When I use the configuration above, Tomcat7 throws and error "Error starting static Resources". Do you get this?Nanna
I need to be able to do this also...looking into a solution. Did you file a feature request with the apache tomcat team for this usecase?Enduring
E
6

This is probably abusing the tomcat maven plugin but here is a solution I found. BTW your fake context file solution didn't work for me because I needed to run a different webapp and my app is also a webapp.

There is a jira out there that would provide a better solution to our problem. See https://issues.apache.org/jira/browse/MTOMCAT-228. Now on to my solution...

First, you need to copy the war to a directory. I suggest the target directory so it can be easily cleaned. Depending on whether you want to support the run or the run-war goals depends on whether you just copy the war or copy the war and unpack it.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <version>${maven-dependency-plugin.version}</version>
  <executions>
    <execution>
      <id>copy-war</id>
      <goals>
        <goal>copy</goal>
      </goals>
      <configuration>
        <artifactItems>
          <artifactItem>
            <groupId>org.foo</groupId>
            <artifactId>bar</artifactId>
            <version>${bar.version}</version>
            <type>war</type>
            <overWrite>true</overWrite>
            <outputDirectory>${project.build.directory}/bar/</outputDirectory>
          </artifactItem>
        </artifactItems>
        <stripVersion>true</stripVersion>
      </configuration>
    </execution>
    <execution>
      <id>copy-war-unpack</id>
      <goals>
        <goal>unpack</goal>
      </goals>
      <configuration>
        <artifactItems>
          <artifactItem>
            <groupId>org.foo</groupId>
            <artifactId>bar</artifactId>
            <version>${bar.version}</version>
            <type>war</type>
            <overWrite>true</overWrite>
            <outputDirectory>${project.build.directory}/bar/bar</outputDirectory>
          </artifactItem>
        </artifactItems>
      </configuration>
    </execution>
  </executions>
</plugin>

Next, you need to configure the tomcat plugins to look at the directory or war that you just copied to in the above step. The following shows a configuration for tomcat 6 & 7 which is identical other than the artifact id.

<plugin>
  <groupId>org.apache.tomcat.maven</groupId>
  <artifactId>tomcat6-maven-plugin</artifactId>
  <version>${tomcat6-maven-plugin.version}</version>
  <configuration>
    <port>8090</port>
    <path>${default.rice.context.path}</path>
    <warDirectory>${project.build.directory}/bar/bar.war</warDirectory>
    <warSourceDirectory>${project.build.directory}/bar/bar</warSourceDirectory>
  </configuration>
</plugin>
<plugin>
  <groupId>org.apache.tomcat.maven</groupId>
  <artifactId>tomcat7-maven-plugin</artifactId>
  <version>${tomcat7-maven-plugin.version}</version>
  <configuration>
    <port>8090</port>
    <path>${default.rice.context.path}</path>
    <warDirectory>${project.build.directory}/bar/bar.war</warDirectory>
    <warSourceDirectory>${project.build.directory}/bar/bar</warSourceDirectory>
  </configuration>
</plugin>

To be clear you don't need to configure warDirectory or need copy-war execution if you only want to support tomcat:run. Conversely, you don't need to configure warSourceDirectory or need copy-war-unpack execution if you only want to support tomcat:run-war.

One final note, this dependency copy workaround also works well with the Jetty Maven plugin so if you wanted to support both tomcat & jetty this might be a good way to do it.

Enduring answered 11/9, 2013 at 1:35 Comment(3)
BTW. I messed around with all different things like external serverXml files, context files and various configurations. This is the only way I was able to get the tomcat plugin to NOT deploy the current webapp.Enduring
I tried the same without unpack war archive, just with using wsdlFile tag. But get the same error. :(Contain
Great solution! However, if project type is other than war, you must force the tomcat plugin to skip a check with ignorePackaging=true. In my case, I was building a jar which needed a mocked service (war) to do some integration testing. I used the dependency:copy mojo and used warDirectory=${project.build.directory}/warFile=mywar.war and everything works perfectly.Salutatory
E
2

I just had another idea about how to solve this problem in a maven-like way. I wanted to document this here as this might help others. I have not tested this solution yet but I see no reason why it would not work.

Basically, if you want to launch a "different" webapp than the current one using jetty or tomcat plugins what you can do is this:

Create another maven module in your project. This module will be an empty war overlay of the webapp you want to launch. Then you can put all your jetty or tomcat configs in that new module (or just centralize the jetty and tomcat config in the parent pom under pluginManagement). Since, jetty & tomcat are designed to launch the "current" application, no special hacked up configurations are required.

Enduring answered 12/9, 2013 at 18:47 Comment(2)
It looked like a great hack, but unfortunately Tomcat Maven plugin turns out to have rather limited overlay support. See eg. this thread: mail-archives.apache.org/mod_mbox/tomcat-users/201204.mbox/…Pedaiah
Oh yeah I ran into the overlay problems too. Please upvote the numerous overlay JIRA issues. I hope they fix them for their 3.0 release which will likely come out in support of tomcat 8. issues.apache.org/jira/browse/MTOMCATEnduring

© 2022 - 2024 — McMap. All rights reserved.