EJB 3.0 y pruebas unitarias con Maven, JUnit 4 y Embedded JBoss sobre Java 6

0
13962

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 (http://www.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.

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:

  1. Definiremos una interfaz que exponga la funcionalidad local del EJB.
  2. Definiremos una interfaz que exponga la funcionalidad remota del EJB.
  3. Crearemos un EJB sin estado que expone el servicio local y remoto definido anteriormente.
  4. Creamos un par de tests JUnit que despliege el EJB en el microcontenedor JBoss Emdebbed 3 e invoque el método local y remoto.
  5. 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
          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.

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