Weld development mode en Liferay

CDI: Contexts and Dependency Injection for the Java EE Platform 

Publicado por Miguel Ángel Júlvez el 25 de febrero de 2017

Weld es la implementación de referencia de CDI, el cual es un estándar JCP para la inyección de dependencias y gestión del ciclo de vida de los beans por parte del contenedor.

Weld nos permite, entre otras cosas, mantener el código desacoplado facilitando su mantenimiento centrándonos en la lógica que necesitamos. Un ejemplo típico de Weld sería:

@Stateless
public class MiClase {
  @Inject
  private MiClaseInyectada miClaseInyectada;
}

Weld ya viene integrado en servidores de aplicaciones Java EE como wildfly o Payara y puede ser usado en contenedores de Servlets como Tomcat o incluso en aplicaciones Java SE.

Para empezar a usarlo simplemente tenemos que añadir la siguiente dependencia a nuestro proyecto

<dependency>
  <groupId>javax.enterprise</groupId>
  <artifactId>cdi-api</artifactId>
  <version>1.2</version>
  <scope>provided</scope>
</dependency>

Si estamos usando tomcat o similar, tendremos que añadir también esta otra dependencia 

<dependency>
  <groupId>org.jboss.weld.servlet</groupId>
  <artifactId>weld-servlet</artifactId>
  <version>2.4.2.SP1</version>
</dependency>

A continuación añadimos lo siguiente en el fichero web.xml de la aplicación

<filter>
   <filter-name>WeldCrossContextFilter</filter-name>
   <filter-class>org.jboss.weld.servlet.WeldCrossContextFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>WeldCrossContextFilter</filter-name>
   <url-pattern>/*</url-pattern>
   <dispatcher>INCLUDE</dispatcher>
   <dispatcher>FORWARD</dispatcher>
   <dispatcher>ERROR</dispatcher>
</filter-mapping>
<listener>
   <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>

Y finalmente añadimos el fichero web.xml dentro del directorio WEB-INF

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" bean-discovery-mode="all" version="1.2"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_2.xsd">
   <!-- This file is necessary in order to inform CDI that scanning should occur for CDI annotations. -->
</beans>

A partir de este momento, ya tenemos Weld integrado y listo para ser usado.

Cuando tenemos una aplicación con muchos Beans administrados por Weld, se hace un poco complicado tener en cuenta todos los Beans que se están usando y sus contextos de aplicación. Por ello, Weld trae consigo una interfaz que ayuda a los desarrolladores a ver qué está pasando con los Beans gestionados por el contenedor.

Para habilitar esta interfaz, simplemente tenemos que añadir lo siguiente a nuestro fichero web.xml (no apto para entornos en producción)

<context-param>
   <param-name>org.jboss.weld.development</param-name>
   <param-value>true</param-value>
</context-param>

Una vez hecho esto, tendremos una nueva interfaz para ayudarnos en nuestro proceso de desarrollo. Esta interfaz se encuentra en http://<host>:<port>/<context>/weld-probe

El problema que tenemos ahora, es que nuestro portlet ha dejado de funcionar en liferay debido a una situación no contemplada en Weld y el apartado de monitorización no funcionará.

Para solucionar esto, he creado un proyecto en github con un "apaño" (https://github.com/majulvez/core/commit/3fa246f5c69fbfcd7272686a9704959fb9691d31) que lo soluciona. Lo puedes descargar de aquí: https://github.com/majulvez/core/tree/miguel

Añádelo a tu repositorio local mediante

<dependency>
  <groupId>org.jboss.weld.servlet</groupId>
  <artifactId>weld-servlet</artifactId>
  <version>2.4.2.SP1-miguel</version>
</dependency>

A partir de este momento, puedes usar todas las funcionalidades del modo development de Weld en los portlets jsf de Liferay