Tabla de Contenidos

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 @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 @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:

<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 */
        ...
}

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 GEA 01/02/2022 09:27


Bibliografia y Ejemplos


JUAN MIGUEL BERNAL GONZALEZ 01/12/2020 13:56