JAX-RS (using Apache CXF) in embedded Tomcat example

I had serious trouble today firing up an embedded Tomcat server that serves up REST resources using JAX-RS via Apache CXF.

Here’s minimal example, hopefully saving you the same trouble:

src/HelloJaxRs.java:

import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;

public class HelloJaxRs
{
    public static void main( String[] args ) throws Exception
    {
        Tomcat tomcat = new Tomcat();
        Context context = tomcat.addContext( "/", "" );

        Wrapper servlet = context.createWrapper();
        servlet.setName( "jaxrs" );
        servlet.setServletClass(
            "org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet" );

        servlet.addInitParameter(
            "jaxrs.serviceClasses",
            Hello.class.getName()
        );

        servlet.setLoadOnStartup( 1 );
        context.addChild( servlet );
        context.addServletMapping( "/rest/*", "jaxrs" );

        tomcat.start();
        tomcat.getServer().await();
    }
}

src/Hello.java:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path( "/hello/{name}" )
public class Hello
{
    @GET
    public String getThing( @PathParam( "name" ) String name )
    {
        return "Hello, " + name;
    }
}

build.xml:


<?xml version="1.0" encoding="UTF-8"?>
<project default="run">

    <target name="run" depends="compile">
        <mkdir dir="bin/tomcat.8080/webapps"/>
        <java
            classname="HelloJaxRs"
            fork="true"
            failonerror="true"
            dir="bin"
        >
            <classpath>
                <pathelement location="bin/"/>
                <fileset dir="lib"><include name="**/*.jar"/></fileset>
            </classpath>
        </java>
    </target>

    <target name="compile">
        <mkdir dir="bin"/>
        <javac srcdir="src" destdir="bin">
            <classpath>
                <fileset dir="lib"><include name="**/*.jar"/></fileset>
            </classpath>
            <compilerarg value="-Werror"/>
        </javac>
    </target>

</project>

To download the dependencies (or you can do something clever with Maven):

$ mkdir lib
$ cd lib
$ wget http://www.webhostingjams.com/mirror/apache/tomcat/tomcat-7/v7.0.57/bin/apache-tomcat-7.0.57.tar.gz
$ tar -xzf apache-tomcat-7.0.57.tar.gz
$ wget http://www.apache.org/dyn/closer.cgi?path=/cxf/3.0.3/apache-cxf-3.0.3.tar.gz
$ tar -xzf apache-cxf-3.0.3.tar.gz
$ cd ..

To run Tomcat:

$ ant

Then, in another terminal, you can see it’s working:

$ curl http://localhost:8080/rest/hello/andy
Hello, andy