CDI: Conceptos avanzados

0
7533

En este tutorial vamos a ver aspectos más avanzados que nos permiten trabajar con conceptos como Alternativas, Especialización, Productores, Eventos e Interceptores en CDI.

0. Índice de contenidos.

1. Introducción

Como ya vimos en el anterior tutorial relacionado (Inyección de dependencias a través de CDI en Tomcat), CDI es una opción factible, y que gana peso con el paso del tiempo, para la definición de contextos y manejo de inyección de dependencias.

En este tutorial vamos a ver aspectos más avanzados que nos permiten trabajar con conceptos como Alternativas, Especialización, Productores, Eventos e Interceptores.

Para ayudarnos a retratar estos aspectos, vamos a realizar pequeñas aplicaciones web JSF en las que iremos utilizando las herramientas anteriormente detalladas.

2. Entorno

El tutorial está escrito usando el siguiente entorno:

  • Hardware: MacBook Pro 17′ (2.66 GHz Intel Core i7, 8GB DDR3 SDRAM).
  • Sistema Operativo: Mac OS X Lion 10.10.3.
  • NVIDIA GeForce GT 330M 512Mb.
  • Crucial MX100 SSD 512 Gb.
  • Software:

    • Eclipse Mars
    • Java JDK 1.8
    • Maven 3
    • Apache Tomcat 8
    • JBoss Weld 2.2.13

3. Alternativas

Mientras estamos desarrollando nuestra aplicación, puede darse el caso de que se tenga multiples implementaciones para un mismo bean, sobre todo si estamos acostumbrados a trabajar mediante diseño por contrato.

Para dar solución a estas situaciones CDI nos ofrece las Alternativas. Una herramienta aplicable en el momento de despliegue, que nos permite seleccionar entre las distintas implementaciones de una misma interfaz

Esta solución suele utilizarse en las siguientes situaciones:

  • Manejar lógica de negocio específica de cada cliente en tiempo de ejecución.
  • Seleccionar beans validos para escenarios concretos.
  • Creación de dobles de test.

Para escenificar el uso de Alternativas vamos a utilizar como base el proyecto CDI del anterior tutorial Inyección de dependencias a través de CDI en Tomcat.

Aplicando las Alternativas.

Comenzaremos añadiendo una nueva implementación de la interfaz “Greeting”, la cual utilizamos para implementar los servicios de la aplicación.

Mediante la anotación @Alternative marcamos la implementación como alternativa dentro de implementaciones existentes, pero no es el único paso para hacer uso de alternativas, siendo necesario declarar esta clase en la sección del fichero beans.xml, como se puede ver a continuación.

El resultado de nuestras modificaciones es que la alternativa de implementación prevalece sobre la opción “default”.

Utilizando multiples Alternativas.

Podemos querer hacer uso de las múltiples alternativas que tengamos definidas, para estos casos disponemos de varias posibilidades, en forma de anotaciones:

  • @Named
  • @Qualifier

En este caso vamos a ampliar el supuesto anterior con otra implementación de la interfaz Greeting para tener un poco más de variedad en el ejemplo, para ello añadimos Alternative2GreetingServiceImpl, tanto al proyecto, como dentro del fichero beans.xml.

@Named

Llegados a este punto, se hace necesario identificar los distintos servicios que tenemos, en un primer momento realizaremos esta identificación a través de la anotación @Named. A continuación lo detallamos para cada implementación:

En la clase MessageServerBean habrá que establecer dichos servicios…

Finalmente modificaremos el fichero xhtml para solicitar los distintos mensajes…

El resultado debe ser similar al que se muestra en la imagen a continuación:

@Qualifier

Si queremos optar por identificar nuestros servicios a través de @Qualifier tendremos que crearlos, como se ve a continuación:

Sirva esta declaración a modo de ejemplo para realizar la definición del resto de @Qualifier (AlternativeGretingService y Alternative2GreetingService)

Después de definirlos, habrá que marcar cada servicio con su correspondiente @Qualifier sustituyendo la anotación @Named por @, por ejemplo, se debe sustituir @Named(“GreetingServiceImpl”) por @GreetingService.

Este cambio debe realizarse de igual manera en la clase MessageServerBean, quedando de la siguiente manera:

El resultado final debe ser similar al que mostramos en el punto anterior.

4. Especialización

La epecialización es una solución similar a las alternativas en lo que se refiere a sustituir un bean por otro. Sin embargo, lo realmente interesante de las especializaciones es que permite ampliar la funcionalidad de un bean específico sobreescribiendo sus métodos.

La especialización se realiza tanto en tiempo de ejecución como de compilación. Cuando se declara que un bean especializa otro, extenderá la clase, y en tiempo de ejcución el bean especializado sustituye por completo al bean inicial. Si el bean inicial se genera mediante un método “Productor”, habrá que sobreescribir el método “Productor” parta que genere el bean especializado.

Declarar un bean especializado es sencillo, en nuestro caso vamos a especializar el bean Alternative2GreetingService, extendiendo la implementación y sobreescribiendo el método getSalute():

Por otro lado, hace falta dejar constancia en el fichero beans.xml.

Con estos cambios el resultado que debe obtenerse es el siguiente:

5. Productores

Un método productor es aquel que genera un objeto que puede ser inyectado, tiene que estar anotado con javax.enterprise.inject.Produces.

En este caso vamos a volver al ejemplo base (Inyección de dependencias a través de CDI en Tomcat) para explicar como hacer uso de @Produces.

Primero ampliaremos los servicios de generación de saludo (AlternativeGreetingServiceImpl y Alternative2GretingServiceImpl) mediante las clases ya expuestas en este tutorial.

Con posterioridad, eliminaremos de estas (GreetingServiceImpl, AlternativeGreetingServiceImpl y Alternative2GreetingServiceImpl) las antoaciones que tienen.

A continuación generaremos la clase que contiene al método productor:

Como se ve en el código anterior, el método productor de Beans se marca con @Produces.Hemos mantenido el Qualifier @Greeting para hacer más cómodo el desarrollo.

Adicionalmente, hemos creado un enumerado que mantiene los tipos de servicios que mantenemos..

Finalmente, nos aseguramos de que el fichero beans.xml está vacío y de que el contenido del fichero index.xhtml es el correcto:

Por último, el resultado:

6. Eventos

Los eventos son el mecanismo que ofrece CDI para que los beans se comuniquen “bajo demanda”. Un bean puede definir un evento, otro puede “disparar” ese evento y un tercero puede ser notificado.

Un evento consiste en:

  • Un objeto Java que define el evento
  • Los qualifiers de eventos

Para este ejemplo vamos a hacer un proyecto nuevo por completo. Como ya hemos visto con anterioridad como configurar de base un proyecto CDI con tomcat, saltaremos a la parte de la definición de objetos.

Primero definimos el evento

A continuación creamos un listener que esté observando por si el evento se dispara:

El Listener esta anotado con @Stateless que marca el bean como stateless, y por otro lado, vemos que el parámetro del método listenToHello esta anotado con @Observes, lo que quiere decir que se trata de un parametro del evento, y que hace que el método listenToHello sea declarado como método observer.

En tercer lugar tenémos la clase HelloMessenger, encargada de disparar el evento, junto con su parámetro:

Finalmente definimos una página web (index.xhtml) donde estableceremos le código que hará la llamada al método hello(), encargado de disparar el evento.

Al arrancar la aplicación se verá una página web con un botón (Fire).

Si el botón es pulsado lanzará el evento, que será recogido por el Listener y se encargará de pintar el mensaje indicado por consola.

7. Conclusiones

Como hemos visto a lo largo del tutorial, CDI nos provee de las herramientas necesarias para enfrentarnos a casi cualquier proyeto en el que se necesite un contexto y que requiera de inyección de dependencias.

Con respecto al futuro de CDI, pasa por su especificación 2.0, con la llegada de JEE 8, que se centrará en dos aspectos principalmente:

  • Soporte CDI para aplicaciones Java SE puras.
  • Modularidad. Definiendo un modelo CDI con mayor granularidad favoreciendo la integración de otras especificaciones Java EE

8. Referencias

Dejar respuesta

Please enter your comment!
Please enter your name here