Tag Archives: Java

Spring AOP y AspectJ en tres patadas

Inauguramos el nuevo nombre y aspecto del blog, que pasa de “Posteando mientras…” a “El Recetario”, con una nueva receta de Spring. En este caso vamos a cocinar algo con Spring AOP.

Qué cocinamos

Spring AOP es la parte de Spring relacionada con la porgramación orientada a aspectos. La programación orientada a aspectos es un paradigma informático que se fundamenta en programar en función de un aspecto, funcionalidad o característica concreta, en lugar de hacerlo centrado en un servicio o método específico. Es decir, que se puede codificar una funcionalidad o actividad no en función de un método o servicio específico, si no para un conjunto de ellos que representan una característica o aspecto representativo de la aplicación.

Por ejemplo, se puede programar la escritura de logs, la intercepción de excepciones, la generación de comentarios o auditorías en función de la ejecución o resultados de varios métodos que implementan una única funcionalidad o característica de la aplicación final. Así, podemos crear una entrada en un log cada vez que se invoque un método de la capa de servicios, o cada vez que se llame a un método de un paquete concreto.

Las acciones a realizar o implementación del aspecto es el “Advice”. Un aspecto puede tener varios “advices”, y cada “advice” estara asociado a un punto de interés o “pointcut”. El punto de interés que se usa para indicar cuando ha de ejecutarse el “advice”, es decir, los métodos que se quiere controlar.

AspectJ facilita la creación de los aspectos usando anotaciones.

Ingredientes

  • Spring Boot
  • Spring MVC
  • Spring AOP
  • AspectJ
  • Log4j
  • Maven

Paso a paso

1. Pom.xml

Configuramos el pom.xml de Spring Boot para que resuelva las dependencias necesarias para crear una aplicación con Spring AOP. La aplicación va a ser una simple API REST que recibirá una petición para contar cuantas veces aparece una determinada letra en una palabra, de ahi que necesitemos Spring MVC para la parte web. Se va a capturar la invocación y resultados de la ejecución de esta API usando aspectos y se escribirá en un log cuando esto ocurrá usando Log4j.

2. Inicializar Spring Boot

Se puede obtener más información acerca de Spring Boot en este otro post. Basta con incluir el siguiente código para inicializar la aplicación como Spring Boot. Esto hará que se ejecute en el Tomcat embebido que se carga automaticamente al incluir las dependencias de Spring MVC.

3. Crear el servicio que servirá de pointcut para los advices del aspecto

Como ejemplo práctico disponemos de un servicio que recibe una palabra y una letra. Éste cuenta cuantas veces aparece la letra en dicha palabra y devuelve la cuenta.

4. Controlador REST

Como se ha mencionado antes, se va ha implementar un servicio web tipo REST que se invocará desde un navegador web. Este servicio recibe en su URL una palabra y una letra, que seran los datos que se le pasarán al servicio antes creado.

5. Aspecto

Por último lo interesante de esta receta. La creación del aspecto usando las anotaciones de AspectJ. El aspecto puede tener varios “advices”, a saber:

  • @Before – Para antes de la ejecución del pointcut
  • @After – Para después de la ejecución del pointcut
  • @AfterReturning – Para después de la ejecución y recibiendo lo que se retorna
  • @AfterThrowing – Para después de que se lanza una excepción
  • @Around – Para antes y después del pointcut

Declaramos la clase como Aspect y como Component para que Spring la instancie automaticamente y la configure como aspecto:

Implementamos a modo de ejemplo los sigueintes advices:

- logBefore, para que escriba un mensaje en el log antes de ejecutar el servicio anterior:

Usamos la anotación @Before y el pointcut será la ejecución de cualquier método que tenga el texto Service en su nombre dentro del paquete net.luisalbertogh.springaop, independientemente de lo que reciban como argumento.

- logAfterReturning, para que escriba en el log después de la ejecución del servicio, e imprima el resultado obtenido:

Al igual que en el caso anterior, se usa la anotación y se define el pointcut correspondiente, pero en este caso además se añade el resultado (result).

- logAfterThrowing, para que escriba después de lanzar una excepción e indique el mensaje de error en el log:

- logAround, para que escriba en el log antes y después de la ejecución del servicio. En este caso, lo que ocurre es que se pasa la ejecución del pointcut al advice. Entonces para que continue la ejecución del servicio se usa joinPoint.proceed().

El resultado

En el navegador se vería esto:

Spring AOP

Spring AOP

Y en el log o en la consola:

INFO : net.luisalbertogh.springaop.controllers.ExampleController – Entering in CALCULATE
INFO : net.luisalbertogh.springaop.aspect.LogAspect – logBefore
INFO : net.luisalbertogh.springaop.aspect.LogAspect – Log before in: countCharsService
INFO : net.luisalbertogh.springaop.aspect.LogAspect – logAfterReturning
INFO : net.luisalbertogh.springaop.aspect.LogAspect – Log after in: countCharsService
INFO : net.luisalbertogh.springaop.aspect.LogAspect – - And value returned is: 4
INFO : net.luisalbertogh.springaop.controllers.ExampleController – Finishing CALCULATE

El proyecto completo aqui. Y también en Github.

Nueva API para fechas y tiempo en Java 8

Este post es un resumen rápido de lo que nos podemos encontrar en la nueva API de manipulación de fechas y tiempo de Java 8.

Esta API es mucho más avanzada y potente que sus antecesores y tiene como objetivo facilitar la manipulación de fechas y horas y resolver los múltiples problemas y malentendidos que causaba la tradicional API de Java (Calendar, Date, etc.) especialmente con las horas en diferentes zonas horarias, etc.

Dentro de la nueva API, que se encuentra principalmente en el paquete java.time, podemos encontrar las siguientes clases:

1. Clock

Representa el tiempo del sistema. Tiene información sobre la zona horaria en la que nos encontramos. Puede ser usado para acceder al tiempo en milisegundos (desde el 1 de enero de 1970) o para obtener diferentes instantes de tiempo para crear diferentes representaciones del mismo en diferentes zonas horarios o cronologías.

 

2. Instant

Representa un instante en la línea temporal del reloj (Clock). Esta siempre en UTC. Puede ser usado como una representación universal de tiempo o para obtener otras representaciones del mismo (pero requeriría de zona horaria). También puede usarase para obtener instancias de Date por motivos de compatibilidad con códigos antiguos (con la zona horaria local).

 

3. ZonedDateTime

Es una representacion de la fecha y el tiempo con información de la zona horaria completa.

 

4. OffsetDate, OffsetTime, OffsetDateTime

Representaciones de fecha, hora y fecha y hora respectivamente con información del desplezamiento de horas dentro de la zona horaria correspondiente (pero sin información sobre el nombre de la zona, por ejemplo).

 

5. LocalDate, LocalTime, LocalDateTime

Representación de fecha, hora y fecha y hora respectivamente sin información sobre la zona horaria. Es la forma preferida de representación y la recomendada si no se requieren datos sobre las zonas horarias.

 

6. ZoneId

Representación de las zonas horarias.

 

7. DateTimeFormatter

Formateador de fechas y horas para parsear, transformar u obtener las mismas en diferentes formatos.

 

8. Period

Representa un intervalo de tiempo concreto (mínimo un día). Se pueden usar en las operaciones con fechas (plusXXX(), minusXXX()).

 

9. Duration

Igual que los Period pero en este caso también admiten horas, minutos, segundos, etc.

 

Se puede encontrar más información sobre la API de tiempo de Java 8 en los siguientes enlaces:

http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html
https://docs.oracle.com/javase/tutorial/datetime/iso/overview.html
https://docs.oracle.com/javase/tutorial/datetime/index.html

Concurrencia en Java – Ejecución síncrona y tiempo de espera máximo

Comenzamos una serie de posts relacionados con la concurrencia en Java y la ejecución de hilos de forma concurrente asi como diferentes mecanismos y frameworks de paralelismo y programación de ejecuciones en el tiempo (pools de hilos, Quartz, etc.).

En este primer post mostramos un mecanismo Java estandar muy sencillo para ejecutar una lógica cualquiera dentro de un hilo de ejecución separado y esperar a que acabe, pero tan solo un tiempo máximo, para evitar posibles bloqueos del hilo de ejecución principal.

El planteamiento es el siguiente:

1. Tenemos una lógica de negocio implementada en alguna unidad de ejecución, una clase, un hilo, etc.

2. Podemos ejecutar esa lógica invocando algún método de esa clase o hilo (i.e. el método run()).

3. En lugar de ejecutar ese método de forma explicita desde el hilo principal de ejecución de nuestro programa, disponemos de un hilo aparte al que pasaremos esa lógica de negocio y desde el que la ejecutaremos:

4. Lanzamos el hilo de forma asíncrona (start()) pero en lugar de desentendernos de él, le esperamos un tiempo máximo usando el metodo join() de la API de concurrencia de Java. Ademas, metemos todo dentro de un bloque try-catch de tal manera que, bien ante una excepción o bien cuando finalice la ejecución o se supere el tiempo de espera máximo, se compruebe si el hilo sigue activo (isAlive). Si es así, se solicitará su interrupción para no dejar hilos activos de forma innecesaria (interrupt()).