The Maven Cookbook

6.3. Starting a WAR Dependency in a Servlet Container

6.3. Starting a WAR Dependency in a Servlet Container

6.3.1. Task

You need to configure Maven to download and start a web application from a repository manager.

6.3.2. Action

Use the Maven Dependency plugin to copy the web application's WAR artifact to your project. Then configure the Maven Jetty plugin to execute the web application using the plugin's dependencies element to configure the classpath for Jetty.

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.sonatype.mcookbook</groupId>
  <artifactId>start-jackrabbit</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>start-jackrabbit</name>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <id>default-cli</id>1
            <configuration>
              <artifactItems>
                <artifactItem>
                  <groupId>org.apache.jackrabbit</groupId>
                  <artifactId>jackrabbit-webapp</artifactId>
                  <version>1.6.0</version>
                  <type>war</type>
                  <overWrite>true</overWrite>
                  <destFileName>jackrabbit-webapp.war</destFileName>
                </artifactItem>
              </artifactItems>
              <outputDirectory>
                ${project.build.directory}/war
              </outputDirectory>
              <overWriteReleases>true</overWriteReleases>
              <overWriteSnapshots>true</overWriteSnapshots>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>maven-jetty-plugin</artifactId>
        <version>6.1.22</version>
        <executions>
          <execution>
            <id>default-cli</id>2
            <configuration>
              <contextPath>jackrabbit</contextPath>
              <daemon>false</daemon>
              <webApp
                ${project.build.directory}/war/jackrabbit-webapp.war
              </webApp>
            </configuration>
          </execution>
        </executions>
        <dependencies>
          <dependency>3
            <groupId>org.apache.jackrabbit</groupId>
            <artifactId>jackrabbit-webapp</artifactId>
            <version>1.6.0</version>
            <type>war</type>
          </dependency>
          <dependency>
            <groupId>javax.jcr</groupId>
            <artifactId>jcr</artifactId>
            <version>2.0</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>4
      <groupId>org.apache.jackrabbit</groupId>
      <artifactId>jackrabbit-webapp</artifactId>
      <version>1.6.0</version>
      <type>war</type>
    </dependency>
  </dependencies>
</project>

This POM uses some advanced concepts to configure the default command-line options for both the Maven Dependency plugin and the Maven Jetty plugin. It also downloads and executes the jackrabbit-webapp.war artifact from the Central Maven repository.

1

This particular plugin configuration configures the default command-line execution of a goal by using the default-cli identifier. This configures the default configuration that is used when a plugin goal is executed directly on the command-line (i.e. mvn dependency:copy). In this section of the POM, the Maven Dependency plugin is configured to download the Jackrabbit web application artifact and to save this file in ${project.build.directory}/war/jackrabbit-webapp.war.

2

Again, using the identifier of default-cli specifies the configuration of the plugin when one of its goals is executed on the command-line. This particular configuration points the Jetty plugin at the downloaded jackrabbit-webapp.war file, sets the context path to jackrabbit, and sets the daemon parameter to false. Setting daemon to false will cause the Maven build to block and wait for the Jetty process.

3

This dependencies element under the Maven Jetty plugin configuration configures the classpath for the Jetty servlet container. Without declaring these dependencies, the Jackrabbit web application would not have access to the libraries that are required for execution. Listing the jackrabbit-webapp artifact as a dependency for this plugin execution causes Maven to read the POM for this artifact and download all of the transitive dependencies of the web application artifact. This element also adds in an implementation of the Java Content Repository (JCR) API.

3

Even though this project is nothing more than a place-holder project for the plugin configuration contained in the POM it does declare a dependency on the jackrabbit-webapp artifact it requires for execution. This particular dependency block is unnecessary, but its presence helps to declare the explicit dependency for other tools which may consume this POM.

To download the Jackrabbit web application and execute it in Jetty, copy the POM to an empty directory and run mvn clean dependency:copy jetty:run-war. Because you've configured the default command-line options in the POM, you should Maven downloading Jackrabbit, all of its dependencies, and starting the application in Jetty on port 8080.

$ mvn clean dependency:copy jetty:run-war
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building start-jackrabbit
[INFO]    task-segment: [clean, dependency:copy, jetty:run-war]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean {execution: default-clean}]
[INFO] Deleting directory /Users/Tim/Library/Code/sonatype/maven-cookbook/mcookbook-examples/web/\
       start-jackrabbit/target
[INFO] [dependency:copy {execution: default-cli}]
[INFO] Configured Artifact: org.apache.jackrabbit:jackrabbit-webapp:1.6.0:war
[INFO] Copying jackrabbit-webapp-1.6.0.war to /Users/Tim/Library/Code/sonatype/maven-cookbook/\
       mcookbook-examples/web/start-jackrabbit/target/war/jackrabbit-webapp.war
...
[INFO] [jetty:run-war {execution: default-cli}]
[INFO] Configuring Jetty for project: start-jackrabbit
2009-11-29 18:57:26.676:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
[INFO] Context path = /jackrabbit
[INFO] Tmp directory =  determined at runtime
[INFO] Web defaults = org/mortbay/jetty/webapp/webdefault.xml
[INFO] Web overrides =  none
[INFO] Starting jetty 6.1.22 ...
2009-11-29 18:57:26.811:INFO::jetty-6.1.22
2009-11-29 18:57:26.845:INFO::Extract /Users/Tim/Library/Code/sonatype/maven-cookbook/mcookbook-examples/\
           web/start-jackrabbit/target/war/jackrabbit-webapp.war to \
           /Users/Tim/Library/Code/sonatype/maven-cookbook/mcookbook-examples/web/start-jackrabbit/target/\
           work/webapp
2009-11-29 18:57:27.796:INFO::No Transaction manager found - if your webapp requires one, please configure one
29.11.2009 18:57:28 *INFO * root: Logging initialized. (LoggingServlet.java, line 87)
29.11.2009 18:57:28 *INFO * RepositoryStartupServlet: RepositoryStartupServlet initializing... 
                            (RepositoryStartupServlet.java, line 235)
29.11.2009 18:57:28 *ERROR* RepositoryStartupServlet: Repository startup configuration is not valid but a 
           bootstrap config is specified. (RepositoryStartupServlet.java, line 366)
29.11.2009 18:57:28 *ERROR* RepositoryStartupServlet: Either create the jackrabbit/bootstrap.properties file 
           or (RepositoryStartupServlet.java, line 367)
29.11.2009 18:57:28 *ERROR* RepositoryStartupServlet: use the '/config/index.jsp' for easy configuration. 
           (RepositoryStartupServlet.java, line 368)
29.11.2009 18:57:28 *ERROR* RepositoryStartupServlet: RepositoryStartupServlet initializing failed: 
           javax.servlet.ServletException: Repository startup configuration is not valid. 
           (RepositoryStartupServlet.java, line 245)
29.11.2009 18:57:28 *INFO * RepositoryAccessServlet: RepositoryAccessServlet initialized. 
           (RepositoryAccessServlet.java, line 98)
29.11.2009 18:57:28 *INFO * SimpleWebdavServlet: resource-path-prefix = '/repository' 
           (SimpleWebdavServlet.java, line 145)
29.11.2009 18:57:28 *INFO * SimpleWebdavServlet: WWW-Authenticate header = 'Basic realm="Jackrabbit Webdav 
           Server"' (SimpleWebdavServlet.java, line 151)
2009-11-29 18:57:28.982:INFO::Started SelectChannelConnector@0.0.0.0:8080
[INFO] Started Jetty Server

Once Maven has started Jetty with the jackrabbit-webapp.war JAR, go to a web browser and open http://localhost:8080/jackrabbit. You should see the Apache Jackrabbit administrative web interface.

Note

The first time you start the Jackrabbit web application, it will print an exception stack trace as it tries to locate a Jackrabbit database. This stack trace disappears once you load the Jackrabbit administrative interface and create a new Jackrabbit database.

While this isn't the most straightforward use of a Maven POM, it does demonstrate the power of using Maven's dependency management and plugin configuration to distribute the settings necessary to execute a web application. If you used such a mechanism to distribute your own web applications, you could configure a web application and all of the information required to download your web application, it's dependencies, the servlet container, and any configuration needed to run your application.