Oferta de temporada, cualquier libro a US$5

martes, 12 de octubre de 2010

EJB 3.1 en Porlets de Liferay

Ya que GlassFish v3 es compatible con Java EE6, y permite módulos web con componentes EJB (por la característica propia de EJB 3.1).. y además Liferay puede ser instalado sobre GlassFish v3... y... los portlets son módulos web con otro archivo de despligue ¿los portlets para Liferay/GFv3 deberían permitir EJB 3.1?

Pues la respuesta es sencilla: Sí. Pero cuando uno desarrolla un portlet con EJB 3.1 y lo trata de desplegar sobre Lfieray 6.0, no funciona. Por alguna razón no despliega correctamente la aplicación, lanza errores de clases de SpringFramework faltantes, etc. Lo curioso es que si se despliega sobre Liferay 5, sí funciona correctamente. Entonces ¿qué pasa?. Pues bien, leyendo un poco los mensajes de error y después de varias pruebas.. pude dar con la solución.

Para comenzar, el error que lanza es el siguiente:
Error in annotation processing: java.lang.NoClassDefFoundError: org/springframework/transaction/PlatformTransactionManager

Pero si examinamos la carpeta lib del módulo de liferay, sí están las bibliotecas de Spring.

La solución a este problema es el siguiente: debemos copiar ciertas bibliotecas de Spring a la carpeta lib del dominio donde está instalado el Liferay. Para evitar conflictos de versión del Spring, copiemos los siguientes archivos .jar del .war de Liferay a $GLASSFISH_HOME/domains/domain1/lib.
  • aopalliance.jar
  • aspectj-rt.jar
  • aspectj-weaver.jar
  • commons-logging.jar
  • spring-aop.jar
  • spring-asm.jar
  • spring-beans.jar
  • spring-context.jar
  • spring-core.jar
  • spring-expression.jar
  • spring-transaction.jar
Ahora sí, podemos desplegar portlets que contienen EJB con total normalidad.

Pero! (no tan rápido), como las clases portlets (descendientes de javax.portlet.GenericPortlet) no son parte del estándar de un módulo web, entonces no podrá utilizarse un EJB con la notación @EJB (lo que sí funciona en un Servlet). Entonces ¿cómo instanciar EJB?:

Pues habrá que utilizar el JNDI dentro del módulo, de la siguiente manera:


Context c = new InitialContext();
EjbFacade facade= c.lookup("java:global/NombrePorlet/NombreEjbFacade!paquete.ejb.NombreEjbFacade");

Algo más explicado sobre cómo acceder a las clases EJB 3.1 se encuentra en este post: Cliente remoto de EJB 3.1

Espero que les sea de utilidad.