Partner – Microsoft – NPI (cat= Spring)
announcement - icon

Azure Spring Apps is a fully managed service from Microsoft (built in collaboration with VMware), focused on building and deploying Spring Boot applications on Azure Cloud without worrying about Kubernetes.

And, the Enterprise plan comes with some interesting features, such as commercial Spring runtime support, a 99.95% SLA and some deep discounts (up to 47%) when you are ready for production.

>> Learn more and deploy your first Spring Boot app to Azure.

You can also ask questions and leave feedback on the Azure Spring Apps GitHub page.

Course – LS (cat=REST)

Get started with Spring and Spring Boot, through the reference Learn Spring course:

>> 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’ll explore the creation of a RESTful Web Service using Jersey 2. Also, we’ll use Spring’s Dependency Injection (DI) with Java configuration.

2. Maven Dependencies

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

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

Also, for Spring integration we have to add the jersey-spring4 dependency:

<dependency>
    <groupId>org.glassfish.jersey.ext</groupId>
    <artifactId>jersey-spring4</artifactId>
    <version>2.26</version>
</dependency>

The latest version of these dependencies is available at jersey-container-servlet, jersey-media-json-jackson and jersey-spring4.

3. Web Configuration

Next, we need to set up a web project to do Servlet configuration. For this, 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");
    }
}

Here, we’re adding the @Order(Ordered.HIGHEST_PRECEDENCE) annotation to ensure that our initializer is executed before the Jersey-Spring 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
}

Note that 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 we can use JAX-RS annotations 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. We can also embed variables within the URI syntax, as the {id} variable shows. Then, the variables will be substituted at runtime. To obtain, the value of the variable we can use the @PathParam annotation.

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

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

On the other hand, the @Consumes annotation defines the MIME media types that the service can consume. In our example, the service can 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, we’re using it to inject UriInfo. We can also use it 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 an 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’ve introduced the Jersey framework and developed a simple API. We’ve 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.

Course – LS (cat=Spring)

Get started with Spring and Spring Boot, through the Learn Spring course:

>> THE COURSE
Course – LS (cat=REST)

Get started with Spring and Spring Boot, through the Learn Spring course :

>> CHECK OUT THE COURSE
res – REST (eBook) (cat=REST)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.