13

I have Knowledge of the Web container and Tomcat and can deploy static and dynamic web sites. But I am new to REST and Jersey. I have read the 2.6 user's guide, reviewed many sites and youtube videos. There seems to be a lot of info on 1.x Jersey but not much on 2.x I can get 1.18 working in my environment but can't seem to get any deployment models working for 2.x. I noticed in 2.x there is an Application deployment model. So I thought i would ask some very generic questions to get this started.

  1. Which deployment model is best for basic REST services through Tomcat 8 and why?
  2. I see that the .jars deployed with 2.6 are much different than the ones deployed with 1.18. Is there an easy way to tell which jars you need for a basic Tomcat installation?
  3. If you have a basic example, that would be great.

Thanks

rss181919
  • 427
  • 1
  • 5
  • 16
  • I just started looking at Jersey after spending the last couple years working with RestEasy. Any reason why you are 'forcing' Tomcat into the situation? Reason I ask is that I started with the Jersey User's Guide and followed their steps, which uses Maven for builds and Grizzly for the web server and it everything ran. I believe the initial sample uses Jersey 2.6. – mikemil Feb 28 '14 at 05:52
  • When you say "forcing Tomcat" are you referring to the fact that Jersey was tested on Grizzly and I should use that instead? By the way, I got it working in Tomcat per the directions in the users guide. I had a user error in my testing which made it look like it wasn't working when it was just me trying to access the wrong path. – rss181919 Feb 28 '14 at 17:22
  • Didn't mean it in a negative tone, just that I am recently going thru some of the same process and it was very easy to use their 'defaults' from the user guide. Glad to hear you got it running! BTW. make sure to accept your answer to your own question - you get some reputation points for that! :-) – mikemil Feb 28 '14 at 17:47

2 Answers2

44

What follows are what I hope are relatively complete solutions to your questions.

You don't mention Maven, so I will: Maven is your friend here.

Let's start with a 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>com.example.groupid</groupId>
  <artifactId>stack</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.containers</groupId>
      <artifactId>jersey-container-servlet-core</artifactId>
      <version>2.13</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.containers</groupId>
      <artifactId>jersey-container-servlet</artifactId>
      <version>2.13</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>stack</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.5</version>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.2</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <name>Stack</name>
</project>

That might not be the absolute minimum in terms of dependencies, but it's close.

But that's just the pom. The trickery continues in the web.xml and the Java classes.

About that web.xml...

It's insanely complicated, so bear with me:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         metadata-complete="false"
         version="3.1">
</web-app>

Ok, maybe not that complicated.

Note that setting metadata-complete="true" may result in Tomcat starting faster.

A pair of Java classes

One is the "application", the other is the rest call.***

The rest call is pretty straightforward:

package some.package;

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

@Path("/hello")
public class HelloRest {

  @GET
  public String message() {
    return "Hello, rest!";
  }
}

The application looks like this:

package some.package;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

import some.package.HelloRest;

@ApplicationPath("/rest")
public class RestApp extends Application {
  public Set<Class<?>> getClasses() {
    return new HashSet<Class<?>>(Arrays.asList(HelloRest.class));
  }
}

And that's it. When you navigate to something like http://localhost:8080/stack/rest/hello, you should see the text "Hello, rest!"

Leverage Jersey a bit.

getClasses() in RestApp is a little ugly. You might use Jersey's ResourceConfig, as at the Jersey User's Guide, which would look like this:

public class RestApp extends ResourceConfig {
    public RestApp() {
        packages("some.package");
    }
}

But I don't want to use Maven!

Fine. These are the jars Eclipse lists as Maven dependencies:

  • javax.servlet-api-3.1.0.jar
  • jersey-container-servlet-core-2.13.jar
  • javax.inject-2.3.0-b10.jar
  • jersey-common-2.13.jar
  • javax.annotation-api-1.2.jar
  • jersey-guava-2.13.jar
  • hk2-api-2.3.0-b10.jar
  • hk2-utils-2.3.0-b10.jar
  • aopalliance-repackaged-2.3.0-b10.jar
  • hk2-locator-2.3.0-b10.jar
  • javassist-3.18.1-GA.jar
  • osgi-resource-locator-1.0.1.jar
  • jersey-server-2.13.jar
  • jersey-client-2.13.jar
  • validation-api-1.1.0.Final.jar
  • javax.ws.rs-api-2.0.1.jar
  • jersey-container-servlet-2.13.jar

Presumably, adding those manually to your classpath should work. Or use Maven.

6cef
  • 672
  • 6
  • 17
  • 4
    Wow! This is a superb answer! Don't think I've ever come across a more complete answer... – markvgti Apr 21 '16 at 10:05
  • I wish the same thing could be accomplished without xml but instead o a `main()` method like you can with `HttpServer` – Sridhar Sarnobat Apr 09 '18 at 18:27
  • 1. what needs to be done if one wants to use different version of jersey(other than already present in Tomcat Server)? 2. It's possible to deploy war file bundled with servlet jar? 3. It's possible to use different version of jersey in existing Tomcat Server? – Rohit Kumar Jul 26 '20 at 10:54
1

I was able to get this working using the directions supplied in the Jersey 2.6 user's guide for deployment to a 3.x servlet container. I ended up using something similar to the item below. Because the URL mapping is supplied in the .xml, you can omit @ApplicationPath from the Application subclass.

<web-app version="3.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <!-- Servlet declaration can be omitted in which case
         it would be automatically added by Jersey -->
    <servlet>
        <servlet-name>org.example.MyApplication</servlet-name>
    </servlet>

    <!-- Servlet mapping can be omitted in case the Application subclass
         is annotated with @ApplicationPath annotation; in such case
         the mapping would be automatically added by Jersey -->
    <servlet-mapping>
        <servlet-name>org.example.MyApplication</servlet-name>
        <url-pattern>/myresources/*</url-pattern>
    </servlet-mapping>
</web-app>
rss181919
  • 427
  • 1
  • 5
  • 16