EJB 3.0 y pruebas unitarias con Maven, JUnit 4 y Embedded JBoss sobre Java 6
Introducción
Este tutorial es un complemento a otro tutorial (https://adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=ejb3JUnitWithJBoss) publicado anteriormente, y en el cual se documenta de forma más extensa los conceptos expuestos aquí.
El problema es que el anterior tutorial fallaría si lo intentaramos ejecutar bajo la versión 6 de la máquina virtual de Java (Java 6), en este tutorial se aporta el conocimiento necesario para solventar este problema.
Además, como diferencia en vez de usar la versión JBoss Embedded Beta 2, en este tutorial usaremos la JBoss Embedded Beta 3 (Kernel de JBoss 5).
Emdebbed JBoss (Beta 3)
Emdebbed JBoss es un versión limitada de el servidor de aplicaciones JBoss, pensada para ser embebida en aplicaciones de escritorio, tests, Tomcat, etc..
El peso que tiene esta versión es muy inferior al que tiene la versión no embedida del servidor de aplicaciones JBoss y entre otras cosas es ideal para
ejecutar nuestros tests de forma más eficiente.
Es decir, esta versión está pensada para ser capaz de ejecutar el Kernel de JBoss 5 y los servicios JEMS sin usar el classloader de la versión no embedida de JBoss.
- Puede ver un listado de sus características y limitaciones haciendo clic aquí.
- Puedes descargarlo haciendo clic aquí.
Ejemplo
A continuación vamos a ver un ejemplo completo en el cual crearemos un EJB sin estado que expone funcionalidad
que puede ser invocada de forma tanto local como remota.
Posteriormente creamos un test JUnit que despliega el EJB en el microcontenedor JBoss Emdebbed 3 e invoca el método que expone.
A continuación vamos a ver un completo ejemplo en el cual:
- Definiremos una interfaz que exponga la funcionalidad local del EJB.
- Definiremos una interfaz que exponga la funcionalidad remota del EJB.
- Crearemos un EJB sin estado que expone el servicio local y remoto definido anteriormente.
- Creamos un par de tests JUnit que despliege el EJB en el microcontenedor JBoss Emdebbed 3 e invoque el método local y remoto.
- Veremos que modificaciones tenemos que hacer en el archivo de configuración de Maven para ejecutar todo de manera automática.
El código fuente de este tutorial puede ser descargado desde aquí.
Importante:
Hay que copiar los archivos de configuración de JBoss Embedded (%JBOSS_EMDEBBED_DIR%/bootstrap) al directorio src/test/resources
de nuestro proyecto Maven, para que esta configuración esté disponible (via classpath) para el servidor.
Si observa la imagen, verá que son los archivos y directorios resaltados por el cuadrado rojo.
Interfaz EJB Local:
package com.autentia.embedded3java6; /** * Interfaz local de un saludador. * Sólo se puede usar desde la JVM donde está ejecutandose el servidor de aplicaciones que gestiona el EJB. */ @javax.ejb.Local public interface Greeter { public String sayHi(); }
Interfaz EJB Remota:
package com.autentia.embedded3java6; /** * Interfaz remota de un saludador. * Para poder invocar el EJB desde fuera de la JVM del servidor de aplicaciones. */ @javax.ejb.Remote public interface GreeterRemote extends Greeter { // Aunque no añade nada nuevo a la interfaz que extiende, es mejor separarlo por motivos de diseño // y así se evitarán problemas futuros en caso de ampliar funcionalidad. }
EJB de ejemplo:
EJB de ejemplo: No tiene estado y puede ser invocado local o remótamente:
package com.autentia.embedded3java6; /** * EJB sin estado. */ @javax.ejb.Stateless public class DummyGreeterBean implements Greeter, GreeterRemote { public static final String DEFAULT_GREETING = "Autentia: ¡ Hola Mundo !"; public String sayHi() { return DummyGreeterBean.DEFAULT_GREETING; } }
Test a realizar:
package com.autentia.embedded3java6; import javax.naming.InitialContext; import junit.framework.JUnit4TestAdapter; import org.jboss.deployers.spi.DeploymentException; import org.jboss.embedded.Bootstrap; import org.jboss.virtual.plugins.context.vfs.AssembledContextFactory; import org.jboss.virtual.plugins.context.vfs.AssembledDirectory; import org.junit.Assert; /** * Tests que deseamos realizar de nuestra lógica de negocio * @author Carlos García. Autentia. */ public class EJBsTest { /** * Simula un jar con todos los elementos que vamos a desplegar en el microcontenedor (Embedded JBoss). */ private static AssembledDirectory jar; /** * En caso de ejecutar los tests en un IDE. */ public static void main(String[] args) { junit.textui.TestRunner.run(EJBsTest.suite()); } /** * Despliegua todos los elementos que necesitamos para ejecutar los test. * Simula la construcción de un jar, y como si luego echáramos este jar al directorio server/default/deploy del JBoss. * @throws DeploymentException si no se puede hacer el despliegue. */ private static void deploy() throws DeploymentException { jar = AssembledContextFactory.getInstance().create("ejbTestCase.jar"); jar.addClass(Greeter.class); jar.addClass(GreeterRemote.class); jar.addClass(DummyGreeterBean.class); Bootstrap.getInstance().deploy(jar); } /** * Elimina los elementos que se habían desplegado con deploy(); * @throws DeploymentException si no se puede hacer la desinstalación. */ private static void undeploy() throws DeploymentException { Bootstrap.getInstance().undeploy(jar); AssembledContextFactory.getInstance().remove(jar); } /** * Este método determina los métodos que se van a ejecutar con el test. * @return El conjunto de test que hay que ejecutar. */ public static junit.framework.Test suite() { final junit.framework.Test suite = new JUnit4TestAdapter(EJBsTest.class); return suite; } /** * La inicialización de Embedded JBoss tarda varios segundos así que nos aseguramos que se haga una única vez. * @throws DeploymentException si no se puede hacer el despliegue de los elementos para ejecutar los tests. */ @org.junit.BeforeClass public static void setUpBeforeAllTest() throws Exception { if (! Bootstrap.getInstance().isStarted()) { Bootstrap.getInstance().bootstrap(); } EJBsTest.deploy(); } /** * Parada del Embedded JBoss. Nos aseguramos que se haga una única vez después de ejecutar todos los test. * @throws DeploymentException En caso de error en el proceso de desinstalación. */ @org.junit.AfterClass public static void tearDownAfterAllTest() throws DeploymentException { EJBsTest.undeploy(); if (System.getProperty("shutdown.embedded.jboss") != null) { Bootstrap.getInstance().shutdown(); } } /** * Invocación a través del interfaz local * @throws javax.naming.NamingException En caso de problemas */ @org.junit.Test public void dummyGreeterBean_sayHi_loacal() throws javax.naming.NamingException { InitialContext ctx = new InitialContext(); Greeter greeter = (Greeter)ctx.lookup("DummyGreeterBean/local"); String greeting = greeter.sayHi(); Assert.assertEquals(DummyGreeterBean.DEFAULT_GREETING, greeting); } /** * Invocación a través del interfaz remoto * @throws javax.naming.NamingException En caso de problemas */ @org.junit.Test public void dummyGreeterBean_sayHi_remote() throws javax.naming.NamingException { InitialContext ctx = new InitialContext(); GreeterRemote greeter = (GreeterRemote) ctx.lookup("DummyGreeterBean/remote"); String greeting = greeter.sayHi(); Assert.assertEquals(DummyGreeterBean.DEFAULT_GREETING, greeting); } }
Archivo pom.xml
:
Está autocomentado.
4.0.0 com.autentia.tutoriales.jbossembeddedjava6 embeddedJBoss3Java6 jar 1.0-SNAPSHOT embeddedJBoss3Java6 http://maven.apache.org jboss-repository JBoss Repository http://repository.jboss.com/maven2 default org.apache.maven.plugins maven-compiler-plugin 1.6 org.apache.maven.plugins maven-surefire-plugin 2.4.2 -Dsun.lang.ClassLoader.allowArraySyntax=true org.jboss.embedded jboss-embedded-all beta3 test org.jboss.embedded jboss-embedded beta3 test org.jboss.embedded thirdparty-all beta3 test org.jboss.embedded hibernate-all beta3 test jboss jboss-ejb-api 4.2.0.GA provided junit junit 4.3.1 test
Conclusiones
Por desgracia a veces cuando sale una nueva versión al mercado de algún elemento (en este caso Java 6) puede aparecer algún problema el cual requiera realizar acciones adicionales para su funcionamiento, en este caso modificar los archivos de configuración y parámetros de ejecución de la JVM.
Un saludo.
Carlos García. Creador de MobileTest, un complemento educativo para los profesores y sus alumnos.