====== Agrupación de Parámetros con @BeanParam ====== En los servicios Rest podemos agrupar los parámetros que recibe una invocación con la anotación [[https://docs.oracle.com/javaee/7/api/javax/ws/rs/BeanParam.html|@BeanParam]]. Para poder utilizarlo tenemos que tener actualizado FundeWeb a las versiones 2.0.85 y/o 2.1.39. Para aplicaciones que despliegan en Weblogic 12.1, la versión del Parent en el POM principal tienes que ser 2.0.38 (2.0.38-primefaces6) o superior. Para aplicaciones que despliegan en Weblogic 12.2, la actualización del Parent debería ser automática. ===== Ejemplo ===== Supongamos que tenemos un servicio Rest que acepta muchos parámetros: 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(@CookieParam("token") String token, @FormParam("firstname") String firstname, @FormParam("lastname") String lastname, @FormParam("status") String status, @QueryParam("source") String source) { String result = String.format("firstname = %s, lastname = %s, status = %s, token = %s, source = %s", new Object[] { firstname, lastname, status, token, source }); return Response.ok(result).build(); } } Con la anotación [[https://docs.oracle.com/javaee/7/api/javax/ws/rs/BeanParam.html|@BeanParam]] podemos agruparlos en un //DTO// o //POJO//. 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(); } } Ahora la clase //CustomerDTO// contiene los parámetros junto a sus anotaciones Rest: 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 */ ... } Dentro de este DTO podemos utilizar las anotaciones: @PathParam, @QueryParam, @MatrixParam, @CookieParam y @HeaderParam. ===== Integración con Bean Validation ===== Para poder seguir usando Bean Validation, solo tenemos que poner la anotación //@Valid// delante de la anotación //@BeanParam//. Después las anotaciones de validación en los parámetros. package api.services; import java.util.Map; import javax.ws.rs.*; import javax.ws.rs.core.*; import javax.validation.Valid; @Path("customers") public class CustomersService { @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response saveCustomer(@Valid @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(); } } Y en el //DTO//: package api.services; import javax.ws.rs.*; import javax.validation.constraints.Size; public class CustomerDTO { @Size(min = 4) @CookieParam("token") private String token; @Size(min = 4) @FormParam("firstname") private String firstname; @Length(min = 4) @FormParam("lastname") private String lastname; @Size(max = 2) @FormParam("status") private String status; @Size(max = 100, min = 10) @QueryParam("source") private String source; /* GET and SET */ ... } ===== FAQs ===== === Excepción ParamException$BeanParamException: HTTP 400 Bad Request === Después de configurar servicio y DTO de la forma en que se indica en esta Wiki, al realizar una petición puede surgir la excepción: ... 31 ene 2022 13:16:33,175 ERROR (WebApplicationExceptionMapper.java:36) - Usuario: - Unexpected Error. com.sun.jersey.api.ParamException$BeanParamException: HTTP 400 Bad Request at com.sun.jersey.server.impl.model.parameter.BeanParamValueInjectableProvider$BeanParamValueInjectable.getValue(BeanParamValueInjectableProvider.java:46) at com.sun.jersey.server.impl.inject.InjectableValuesProvider.getInjectableValues(InjectableValuesProvider.java:86) at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$EntityParamInInvoker.getParams(AbstractResourceMethodDispatchProvider.java:153) ... //FundeWeb 2.0// **Solución** Revisar los constructores del DTO y dejar **__única y exclusivamente__** el constructor vacío. --- //[[ramon.ginel@ticarum.es|RAMON GINEL GEA]] 01/02/2022 09:27// ---- ===== Bibliografia y Ejemplos ===== * [[https://docs.oracle.com/javaee/7/api/javax/ws/rs/BeanParam.html|JEE - JAX-RS - @BeanParam]] * [[https://www.oscarblancarteblog.com/2019/01/17/bean-params/|Bean Params con @BeanParam]] ---- --- //[[juanmiguel.bernal@ticarum.es|JUAN MIGUEL BERNAL GONZALEZ]] 01/12/2020 13:56//