En los servicios Rest podemos agrupar los parámetros que recibe una invocación con la anotación @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.
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 @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.
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:
<code java> 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 */ ... }
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 GEA 01/02/2022 09:27