The introduction

When it comes to RestFul, it’s easy to think of the Spring framework, and if you haven’t worked with it before, it’s recommended to click on the portal to learn how to quickly build a RestFul Web service using Spring.

Today we are building a Restful service by integrating Spring with Jersey, another lightweight framework. Jersey is an open source framework for building Restful Web services. Is a concrete implementation of the JAX-RS specification.

Maven rely on

First we introduce jersey-related dependencies:

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>3.0.1</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>3.0.1</version>
    </dependency>
Copy the code

To integrate the Spring framework, we also need to introduce jersey-Spring 4 dependencies:

    <! -- Integrate spring -->
    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-spring4</artifactId>
        <version>3.0.0 - M6</version>
    </dependency>
Copy the code

Web configuration

Next, we need to create a Web project for the Servlet configuration, use the Spring WebApplicationInitializer.

@Order(Ordered.HIGHEST_PRECEDENCE)
public class ApplicationInitializer implements WebApplicationInitializer {

    public void onStartup(javax.servlet.ServletContext servletContext) {
        AnnotationConfigWebApplicationContext context
                = new AnnotationConfigWebApplicationContext();

        servletContext.addListener(new ContextLoaderListener(context));
        servletContext.setInitParameter("contextConfigLocation"."com.example.server"); }}Copy the code

Here add @ Order (Ordered HIGHEST_PRECEDENCE) the role of annotation is to ensure that the WebApplicationInitializer in Jersey – Spring before the default initialization program execution.

Use the Jersey JAX-RS service

Resource representation class

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

    public int getId(a) {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName(a) {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName; }}Copy the code

JAXB annotations like @XMLRootelement need to be introduced when only XML support is required (other than JSON),

Implementation services

Now let’s build a RESTful Web service using JAX-RS annotations:

@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(); }}Copy the code

The @path annotation represents the service request route. We can also embed variables in the request route, such as {id} in the code. If you need to get the value of this variable, you can annotate it with @pathParam.

@get, @PUT, @post, @delete, and @head indicate how HTTP requests are made.

Produces represents the data type of the response, which in our example we have configured to return JSON or XML based on the HTTP request header (Acceptapplication/ JSON or Application/XML).

@Consumes defines the MIME types that are available for services. The data types depend on the content-type (application/ JSON or Application/XML) of the request header.

The @context annotation is used to inject information into a class field, bean property, or method parameter. In the example, we use it to inject UriInfo. We can also use it to inject ServletConfig, ServletContext, HttpServletRequest, and HttpServletResponse.

Using ExceptionMapper

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

@Provider
public class NotFoundExceptionHandler 
 implements ExceptionMapper<EmployeeNotFound> {

   public Response toResponse(EmployeeNotFound ex) {
       returnResponse.status(Response.Status.NOT_FOUND).build(); }}Copy the code

Managing Resource Classes

Finally, let’s connect all service implementation classes and exception mappings according to the application path:

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

The API test

public class JerseyApiLiveTest {

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

    @Test
    public void givenGetAllEmployees_whenCorrectRequest_thenResponseCodeSuccess(a) 
      throws ClientProtocolException, IOException {
 
        HttpUriRequest request = newHttpGet(SERVICE_URL); HttpResponse httpResponse = HttpClientBuilder .create() .build() .execute(request); assertEquals(httpResponse .getStatusLine() .getStatusCode(), HttpStatus.SC_OK); }}Copy the code

conclusion

This article introduced the Jersey framework and developed a simple API. We introduced Spring for dependency injection. We also saw the use of ExceptionMapper.