If you have a few years of experience in the Java ecosystem, and you're interested in sharing that experience with the community (and getting paid for your work of course), have a look at the "Write for Us" page. Cheers. Eugen

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

Jersey is an open source framework for developing RESTful Web Services. It serves as a reference implementation of JAX-RS.

In this article, we will explore the creation of RESTful Web Service using Jersey 2. We will use Spring’s Dependency Injection (DI) with Java configuration.

2. Maven Dependencies

Let’s begin by adding dependencies in the pom.xml:

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>2.25</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.25</version>
</dependency>

For Spring integration:

<dependency>
    <groupId>org.glassfish.jersey.ext</groupId>
    <artifactId>jersey-spring3</artifactId>
    <version>2.25</version>
</dependency>

The latest version of these dependencies can be found at jersey-container-servletjersey-media-json-jackson and jersey-spring3.

We have used Spring 3 here as Jersey integration with Spring 4 is not available at the time of writing.

3. Web Configuration

We need to setup a web project to do Servlet configuration. We’ll use Spring’s WebApplicationInitializer:

@Order(Ordered.HIGHEST_PRECEDENCE)
public class ApplicationInitializer 
  implements WebApplicationInitializer {
 
    @Override
    public void onStartup(ServletContext servletContext) 
      throws ServletException {
 
        AnnotationConfigWebApplicationContext context 
          = new AnnotationConfigWebApplicationContext();
 
        servletContext.addListener(new ContextLoaderListener(context));
        servletContext.setInitParameter(
          "contextConfigLocation", "com.baeldung.server");
    }
}

The annotation @Order(Ordered.HIGHEST_PRECEDENCE) is used to ensure that our initializer is executed before the Jersey-Spring provided default initializer.

4. A Service Using Jersey JAX-RS

4.1. Resource Representation Class

Let’s use a sample resource representation class:

@XmlRootElement
public class Employee {
    private int id;
    private String firstName;

    // standard getters and setters
}

JAXB annotations like @XmlRootElement are required only if XML support is needed (in addition to JSON).

4.2. Service Implementation

Let’s now look at how JAX-RS annotations can be used to create RESTful web services:

@Path("/employees")
public class EmployeeResource {
 
    @Autowired
    private EmployeeRepository employeeRepository;

    @GET
    @Path("/{id}")
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public Employee getEmployee(@PathParam("id") int id) {
        return employeeRepository.getEmployee(id);
    }

    @POST
    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public Response addEmployee(
      Employee employee, @Context UriInfo uriInfo) {
 
        employeeRepository.addEmployee(new Employee(employee.getId(), 
          employee.getFirstName(), employee.getLastName(), 
          employee.getAge()));
 
        return Response.status(Response.Status.CREATED.getStatusCode())
          .header(
            "Location", 
            String.format("%s/%s",uriInfo.getAbsolutePath().toString(), 
            employee.getId())).build();
    }
}

The @Path annotation provides the relative URI path to the service. Variables can be embedded within the URI syntax, as can be seen in {id}. Variables are substituted at runtime. The @PathParam annotation is used to obtain the value of the variable.

@GET, @PUT, @POST, @DELETE and @HEAD define the HTTP method of the request, which will be processed by annotated methods.

@Produces annotation defines endpoint’s response type (MIME media type). In our example, it is configured to return either JSON or XML depending on the value of HTTP header Accept (application/json or application/xml).

@Consumes annotation defines the MIME media types that can be consumed by the service. In our example, it is configured to consume either JSON or XML depending on the HTTP header Content-Type (application/json or application/xml).

The @Context annotation is used to inject information into a class field, bean property or method parameter. In our example, it is used to inject UriInfo. It can also be used to inject ServletConfig, ServletContext, HttpServletRequest and HttpServletResponse.

5. Using ExceptionMapper

ExceptionMapper allows us to intercept the exceptions and return appropriate HTTP response code to the client. In the following example, HTTP response code 404 is returned if EmployeeNotFound exception is thrown:

@Provider
public class NotFoundExceptionHandler 
  implements ExceptionMapper<EmployeeNotFound> {
 
    public Response toResponse(EmployeeNotFound ex) {
        return Response.status(Response.Status.NOT_FOUND).build();
    }
}

6. Managing Resource Classes

Finally, let’s wire up all service implementation classes and exception mappers against and application path:

@ApplicationPath("/resources")
public class RestConfig extends Application {
    public Set<Class<?>> getClasses() {
        return new HashSet<Class<?>>(
          Arrays.asList(
            EmployeeResource.class, 
            NotFoundExceptionHandler.class, 
            AlreadyExistsExceptionHandler.class));
    }
}

7. API Testing

Let’s now test the APIs with some live tests:

public class JerseyApiLiveTest {

    private static final String SERVICE_URL
      = "http://localhost:8082/spring-jersey/resources/employees";

    @Test
    public void givenGetAllEmployees_whenCorrectRequest_thenResponseCodeSuccess() 
      throws ClientProtocolException, IOException {
 
        HttpUriRequest request = new HttpGet(SERVICE_URL);

        HttpResponse httpResponse = HttpClientBuilder
          .create()
          .build()
          .execute(request);

        assertEquals(httpResponse
          .getStatusLine()
          .getStatusCode(), HttpStatus.SC_OK);
    }
}

8. Conclusion

In this article, we have introduced Jersey framework and developed a simple API. We have used Spring for Dependency Injection features. We have also seen the use of ExceptionMapper.

As always, the full source code is available in this Github project.

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE LESSONS