Mostrando entradas con la etiqueta annotation. Mostrar todas las entradas
Mostrando entradas con la etiqueta annotation. Mostrar todas las entradas

sábado, 5 de octubre de 2019

Java Annotations: Types y Bean Validation

Hoy vamos a hablar de las Type Annotations y como hacer las nuestras propias validaciones de codiga a traves de ellas. 

Basicamente las Type Annotations es la posibilidad a partir de Java 8 de utilizarlas cada vez que indiquemos un tipo de clase. Es decir en: operadores new, cast de objetos, clausulas de implementacion o lanzamiento de excepciones, etc. Y esto es posible gracias al enumerado TYPE_USE, indicadolo en el apartado target.

@Target({ ElementType.TYPE_USE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { DNIValidator.class })
public @interface DNI {
 Class<?>[] groups() default {};
 String message() default "DNI must be valid";
 Class<? extends Payload>[] payload() default {};
}

Y para ver un ejemplo practico, anadiremos a esta informacion la de las ConstraintValidator (basadas en la especificacion JSR-380, tambien conociada como Bean Validation 2.0). La cual nos permitira validar el contenido de nuestros objetos en tiempo de ejecucion. 

Para llevar a cabo el ejemplo necesitaremos las librerias
  • hibernate-validator: Que contiene la implementacion de JSR-380.
  • hibernate-validator-annotation-processor: Que permite el procesamiento de las anotaciones.
  •  javax.el: Que habilita el uso de EL para el manejo de mensajes en las anotaciones.
El ejemplo lo basaremos en la anotacion mostrada anteriormente pero para ello antes hay que explicar el resto del codigo que es obligatorio para el correcto funcionamiento.
  • Anotacion Retention: Donde le indicaremos la permanencia de la anotacion. Puede ser @Source que descarta la anotacion durante la compilacion, @Class descarta la anotacion durante la carga de la clase y @Runtime que mantiene siempre la anotacion.
  • Anotacion Constraint: Aqui indicaremos la clase o clases de validacion que queremos asociarle. 
  • Atributo groups: Donde le indicamos la agrupacion jerarquica de la anotacion, permitiendo a la hora de indicar la anotacion, a que grupos se aplica. 
  • Atributo message: Donde indicamos el mensaje de validacion asociado. 
  • Atributo payload: A traves del cual indicamos metadatos asociados a la naotacion. 
El siguiente paso sera la validacion asociada a dicha anotacion. Y la crearemos a traves de una clase que extienda de ConstraintValidator e implemente el metodo isValid. 

import java.util.regex.*;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class DNIValidator implements ConstraintValidator<DNI, String> {
 private static String REGEX = "\\d{8}[A-HJ-NP-TV-Z]";
 @Override
 public boolean isValid(final String arg0, final ConstraintValidatorContext arg1) {
  Pattern p = Pattern.compile(REGEX);
  Matcher m = p.matcher(arg0);
  return m.matches();
 }
}

Ahora solo nos quedaria la prueba. Para ellos crearemos una clase denominada group que contenga un grupo de personas (un mapa) donde indicaremos la anotacion tipada @DNI. Y posteriormente probaremos la clase y su validacion a traves de JUnit y ValidatorFactory.

public class Group {
 private Map<@DNI String, String> people = new HashMap<>();
 public void addPeople(final String dni, final String name) {
  people.put(dni, name);
 }
}
// ...
public class DNIValidatorTest {
 private Validator validator;
 @Test
 public void ko() {
  Group group = new Group();
  group.addPeople("01234567U", "Daniel");
  Set<ConstraintViolation<Group>> violations = validator.validate(group);
  assertThat(violations.isEmpty(), is(false));
 }
 @BeforeEach
 public void setUp() {
  ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
  validator = factory.getValidator();
 }
}

Un unltimo detall, debemos tener en cuenta que en la propia especificacion se indican multiples anotaciones, como pueden ser: @NotBlank, @Email, @NegativeOrZero, etc. Por lo que conviene echarles un vistazo previamente, no vaya a ser que ya exista aquella que querramos implementar.

martes, 14 de mayo de 2019

Lombok: Como reducir código tan necesario como tedioso

Hoy vamos a ver una librería pequeña pero super util, que nos va a evitar escribir código tedioso como son los getters y setters. Lombok nos permite hacer esto y más a través de anotaciones.

Antes de empezar a ver ejemplos, lo primero que tenemos que hacer es habilitar que nuestro IDE comprenda las anotaciones de Lombok y que en tiempo de compilación puedan ser usadas. Si usamos eclipse, debemos bajar el jar de la librería, por ejemplo de maven central, y ejecutar dicho jar con el comando java -jar. Esto nos abrirá un menú de instalación que nos permitirá instarlo en nuestro IDE.

Lo siguiente será añadir la librería como dependencia de nuestro proyecto. Una vez configurado podemos ver ejemplos de anotaciones y su funcionamiento. Una prueba del mismo, será al incluir nuestras anotaciones ver la vista outline, donde se habrán generado los metodos asociados a las anotaciones. 
  • @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor. Nos permiten crear constructuros de clase.
@NoArgsConstructor
@AllArgsConstructor
public class Saludo
  • @EqualsAndHashCode, @ToString. Anotaciones de clase que permiten generar métodos comunes de clase.
@ToString
@EqualsAndHashCode
@Entity
public class Book extends GenericEntity<Integer>{
  • @Getter, @Setter. Nos permiten olvidarnos de los famosos getter/setters.
private @Getter @Setter String saludo;
  • @Data que auna las anteriores anotaciones: @ToString, @EqualsAndHashCode, @Getter, @Setter y @RequiredArgsConstructor
  • @Value. Al reves que @Data crea todos los métodos igual que este, exceptuando los setters, ya que los atributos serán declarados como privados y finales. 
  • @CommonsLog, @Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j. Nos permiten generar el atributo log del tipo que deseemos para realizar las trazas de nuestro proyecto.
@Log4j
@RestController
public class SaludoRestController {
    @GetMapping("/saludo")
    public Saludo Saludo(@RequestParam(value = "nombre", defaultValue = "World") final String nombre) {
        log.info("Saludo - init");
        return new Saludo("Hola", nombre);
    }
}
  • @NonNull, lanzará un NullPointerException si el parámetro asociado es nulo.
@GetMapping("/{id}")
public Book findById(@NonNull @PathVariable("id") final Integer id) {
    return repository.findOne(id);
}
  • @Cleanup. Genera un bloque finally y cierra el recurso asociado a la anotación. Aunque si es closeable el recurso tampoco tiene mucho sentido en mi opinión. 
Podeis ver el código del ejemplo aquí.


martes, 4 de agosto de 2015

WebService con JAX-WS, JAXB y JPA - II

Vamos a mejorar el ejemplo que teniamos del webservices con JAX-WS. Ahora para introducirle la capa de acceso a datos. Esta parte la haremos usando otro estandar de Java EE: JPA.

¿Que es JPA o JAXB?
  • JPA: Es la API que permite hacer representaciones Java de objetos de BBDD relacionales y facilitar su manejo. Enlace Wikpedia Enlace Oficial
  • JAXB: Es la API que permite hacer representaciones java de documentos XML y facilitar su manejo. 
Para empezar le añadimos las librerías necesarias para que funcione JPA. Para ello elegimos la implementación de Hibernate:
  • hibernate-entitymanager: La implementación para el uso del entity manager por Hibernate.
  • hibernate-jpa-2.1-api: La implementación de Hibernate de JPA
  • Conector de base de datos: En mi caso MySQL. 
Una vez configurado las librerías vamos a crear el fichero de configuración de BBDD, con JPA normalmente es el conocido 'persistence.xml':


 org.hibernate.ejb.HibernatePersistence
 
  
  
  
  
  
  
  
  
 


En el podemos ver la siguiente configuración:
  • Hemos llamado a nuestra configuración 'myPersistenceUnit'.
  • Hemos indicado los datos de conexión: URL, usuario, password, driver de conexión, etc
  • Hemos indicado que se autodetecten las clases que utilizaremos para conectar a la BBDD. De lo contrario deberiamos indicar especificamente que clase serán las que representen los objetos relacionales de BBDD. 
  • Hemos indicado configuración adicional sobre las querys. En este caso que se muestren y se muestren formateadas. 
Para la parte de acceso a datos hemos creado una clase abstracta que permite obtener la entidad gestora de BBDD configurada en nuestro archivo, pero para eso deberemos indicarle cual es nuestra configuración

public abstract class AbstractDao {
 private static EntityManagerFactory emf;
 private final ThreadLocal em = new ThreadLocal() {
  @Override
  protected EntityManager initialValue() {
   return getEntityManagerFactory().createEntityManager();
  }
 };
 private EntityManagerFactory getEntityManagerFactory() {
  if (emf == null) {
   emf = Persistence.createEntityManagerFactory("myPersistenceUnit");
  }
  return emf;
 }
 protected EntityManager getEntityManager() {
  return em.get();
 }
}

Por otro lado creamos una interface DAO y su implementación con los cuales acceder a los datos de BBDD.

Ya casi estaría listo, crearemos un método del Web Service que llame a ese servicio DAO y que pueda obtener los datos de BBDD. Pero nos quedaría un pequeño asunto, ¿Como indicamos el formato de la respuesta?. Para esto utilizaríamos el JAXB, crearemos clases que tengan el formato de la información que queremos devolver en el servicio. Este formato se lo podemos indicar a través de anotaciones. Aquí un ejemplo de clase JAXB

@XmlRootElement
public class UserXml implements java.io.Serializable {
 private Integer userId;
 private String username;
 private String password;
 private boolean enabled;
 @XmlElement
 public Integer getUserId() {
  return userId;
 }
 @XmlElement
 public String getUsername() {
  return username;
 }
 @XmlElement
 public String getPassword() {
  return password;
 }
 @XmlElement
 public boolean isEnabled() {
  return enabled;
 }
        //setters
 public void setEnabled(final boolean enabled) {
  this.enabled = enabled;
 }
 public static UserXml valueOf(final User user) {
  UserXml userXml = new UserXml();
  userXml.setEnabled(user.isEnabled());
  userXml.setPassword(user.getPassword());
  userXml.setUserId(user.getUserId());
  userXml.setUsername(user.getUsername());
  return userXml;
 }

}

Y aquí un ejemplo del servicio web:

public List getUsers() {
 List list = dao.getUsers();
 List result = new ArrayList();
 for (User p : list) {
  result.add(UserXml.valueOf(p));
 }
 return result;
}

domingo, 2 de agosto de 2015

WebService con JAX-WS - I

La idea de este post y si puede ser de una serie de post futuros, es crear pequeños prototipos de los que partir para hacer futuros desarrollos.

Para este primer caso vamos a hacer un webservices con JAX-WS pero nada de spring, algo básico. Además aparte del post iré poniendo la dirección GIT donde lo tengo subido para que cualquiera pueda descargarlo y continuar con el mismo.

Si no estas familiarizado con la tecnología te hago aquí un pequeño resumen de que es cada estandar con el que crearemos la aplicación:
  • JAX-WS: Es la API de Java para la creación de servicios web que forma parte de JAVA EE. 
Para empezar creamos un proyecto web y lo reconfiguramos como proyecto maven. Las librerías que hemos necesitado han sido:
  • jaxws-rt: La implementación para el funcionamiento de JAX-WS
  • slf4j-api y log4j: Librerías para realizar logs
Una vez configurado el cliente vamos ha hacer dos cosas. Crear la propia interfaz del servicio web:

@WebService
public interface WebServiceSample {
 @WebMethod
 Saludo saludar();
 @WebMethod
 String despedir();
}

Y aquí esta su implementación, una cosa sencillita. La importancia del asunto recae en las anotaciones que marcan a la clase y a su implementación como servicio web.

@WebService(endpointInterface = "es.home.ws.example.WebServiceSample")
public class WebServiceSampleImpl implements WebServiceSample {
 @Override
 public Saludo saluda() {
  Saludo s = new Saludo();
  s.setNombre("John");
  s.setSaludo("Doe");
  return s;
 }
 @Override
 public String despedir() {
  return "Goodbye";
 }
}

En principio con esto nos valdría si desplegásemos en un servidor de aplicaciones web como weblogic o jboss. Pero nosotros vamos a hacerlo en un contenedor de servlets como Tomcat. Y para ello necesitaremos de dos configuraciones más. modificar el web.xml y crear el fichero sun-jaxws.xml

El fichero web.xml configuramos para la ruta por la que queremos que pasen las llamadas a nuestro webservices e indicamos el servlet que captará estas llamadas.


  com.sun.xml.ws.transport.http.servlet.WSServletContextListener
 
 
  webservice-sample
  com.sun.xml.ws.transport.http.servlet.WSServlet
  1
 
 
  webservice-sample
  /webservice-sample
 

En el fichero sun-jaxws.xml indicamos la configuración para que el servicio funcione correctamente. Esta configuración será leída por el servlet indicado en el web.xml y en ella le indicamos la url por la cual va a ser llamado el servicio (configurado en el web.xml) y que implementación realizará las llamadas


 


Una vez configurado si arrancamos el tomcat y accedemos a la URL:  http://localhost:8080/ExampleWS/webservice-sample veremos la configuración del servicio web y tendremos acceso a su WSDL.

En este enlace (ExampleWS) podreis encontrar el código fuente subido a Github.

Anotación: He tenido problema con maven al resolver las dependencias de jax-rt en su versión 2.2.10. La he cambiado por al 2.2.3 y ha funcionado correctamente.

lunes, 20 de enero de 2014

Control de excepciones con Spring su AOP y las anotaciones

A través de las anotaciones y los aspectos de Spring 3 tendremos una forma sencilla de controlar las excepciones en un conjunto de métodos.

Una de las grandes virtudes de Spring es la programación orientada a aspectos, y con ella se pueden hacer cosas muy interesantes y realizar este mismo ejemplo de múltiples formas. Aquí pondremos un sencillo ejemplo de captura de excepciones.

Para empezar crearemos la anotación con la cual queremos realizar el control de excepciones. Aquí indicamos a que tipo de elementos queremos que afecte al anotación (a través de @Target) y en que fase queremos que sea tenida en cuenta (a través de Retention). Target es más claro de entender pero Retention nos permite indicar si va a ser tenida en cuenta la anotación solo en el código fuente (SOURCE), en la compilación (CLASS) o durante su ejecución (RUNTIME).

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExcepcionControl {
}

Luego creamos la clase que contendrá el aspecto y que indicará en que casos y que acciones realizar en caso de que se de la acción a controlar. Los aspectos nos permiten controlar acciones que se realizan de forma general en toda la aplicación y no en una única clase. Una vez creada una clase que funcione como aspecto a través de la anotación @Aspect, debemos indicar que un 'Pointcut' que será aquella zona donde queremos que se vean afectadas las acciones a tomar, y un 'Advice' que son las acciones a tomar.

@Aspect
@Component
public class ExceptionAspect {

 private static Logger LOGGER = Logger.getLogger(ExceptionAspect.class);
 
 @Pointcut("@annotation(es.home.almacen.bbdd.annotation.ExceptionControl)")
 protected void exceptionControl() {}
 
 @Around("exceptionControl()")
 public Object catchException(ProceedingJoinPoint joinpoint) throws Throwable {
  Object exit = null;
  try {
   exit = joinpoint.proceed();
  } catch (Exception except) {
   LOGGER.error("Excepcion capturada en el advice: "+except.getMessage(), except);
   throw  new AlmJpaRepoException(except);
  }
  return exit;
 }
}

Como hemos comentado anteriormente, se puede realizar esto mismo de multiples formas y esto no es más que un ejemplo. Para ver una información más detallada lo mejor es ver la documentación oficial de Spring. Aquí vemos como indicamos que el punto de control será la anotación ExceptionControl y como en el catchException capturamos cualquier excepción y la traducimos o realizamos por ellas las acciones pertinentes.

Por último solo nos queda los ficheros de configuración, en el application context de spring indicamos que vamos a utilizar aspectos y que sean tenido en cuenta:



 
 
....


Y en el pom.xml indicamos las librerías a utilizar, en nuestro caso hemos utilizado Spring 3.

 3.1.2.RELEASE
 1.7.0 

 
   
   
 org.springframework.data
 spring-data-jpa
 ${jpa.data.version}
    
    
    
        org.springframework
        spring-aop
        ${spring.version}
    
    
        org.aspectj
        aspectjrt
        ${aspectj.version}
    
    
        org.aspectj
        aspectjweaver
        ${aspectj.version}
    


Un ejemplo de uso sería el siguiente, donde no necesitariamos capturar las excepciones sino que el aspecto se encargaría de ello:

@ExceptionControl
public Page findSearchDiscs(final String nombre, final String grupo,final Pageable pageable) {
 return dao.findSearchDiscs(nombre, grupo, pageable);
}

miércoles, 11 de diciembre de 2013

Tratamiento de fechas con Spring MVC y JQuery

En un post anterior hablaba sobre Spring MVC y los formularios, y una persona me pregunto sobre el tratamiento de las fechas. Debido a ello voy a explicar como podemos utilizar las fechas en un formulario de Spring MVC y que mantengan su formato, con la ayuda de JQuery.

Para empezar mostramos el DTO con la información. Al haberse realizado con JPA este mismo DTO nos permitirá almacenar la información de los datos a guardar en la BBDD.
@Entity
@Table(name = "libro", catalog = "almacen")
public class Libro implements java.io.Serializable {

 private static final long serialVersionUID = 1L;
 private Integer ident;
 private String nombre;
 private String autor;
 private String serie;
 private String argumento;
 private Integer paginas;
 private Integer volumen;
 @DateTimeFormat(pattern = "dd/MM/yyyy")
 private Date publicacion;

 public Libro() {
 }
 
 @Column(name = "PUBLICACION")
 public Date getPublicacion() {
  return publicacion;
 }

 public void setPublicacion(Date publicacion) {
  this.publicacion = publicacion;
 }

....
}

Aquí podemos ver como además de las anotaciones propias de JPA para realizar la persistencia, hemos añadido la anotación @DateTimeFormat que es propia de Spring y nos permite mostrar la fecha en base a un patrón válido de formato de fecha.

Por otro lado contamos con la página JSP donde añadimos el campo con el tag form:input normal, independientemente de que vayamos a mostrar una fecha.


Con esto ya tendriamos el campo y nos debería valer, siempre y cuando introduzcamos una fecha con el formato indicado anteriormente. Pero yo he querido facilitar un poco más las cosas y añadir una utilidad para introducir fechas. Y como Spring no la trae en sus tags, he echado mano de Jquery. Para ello solo tenemos que asociar un pequeño script que incluya el siguiente código. Así al clickear sobre el campo se abrirá un calendario que nos permitirá indicar la fecha de manera sencilla.

$(function() {
    $('#publicacion').datepicker();
});

Con esto, ya podremos recoger la fecha en el controlador de Spring de forma correcta. Aunque es posible que os haya surgido una excepción del tipo JodaTime library not available - @DateTimeFormat not supported. Y aunque no se muy bien a que es debido tiene una fácil solución también, y es incluyendo la siguiente dependencia en nuestro pom.xml


 joda-time
 joda-time
 1.6.2
 runtime

viernes, 28 de diciembre de 2012

Porque @Transactional no hace rollback?

Uno de los grandes inventos para usar Spring y conexiones a las base de datos es poder definir el datasource y controlar las transacciones a través de anotaciones y dejar de preocuparte de obtener la conexión, de abrir y cerrar recursos, etc.
@Service
@Transactional
public class GenericServiceImpl implements GenericService {
   public void method1(){
      try{
         ...
      }catch(Exception except){
         throws new ServiceException(except);
      }
   }
}
Algo tan sencillo como lo que tenemos arriba debería servir para hacer commit cuando termine todo correctamente y rollback cuando no. En principio uno espera que si se da una excepción en el código, pues Spring se encargue de hacer el rollback.
Pero no amigos, Spring solo hará rollback cuando sea una excepción no declarada de tipo RunTimeException. Por lo que con el código anterior, podemos hacer log de la excepción y luego lanzar nuestro tipo y aún así, si hay varios métodos puede hacer commit de alguno de ellos.
Para evitar este posible erro debemos hacer lo siguiente.
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
Con propagation le hacemos indicar que todas las operaciones incluidas dentro de un mismo método deben ser tratadas con la misma transaccion. Pero lo que realmente ayuda es el rollbackFor, con esta propiedad le indicamos que debe hacer rollback si ocurre alguna excepción.

jueves, 22 de noviembre de 2012

AOP con Spring 2 y Anotaciones

En este post voy a mostrar como hacer uso de la Programación Orientada a Aspectos (AOP en ingles) que es un de las dos grandes características de Spring junto a la inyección de dependencia Gracias a la AOP se pueden encapsular los diferentes conceptos que componen una aplicación en entidades bien definidas, eliminando las dependencias entre cada uno de los módulos (Wikipedia).

Para el uso de AOP vamos a usar la librería Spring 2 y el uso de las anotaciones que es la forma más sencilla y práctica de configurarlo. En este ejemplo haremos una simple clase que permitirá el registro del tiempo que tardan en ejecutarse los métodos de los servicios de la aplicación.

Las librerías a añadir al proyecto deben de ser como mínimo las 3 siguientes, añadiendo el core de spring y las necesarias para el uso de AOP y las anotaciones.

 org.springframework
 spring
 2.5.6


 org.springframework
 spring-aop
 2.5.6


 org.springframework
 spring-aspects
 2.5.6

En el fichero de configuración de Spring debemos incluir las siguientes líneas:

- Configurar el fichero para realizar el correcto uso de etiquetas.

- configuracion para los aop. que permite coger las clases configuradas mediante aspect

- configuracion para las anotaciones

  
La clase de ejemplo que nos permitiría registrar el tiempo que tardan en realizar los metodos de los services es:
@Component
@Aspect
public class LogTimeAspect {
 private static final Logger LOGGER = Logger.getLogger(LogTimeAspect.class);
 @Pointcut("execution(* es.home.service.impl.*.*(..))")
 public void logCheck() {
  // Metodo vacio a proposito. Permite hacer el poincut que requerimos
 }
 @Around("logCheck()")
 public Object profile(final ProceedingJoinPoint pjp) throws Throwable {
  final Signature signature = pjp.getSignature();
  LOGGER.info("Init - " + signature.getDeclaringTypeName() + " - " + signature.getName());
  final long start = System.currentTimeMillis();
  final Object output = pjp.proceed();
  final long elapsedTime = System.currentTimeMillis() - start;
  LOGGER.info("Init - " + signature.getDeclaringTypeName() + " - " + signature.getName());
  LOGGER.info("Method execution time: " + elapsedTime + " milliseconds.");
  return output;
 }
}
- Con la anotación @Component indico que es un componente de Spring y que sea registrado y tenido en cuenta por la aplicación, y con la la anotación @Aspect que la clase es utilizada como un aspecto.

- Con la anotación @Pointcut declaramos un 'Punto de Corte', es decir que indicamos a la aplicación cuando queremos que se ejecute un determinado codigo (En este caso el incluido dentro del método). Con la declaración que le sigue indicamos cuando queremos ejecutarlo. En nuestro caso le indicamos que en todos los métodos de todas las clases de un determinado paquete de la aplicación (en es.home.service.impl están las clases y métodos a registrar).

- Con la anotación @Around, indicamos que se ejecute el código del método asociado antes y despues del ejecutado por un determinado 'Punto de Corte' en este caso logCheck. Por lo que podremos medir el tiempo antes de comenzar el método y despues de ejecutarse el método, y con su resta saber el tiempo de ejecución total.

En la documentación de Spring podéis encontrar que esto no es mas que la punta del iceberg y se pueden configurar los Poincuts de varias formas y también la existencia de otras anotaciones que permiten la ejecución de código al asociarse al Poincut de otras formas. Aquí la documentación oficial

viernes, 9 de noviembre de 2012

Anotaciones Interceptor en Struts2

Buenas, el uso de anotaciones es ampliamente conocido y no es un gran secreto . Pero no todas simplemente se pueden utilizar añadiéndolas al código. Algunas requieren pasos extras como pueden ser estas.

En struts 2 hay tres anotaciones que te pueden interceptar la ejecución de un método y que te permitan realizar ciertas acciones antes y después de la ejecución de dicho método.

@Before : Es llamada antes de ejecutarse el método. Si el valor devuelto no es nulo, el action devolverá su valor indicado. @After : Es llamada después de ejecutar el método.

@BeforeResult : Es llamado después de ejecutar el método pero antes de ejecutar la salida del action. Un simple ejemplo sería este, donde nos permite inicializar objetos antes de llamar al método:
@Before public void init(){ object = new Object(); }
Pero aún falta el paso más importante y sin el no funcionaría esta anotación, y es añadir a la configuración de struts un interceptor que hay por defecto que permite activar dichas anotaciones. Sería de la siguiente forma: