Los bean params hacen referencia a la capacidad de JAX-RS para recibir como parámetro objetos complejos definidos por una clase, esta clase puede ser vista como un Data Transfer Object (DTO), la cual contiene una serie de propiedades recuperadas de varias partes del request, como el header, query, path y formulario.
NOTA: Este artículo es parte de un tutorial completo para crear API REST con JAX-RS, si quieres ver el índice completo entra aquí.
Los Beans params no es una característica nativa del protocolo HTTP o la arquitectura REST, si no que JAX-RS la agrega para poder mapear todos los tipos de parámetros en una sola clase, la cual podríamos ver como un DTO que concentra en un solo punto todos los parámetros esperados.
Para comprender mejor como funcionan los Beans params, imaginemos que tenemos un formulario para registrar nuevos clientes, este formulario enviara al servicio todos los campos al API por medio de @FormParams
, también enviaremos como un header un token de autenticación, para identificar al usuario que está realizando la invocación, imaginemos que el cliente llego por medio de una campaña promocional, por lo que necesitamos saber si llego por facebook, google, etc. por lo que enviaremos un @QueryParam
para saber de donde llego el cliente.
Este caso, podríamos crear un parámetro en Java para uno de los parámetros esperados o podríamos crear una clase como la siguiente:
package api.services;
import javax.ws.rs.*;
public class CustomerDTO {
@CookieParam("token")
private String token;
@FormParam("firstname")
private String firstname;
@FormParam("lastname")
private String lastname;
@FormParam("status")
private String status;
@QueryParam("source")
private String source;
/* GET and SET */
}
La clase CustomerDTO
es en realidad una composición de variables que son recuperadas de varias partes de la petición. Solo en este caso hemos recuperado parámetros de las cookies (@CookieParam
), form (@FormParam
), query (@QueryParam
), sin embargo, la idea de los @BeanParam
es que se pueden utilizar cualquiera de las @xxxParam, lo que quiere decir que podemos utilizar:
- @PathParam
- @QueryParam
- @MatrixParam
- @CookieParam
- @HeaderParam
El siguiente paso es crear un método REST que reciba el @BeanParam
:
package api.services;
import java.util.Map;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
@Path("customers")
public class CustomersService {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response saveCustomer(@BeanParam CustomerDTO customer) {
String result = String.format("firstname = %s, lastname = %s, status = %s, token = %s, source = %s",
new Object[]{customer.getFirstname(),
customer.getLastname(),
customer.getStatus(),
customer.getToken(),
customer.getSource()});
return Response.ok(result).build();
}
}
El formulario con el que invocaremos el servicio REST es el siguiente:
<!DOCTYPE html>
<html>
<body>
<p>Customer form</p>
<form action="http://localhost:8080/api-0.0.1-SNAPSHOT/customers?source=google" method="post">
<div>
<label for="firstname" style="display:inline-block; width: 100px;">Nombre</label>
<input id="firstname" type="text" name="firstname" />
</div>
<div>
<label for="lastname" style="display:inline-block; width: 100px;">Apellido</label>
<input id="lastname" type="text" name="lastname" />
</div>
<div>
<label for="status" style="display:inline-block; width: 100px;">Estatus</label>
<select id="status" name="status" >
<option value="active">Activo</option>
<option value="inactive">Inactivo</option>
</select>
</div>
<br/>
<input type="submit" value="Guardar" />
</form>
</body>
</html>
Observemos que hemos agregado el query param en el action
del <form>
, por lo que será enviado al servidor al momento del submit.
Adicional, agregaremos la cookie token directamente desde el inspector de chrome:
Y obtendremos el siguiente resultado:
Conclusiones
Como hemos podido validar, los @BeanParam
son una excelente estrategia para realizar una composición de una serie de parámetros en una sola fuente de datos, los cuales podríamos fácilmente reutilizar para más de un servicio. Además, nos evita tener que definir una serie de parámetros para poder recuperar cada uno de los valores esperados.
Muchas gracias por compartir tus conocimientos con la comunidad.
Saludos Oscar.