Inyección de dependencias a través de CDI en Tomcat

3
12107

En pocos años CDI se ha convertido en un aspecto clave de la plataforma Java EE y su importancia sigue creciendo mientras que otras especificaciones delegan parte de sus responsabilidades en ella (como es el caso de JTA con @Transactional ó JBV y las validaciones a nivel de métodos).

0. Índice de contenidos.

1. Introducción

Como ya vimos con anterioridad, en este tutorial de José Manuel Sánchez sobre CDI: Inyección de dependencias en JEE y ejecución de test de integración con el soporte de Arquilian, CDI es el mecanismo para resolver dependencias entre servicios dentro del estándar JEE.

La especificación de CDI (Context And Dependency Injection) aparece por primera vez en Java EE 6 (CDI 1.0) y es revisada (mínimamente, CDI 1.1) en Java EE 7.

Esta especificación nos ofrece, a grandes rasgos, la posibilidad de introducir componentes en el ciclo de vida de una aplicación Java que mantenga ámbitos bien acotados y la capacidad de inyectar dependencias en el código.

En pocos años CDI se ha convertido en un aspecto clave de la plataforma Java EE y su importancia sigue creciendo mientras que otras especificaciones delegan parte de sus responsabilidades en ella (como es el caso de JTA con @Transactional ó JBV y las validaciones a nivel de métodos).

Tal es su calado dentro de la plataforma Java EE que actualmente se esta realizando una revisión importante (CDI 2.0) con el objetivo de incorporarla en Java EE 8 (JSR-365 e incluso un early-draft).

Con el objetivo ver como funciona la inyección de dependencias a través de CDI en un contenedor de Servlet como Tomcat con dependencias JEE, proponemos crear una aplicación web JSF en la que, de una manera sencilla, veremos como integrar CDI en un servidor web Apache Tomcat versión 7.

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. Dependencias

En este caso vamos a hacer uso del servidor web Apache Tomcat 8 y la implementación referencia para CDI: «Weld», un proyecto Jboss de Red Hat y distribuida bajo licencia ASL 2.0.

A continuación las dependencias de maven:


  	
		javax.enterprise
		cdi-api
		1.2
	
  	
		org.jboss.weld.servlet
		weld-servlet
		2.2.13.Final
	
	
		org.glassfish.web
		el-impl
		2.2
	
	
		javax.faces
		jsf-api
		2.1
	
	
		org.glassfish
		javax.faces
		2.2.11
	
	
		javax.ejb
		javax.ejb-api
		3.2
	
  

4. Configuración

Son tres los ficheros de configuración establecidos para el correcto despliegue de la aplicación, a continuación se detalla su contenido.

context.xml

Situado en la ruta /main/resources/META-INF/, es el lugar en el que definiremos como resource el BeanManager, que ofrece las operaciones necesarias para tratar con el contexto.



	

web.xml

El descriptor de despliegue en el que se define como desplegar la aplicación web. Debe establecere en la carpeta WEB-INF.


	Archetype Created Web Application
	
		index.xhtml
	
	
	   BeanManager
	   javax.enterprise.inject.spi.BeanManager
	 
	 
	   javax.faces.PROJECT_STAGE
	   Development
	 
	
		Faces Servlet
		javax.faces.webapp.FacesServlet
		1
	
	
		Faces Servlet
		*.xhtml
	

beans.xml

Se trata del fichero donde se definirán los beans para las inyecciones (en nuestro caso quedará vacío puesto que manejaremos las inyecciones a través de anotaciones). Debe establecere en la carpeta WEB-INF.

	

5. Uso

Para ver el funcionamiento de las inyecciones mediante CDI vamos a crear un proyecto muy básico en el que se definiran una clase «servicio» que nos devolverá un mensaje, un bean en la que se inyectará la clase servicio y una página JSF en la que se hará uso del bean.

En primer lugar tenemos una interfaz simple que declara el servicio que vamos a ofrecer:

public interface Greeting {
	
	String getSalute();
	
}

A continuación la clase servicio que implementa el interfaz:

import javax.enterprise.context.Dependent;
import javax.inject.Named;

@Named
@Dependent
public class GreetingService implements Greeting{
	
	@Override
	public String getSalute(){
		return "Hello World!";
	}
}

Como se puede ver, dos son las anotaciones que hemos utilizado en este caso, @Named, que sirve para asociar un nombre al bean (en este caso GreetingService), y @Dependent, que establece el ciclo de vida y el contexto copiándolos del Bean donde se inyecte.

Como se puede ver la única lógica que mantiene el servicio es la generación de un String con el típico «Hello World!!»

A continuación tenemos el bean al que se llamará desde la página web:

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@RequestScoped
public class MessageServerBean {

	@Inject
	Greeting greetingService;
	
	public String getMessage(){
		return greetingService.getSalute();
	}
}

En este caso se utiliza también la anotación para asociar el nombre con el bean y a demás aparecen dos nuevas anotaciones, @RequestScoped que establece el ciclo de vida del bean acotado a la petición y finalmente la anotación @Inject que identifica el punto en el que se inyectará el bean.

Los beans en CDI viven en ámbitos bien definidos, y se crean y se destruyen bajo demanda por el contenedor. En este sentido CDI ofrece una serie anotaciones predefinidas para establecer dichos ámbitos:

  • @RequestScoped: El bean tiene un ciclo de vida relativo a la petición.
  • @SessionScoped: El bean tiene un ciclo de vida relativo a la sesión.
  • @ApplicationScoped: El bean tiene un ciclo de vida relativo a la aplicación.
  • @ConversationScoped: El bean tiene un ciclo de vida relativo a una conversación.

Finalmente tenemos la aplicación web:




	
		Hello!
	
	
	    Hello from Facelets
	    
Message is: #{messageServerBean.message}
Message Server Bean is: #{messageServerBean}

Tras levantar el servidor Tomcat y desplegar la aplicación se puede visitar la web, donde se debe visualizar algo similar a lo que se ve en la imagen a continuación:

Resultado Tomcat

6. Decoradores

Un decorador es una clase Java que tiene la anotación javax.decorator.Decorator y que se corresponde con un elemento «decorators» en el fichero bean.xml

Este tipo de anotación nos permite completar o añadir más lógica a un bean ya existente dentro de nuestra aplicación.

A modo de ejemplo vamos a realizar una pequeña modificación sobre el código de nuestra aplicación y así ver como se puede utilizar

Vamos a comenzar creando nuestro decorador:

import javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.inject.Inject;

@Decorator
public abstract class GreetingDecorator implements Greeting {

	@Inject
	@Delegate
	@Any
	Greeting greeting;
	
	@Override
	public String getSalute() {
		return greeting.getSalute() + " How are you???";
	}

}

En este caso, la anotación @Decorator se encarga de espoecificar que la clase es un Decorador, mientras que la anotación @Delegate establece el punto en el que se debe inyectar el bean a decorar. @Any sirve para establecer el punto de inyección pero sin establecer el nombre del bean inyectado.

A continuación nos dirigimos al fichero beans.xml y dejamos constancia de este decorador:


      
      	cdi.webapp.GreetingDecorator
      

Tras levantar el servidor Tomcat y desplegar de nuevo la aplicación se puede visitar la web, donde se debe visualizar algo similar a lo que se ve en la imagen a continuación:

Resultado Tomcat 2

7. Conclusiones

CDI es la opción de presente y de futuro que ofrece la plataforma Java EE en cuanto a la definición de contextos y manejo de inyección de dependencias.

Como hemos visto, su configuración y uso en entornos Tomcat es rápida y sencilla.
A través de pocas líneas de código se puede disfrutar de todas las ventajas que ofrece, como el establecimiento de ámbitos o el manejo de las inyecciones de dependencias.

En futuros tutoriales trataremos aspectos más avanzados como pueden Alternativas, Eventos ó Interceptadores.

3 COMENTARIOS

  1. Me gusta este ejemplo porque es un excelente punto de partida básico y simple con el que adquirir los conceptos fundamentales y poder enfocarse después en ejemplos más complejos. Ojalá todos los tutoriales fueran así…
    Enhorabuena.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad