API REST con Jersey y Spring

DESCANSO Arriba

Acabo de anunciar el nuevo curso Learn Spring , centrado en los fundamentos de Spring 5 y Spring Boot 2:

>> VER EL CURSO

1. Información general

Jersey es un marco de código abierto para desarrollar servicios web RESTful. Sirve como implementación de referencia de JAX-RS.

En este artículo, exploraremos la creación de un servicio web RESTful utilizando Jersey 2 . Además, usaremos la inyección de dependencia (DI) de Spring con la configuración de Java.

2. Dependencias de Maven

Comencemos agregando dependencias al pom.xml :

 org.glassfish.jersey.containers jersey-container-servlet 2.26   org.glassfish.jersey.media jersey-media-json-jackson 2.26 

Además, para la integración de Spring tenemos que agregar la dependencia jersey-spring4 :

 org.glassfish.jersey.ext jersey-spring4 2.26 

La última versión de estas dependencias está disponible en jersey-container-servlet, jersey-media-json-jackson y jersey-spring4.

3. Configuración web

A continuación, necesitamos configurar un proyecto web para realizar la configuración de Servlet. Para esto, usaremos WebApplicationInitializer de Spring :

@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"); } }

Aquí, estamos agregando la anotación @Order (Ordered.HIGHEST_PRECEDENCE) para asegurarnos de que nuestro inicializador se ejecute antes que el inicializador predeterminado de Jersey-Spring.

4. Un servicio que utiliza Jersey JAX-RS

4.1. Clase de representación de recursos

Usemos una clase de representación de recursos de muestra:

@XmlRootElement public class Employee { private int id; private String firstName; // standard getters and setters }

Tenga en cuenta que las anotaciones JAXB como @XmlRootElement son necesarias solo si se necesita compatibilidad con XML (además de JSON).

4.2. Implementación de servicios

Veamos ahora cómo podemos usar las anotaciones JAX-RS para crear servicios web RESTful:

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

La anotación @Path proporciona la ruta URI relativa al servicio. También podemos incrustar variables dentro de la sintaxis de URI, como muestra la variable {id} . Luego, las variables se sustituirán en tiempo de ejecución. Para obtener el valor de la variable podemos usar la anotación @PathParam .

@GET , @PUT , @POST, @DELETE y @HEAD definen el método HTTP de la solicitud , que será procesada por métodos anotados.

La anotación @Produces define el tipo de respuesta del punto final (tipo de medio MIME). En nuestro ejemplo, lo hemos configurado para devolver JSON o XML según el valor del encabezado HTTP Accept ( application / json o application / xml ).

Por otro lado, la anotación @Consumes define los tipos de medios MIME que puede consumir el servicio. En nuestro ejemplo, el servicio puede consumir JSON o XML según el tipo de contenido del encabezado HTTP ( aplicación / json o aplicación / xml ).

La anotación @Context se usa para inyectar información en un campo de clase, propiedad de bean o parámetro de método. En nuestro ejemplo, lo usamos para inyectar UriInfo . También podemos usarlo para inyectar ServletConfig , ServletContext , HttpServletRequest y HttpServletResponse.

5. Uso de ExceptionMapper

ExceptionMapper nos permite interceptar las excepciones y devolver el código de respuesta HTTP apropiado al cliente. En el siguiente ejemplo, se devuelve el código de respuesta HTTP 404 si se lanza la excepción EmployeeNotFound :

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

6. Gestión de clases de recursos

Finalmente, conectemos todas las clases de implementación de servicios y mapeadores de excepciones con una ruta de aplicación:

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

7. Pruebas de API

Probemos ahora las API con algunas pruebas en vivo:

public class JerseyApiLiveTest { private static final String SERVICE_URL = "//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. Conclusión

En este artículo, presentamos el marco de Jersey y desarrollamos una API simple. Hemos utilizado Spring para las funciones de inyección de dependencia. También hemos visto el uso de ExceptionMapper .

Como siempre, el código fuente completo está disponible en este proyecto de Github.

DESCANSO inferior

Acabo de anunciar el nuevo curso Learn Spring , centrado en los fundamentos de Spring 5 y Spring Boot 2:

>> VER EL CURSO