Skip Navigation

Web Development

Chapter 6

6.1 Running a Web Application in a Servlet Container

6.1.1. Task

You need to run a web application in a servlet container.

6.1.2. Action

Configure your web application's Maven project to inlcude the Maven Jetty plugin as shown in the following POM:

<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>sample-web </artifactId>
<packaging>war </packaging>
<version>1.0-SNAPSHOT </version>
<name>sample-web Maven Webapp </name>
<url>http://maven.apache.org </url>
<dependencies>
<dependency>
<groupId>junit </groupId>
<artifactId>junit </artifactId>
<version>3.8.1 </version>
<scope>test </scope>
</dependency>
<dependency>
<groupId>javax.servlet </groupId>
<artifactId>servlet-api </artifactId>
<version>2.5 </version>
</dependency>
</dependencies>
<build>
<finalName>sample-web </finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty </groupId>
<artifactId>maven-jetty-plugin </artifactId>
<version>6.1.22 </version>
</plugin>
</plugins>
</build>
</project>

To start the web application in Jetty, run the run goal from the Maven Jetty plugin by running mvn jetty:run.

$ mvn jetty:run
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building sample-web Maven Webapp
[INFO] task-segment: [jetty:run]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing jetty:run
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (MacRoman actually) to copy filtered
resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources {execution: default-testResources}]
[WARNING] Using platform encoding (MacRoman actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory ~/maven-cookbook/ mcookbook-examples/web/sample-web/src/test/resources
[INFO] [compiler:testCompile {execution: default-testCompile}]
[INFO] No sources to compile
[INFO] [jetty:run {execution: default-cli}]
[INFO] Configuring Jetty for project: sample-web Maven Webapp
[INFO] Webapp source directory = ~/maven-cookbook/mcookbook-examples/web/ sample-web/src/main/webapp
[INFO] Reload Mechanic: automatic
[INFO] Classes = ~/maven-cookbook/mcookbook-examples/web/sample-web/ target/classes
2009-11-28 19:25:18.129:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
[INFO] Context path = /sample-web
[INFO] Tmp directory = determined at runtime
[INFO] Web defaults = org/mortbay/jetty/webapp/webdefault.xml
[INFO] Web overrides = none
[INFO] web.xml file = ~/maven-cookbook/mcookbook-examples/web/sample-web/ src/main/webapp/WEB-INF/web.xml
[INFO] Webapp directory = ~/maven-cookbook/mcookbook-examples/web/sample-web /src/main/webapp
[INFO] Starting jetty 6.1.22 ...
2009-11-28 19:25:18.231:INFO::jetty-6.1.22
2009-11-28 19:25:18.405:INFO::No Transaction manager found - if your webapp requires one, please configure one.
2009-11-28 19:25:18.800:INFO::Started SelectChannelConnector@0.0.0.0:8080
[INFO] Started Jetty Server

At this point, you can use a web browser to navigate to http://localhost:8080/sample-web/ to interact with the web application.

6.1.3. Detail

Consider a simple web application with a single index.jsp page that contains a form, and a single Servlet that calculates a number from the Fibonacci sequence.

Example 6.1. Simple Form Accepting an Index to Pass to the Fibonacci Servlet

<html>
<body>
<h2>Fibonacci Page</h2>
<form action="fib" method="GET">
<p>Fetch Fibonacci Sequence Index:
<input type="text" name="index" size="5"/></p>
<input type="submit" value="Calculate"/>
</form>
</body>
</html>

The following class is the Servlet which calculates the Fibonacci sequence. It takes a single parameter index and simply prints of the number at the specified position of the Fibonacci sequence.

Example 6.2. Fibonacci Servlet which Calculates a Number from the Fibonacci Sequence

package org.sonatype.mcookbook;

import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FibonacciServlet extends HttpServlet {

protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
int index = Integer.parseInt(req.getParameter("index"));
resp.getWriter().write( fib(index) + "" );
resp.getWriter().flush();
resp.getWriter().close();
}

public long fib(int n) {
if (n <= 1) return n;
else return fib(n-1) + fib(n-2);
}
}

The following web.xml configures the FibonacciServlet to respond to the request path <context>/fib.

Example 6.3. Web Application Descriptor for sample-web

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>fibonacci</servlet-name> <servlet-class>org.sonatype.mcookbook.FibonacciServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>fibonacci</servlet-name> <url-pattern>/fib</url-pattern> </servlet-mapping> </web-app>

After running mvn:jetty, you can load the initial form by going to http://localhost:8080/sample-web/index.jsp. Populating the form with an index and pressing calculate will load the Fibonacci servlet and print out the number at that position of the sequence.

6.2. Starting a WAR Dependency in a Servlet Container

6.2.1. Task

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

6.2.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>
<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>
<configuration>
<contextPath>jackrabbit</contextPath>
<daemon>false</daemon>
<webApp
${project.build.directory}/war/jackrabbit-webapp.war
</webApp>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<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>
<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.

4

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.