====== Validación de Métodos en Componentes JBoss Seam ====== --- //[[juanmiguelbg@um.es|JUAN MIGUEL BERNAL GONZALEZ]] 2015/12/04 12:32// Hemos añadido la posibilidad de hacer la validación de los métodos de los componenetes Seam (aquellos que se definen en el fichero //componentes.xml// mediante la etiqueta //// o mediante la anotacion //@Name//, tanto para //beans// Java como para //EJBs// de sessión. Para validar un método solo hay que añadir la anotación //org.jboss.seam.annotations.validation.@MethodValidated// en el método a validar. Cuando un componente Seam forma parte de una jerarquía de herencia, las anotaciones de validación tienen que encontrarse en la clase o interface raíz de la jerarquía. Cuando el componente Seam es un EJB, las anotaciones de validación tienen que estar en una interface, no pueden estar en la implementación ni ser un EJB sin interfaces (un //@LocalBean//). Para esta validación podéis utilizar los validadores de [[http://beanvalidation.org/1.0/spec/|Bean Validation 1.0]] e [[http://docs.jboss.org/hibernate/validator/4.3/reference/en-US/html/|Hibernate Validation 4.3.2.Final]], además de los que os hayáis definido vosotros con estas tecnologías. ===== Configuración de la Aplicación ===== Tenemos que realizar las siguientes modificaciones: * Abrimos el POM Principal del proyecto y modificamos el //// a la versión [[https://archiva.um.es/archiva/#artifact~internal/es.um.atica.fundeweb/parent|2.0.20 o posterior]]. * Posiblemente, tengamos problemas de dependencias si estabamos en una version del //// anterior a la 2.0.17. Para solucionar el problema, abrimos el POM del módulo WEB y eliminamos las dependencias //cas-client-core// y //velocity// y añadimos las siguiente en su lugar: org.jasig.cas.client cas-client-support-saml * Abrimos el fichero //weblogic-applicaction.xml// y añadimos dentro de la etiqueta //// la etiqueta //org.hibernate.validator.*//. ===== Ejemplos ===== Veamos un par de ejemplos con un componente Seam //Java bean//: package es.um.atica.portalfundeweb.rest; import javax.validation.Valid; import javax.validation.constraints.NotNull; import org.hibernate.validator.constraints.Length; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.validation.MethodValidated; import org.jboss.seam.log.Log; import org.hibernate.validator.constraints.Length; @Name("pruebaValidacion") public class PruebaValidacion { @MethodValidated @Length(min=5) public String saluda(@NotNull @Length(min=2, max=10) String nombre) { return "Hola " + nombre + "!!!" ; } @MethodValidated @Valid public PersonaPrueba validaPersonaPrueba( @NotNull @Length(min = 2, max = 10 ) String nombre, @NotNull @Length(min = 2, max = 10 ) String apellido, @NotNull @Length(min = 2, max = 10 ) String movil ) { return new PersonaPrueba(nombre, apellido, movil); } } En el comonente Seam //PruebaValidacion// tenemos dos métodos //saluda// y //validaPersonaPrueba//, estos métodos tienen anotaciones de validación, tanto para los parámetros de entrada como para el resultado de la operación. Además de la anotación //@MethodValidated//, que indica, que el método se debe validar. Para el método //saluda//, el parámetro de entrada //nombre// no puede ser nulo y tiene que tener una longitud entre 2 y carácteres. El resultado del método tiene que tener una longitud mínima de 5 carácteres. Para el método //validaPersonaPrueba//, los parámetros de entrada no puede ser nulos y tienen que tener una longitud entre 2 y carácteres. El resultado del método es una instancia de la clase //PersonaPrueba//. Para validar un tipo complejo, se utiliza la anotación //javax.validation.@Valid//. package es.um.atica.portalfundeweb.rest; import javax.validation.constraints.NotNull; import org.hibernate.validator.constraints.Length; public class PersonaPrueba { public PersonaPrueba(String nombre, String apellido, String movil) { this.nombre = nombre; this.apellido = apellido; this.movil = movil; } @NotNull @Length(min=5, max=10) private String nombre; @NotNull @Length(min=5, max=10) private String apellido; @NotNull @Length(min=5, max=10) private String movil; public String getNombre() { return nombre; } public void setNombre( String nombre ) { this.nombre = nombre; } public String getApellido() { return apellido; } public void setApellido( String apellido ) { this.apellido = apellido; } public String getMovil() { return movil; } public void setMovil( String movil ) { this.movil = movil; } @Override public String toString() { return nombre + " " + apellido + " --> " + movil; } } La anotación //javax.validation.@Valid// indica al sistema de validación, que valide las propiedades de la clase //PersonaPrueba//. Esta clase tiene tres propiedades que no pueden ser nulas y tienen que tener una longitud comprendida entre 5 y 10 carácteres. Veamos los mismos ejemplos con un componente Seam //EJB//: * Primero la interface: package es.um.atica.portalfundeweb.validacion; import javax.validation.Valid; import javax.validation.constraints.NotNull; import org.hibernate.validator.constraints.Length; import org.jboss.seam.annotations.validation.MethodValidated; import es.um.atica.portalfundeweb.rest.PersonaPrueba; public interface PruebaValidacionEjb { @MethodValidated @Length(min=5) String saluda(@NotNull @Length(min=2, max=10) String nombre); @MethodValidated @Valid PersonaPrueba validaPersonaPrueba( @NotNull @Length(min = 2, max = 10 ) String nombre, @NotNull @Length(min = 2, max = 10 ) String apellido, @NotNull @Length(min = 2, max = 10 ) String movil ); } * Ahora la implementación: package es.um.atica.portalfundeweb.validacion; import javax.ejb.Local; import javax.ejb.Stateless; import org.jboss.seam.annotations.Name; import es.um.atica.portalfundeweb.rest.PersonaPrueba; @Local(PruebaValidacionEjb.class) @Stateless @Name("pruebaValidacionEjb") public class PruebaValidacionEjbImpl implements PruebaValidacionEjb { @Override public String saluda(String nombre){ return "Hola " + nombre + "!!!" ; } @Override public PersonaPrueba validaPersonaPrueba(String nombre, String apellido, String movil ) { return new PersonaPrueba(nombre, apellido, movil); } } ===== La Anotación @MethodValidated ===== La anotación //org.jboss.seam.annotations.validation.@MethodValidated// tiene la siguiente definición: package org.jboss.seam.annotations.validation; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.Target; import org.jboss.seam.validation.ValidationMode; import org.jboss.seam.validation.handlers.MethodConstraintViolationHandler; import org.jboss.seam.validation.handlers.ThrowValidationExceptionHandler; /** * This is an annotation that is used with the Interceptor MethodValidationInterceptor, * that will validate the parameters and the result of a executed method in a seam component. * * @author juanmiguelbg * @version 0.0.1 */ @Target(METHOD) @Retention(RUNTIME) @Inherited public @interface MethodValidated { /** * Execute the validation on the method parameters only. */ ValidationMode mode() default ValidationMode.BOTH; /** * A - potentially empty - number of validation groups for which * the validation shall be performed. The @link {@link javax.validation.groups.Default} * group will be validated if no group is given. */ Class[] groups() default { javax.validation.groups.Default.class }; Class constraintViolationHandler() default ThrowValidationExceptionHandler.class; } La anotación tiene las siguientes propiedades: * **//mode//**: el modo de validación, que puede ser un valor del enumerado //org.jboss.seam.validation.ValidationMode//: * //BOTH//: validar los parámetros y la respuesta (valor por defecto). * //PARAMETERS//: solo validar los parámetros. * //RESULT//: solo validar el resultado. * //NONE//: no validar. * **//groups//**: [[http://docs.jboss.org/hibernate/validator/4.3/reference/en-US/html/validator-usingvalidator.html#validator-usingvalidator-validationgroups|el grupo de validación]]. Se pueden agrupar validaciones. El grupo por defecto es //javax.validation.groups.Default.class//. * **//constraintViolationHandler//**: clase que implementa la interface //org.jboss.seam.validation.handlers.MethodConstraintViolationHandler//, que permite indicar que hacer con los violaciones de las restricciones de validación. Los //handlers// disponibles son: * //org.jboss.seam.validation.handlers.ThrowValidationExceptionHandler//: que lanza la excepción //org.jboss.seam.validation.exceptions.ValidationException// con el conjunto de las restricciones violadas. Si estamos dentro de una transacción, y se lanza dicha exceción, y esta sale del punto de creación (//begin//) de la transacción, la transacción se marcara para //rollback//. Es el //handler// por defecto, también es el comportamiento por defecto en JEE 7. * //org.jboss.seam.validation.handlers.AddToStatusMessageHandler//: que añade la información de las restricciones violadas al //StatusMessages//, que luego se mostraran en el componente PrimeFaces //Growll// o en el //Messages// global de la aplicación. Este //handler// no lanza excepción, por tanto si esta dentro de una transacción, esta no se marcara para //rollback//. ---- ===== Bibliografía y Referencias ===== === Bean Validation === * [[http://beanvalidation.org/1.0/spec/|JSR 303: Bean Validation 1.0 - Specification]] * [[http://beanvalidation.org|Bean Validation Official Site]] === Hibernate Validator === * Hibernate Validator 4.3 - [[http://docs.jboss.org/hibernate/validator/4.3/reference/en-US/html/|Documentation]] - [[http://docs.jboss.org/hibernate/validator/4.3/api/|API]] * [[http://antoniogoncalves.org/2010/03/03/bean-validation-with-jpa-1-0/|Bean Validation with JPA 1.0]] === The Java EE 6 Tutorial === * The Java EE 6 Tutorial - [[http://docs.oracle.com/javaee/6/tutorial/doc/gircz.html|Using Bean Validation]] - [[http://docs.oracle.com/javaee/6/tutorial/doc/bnbqa.html#gkahq|Validating Persistent Fields and Properties]] - [[http://docs.oracle.com/javaee/6/tutorial/doc/gkahp.html|Bean Validation: Advanced Topics]]