EJB 3.0 y pruebas unitarias con Maven, JUnit 4 y Apache Open EJB.

1
16947

EJB 3.0 y pruebas unitarias con Maven, JUnit 4 y Apache Open EJB.

0. Índice de contenidos.

1. Introducción.

Apache OpenEJB es un contenedor de EJBs de código abierto, ligero e integrable,
liberado bajo la Licencia Apache 2.0. Como tal, ha sido integrado en servidores de aplicaciones J2EE como
Gerónimo o WebObjects.

Para nuestros propósitos vamos a utilizarlo como un microcontenedor de EJBs que nos permita ejecutar pruebas unitarias con JUnit y el soporte de Maven.

Hasta ahora, habíamos estado usando Embedded Jboss en sus versiones 2
y 3, solucionando problemas diversos a la hora de ejecutar
tests de persistencia.
En este tutorial vamos a comprobar la sencillez de pasar a OpenEJB y nos olvidaremos de todos los problemas de configuración y de subidas de versiones de la JVM que hemos tenido con Embedded Jboss.

Este tutorial se basa en los anteriores de Embedded Jboss en el sentido que prueba los mismos EJBs, pero ahora con OpenEJB, con lo que para obtener el código de los mismos a aquellos me remito.

2. Entorno.

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil Asus G1 (Core 2 Duo a 2.1 GHz, 2048 MB RAM, 120 GB HD).
  • Sistema operativo: Windows Vista Ultimate.
  • JDK 1.6.0_14
  • Maven 2.1.
  • Apache OpenEJB 3.1.

3. Configuración.

La configuración es bastante más simple, puesto que no hay que descargarse ningún binario y montarlo en el entorno de test, basta con incluir las siguientes
dependencias en nuestro pom.xml con el scope de test:

    
        org.apache.openejb
        openejb-core
        3.1
        test
    
    
        org.hibernate
        hibernate-entitymanager
        3.4.0.GA
        test
    

El resto de dependencias son las mismas que con Embedded Jboss pero sustituyendo las propias de org.jboss.embedded por estas y añadiendo, además, la
siguiente:

		
			org.slf4j
			slf4j-log4j12
			1.4.2
			test
		

The Simple Logging Facade for Java or (SLF4J) proporciona una fachada o abstración para varios frameworks de logging como java.util.logging, log4j and logback,
permitiendo elegir el concreto en tiempo de desarrollo (echando uno u otro jar).

4. Test de EJBs locales y remotos.

El siguiente test cubre nuestras necesidades. Si lo comparamos con el test que corre bajo Embedded Jboss ahora no se requiere el despliegue de un jar montado
dentro de un directorio virtual, OpenEJB se limita a escanear las librerías del classpath en busca de jar que contengan EJBs, con lo que no hay que desplegar
manualmente nada. Para que reconozca un jar como un módulo EJB basta con que encuentre un fichero ejb-jar.xml en el directorio META-INF del mismo, el contenido,
en principio, es indiferente, puede estar vacío y solo contener «<ejb-jar />».

No se requiere una comprobación del estado del microcontenedor, ni un arranque manual. Lo único necesario es la asignación de la propiedad «org.apache.openejb.client.LocalInitialContextFactory»
como factoría del contexto de nombres, aunque también podría estar en un fichero jndi.properties.

package com.autentia.openejb;

import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.junit.Assert;

/**
 * Tests que deseamos realizar de nuestra lógica de negocio
 * @author jmsanchez@autentia.com
 */
public class EJBsTest {

    static Context context;
    
	/**
	 * Inicialización del contenedor de EJBs.
	 * @throws NamingException 
	 */
	@org.junit.BeforeClass
	public static void setUpBeforeAllTest() throws NamingException  {
		Properties props = new Properties();
        props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
                "org.apache.openejb.client.LocalInitialContextFactory");
        
        context = new InitialContext(props);

	}

	/**
	 * Parada del contenedor de EJBs.
	 * @throws NamingException
	 */
	@org.junit.AfterClass
	public static void tearDownAfterAllTest() throws NamingException {
        context.close();
	}

	/**
	 *  Invocación a través del interfaz local
	 * @throws NamingException 
	 */
	@org.junit.Test
	public void dummyGreeterBean_sayHi_loacal() throws NamingException  {
		Greeter greeter = (Greeter) context.lookup("DummyGreeterBeanLocal");
		String greeting = greeter.sayHi();
		Assert.assertEquals(DummyGreeterBean.DEFAULT_GREETING, greeting);
	}
	
	/**
	 * Invocación a través del interfaz remoto
	 * @throws NamingException 
	 */
	@org.junit.Test
	public void dummyGreeterBean_sayHi_remote() throws NamingException  {
		GreeterRemote greeter = (GreeterRemote) context.lookup("DummyGreeterBeanRemote");
		String greeting = greeter.sayHi();
		Assert.assertEquals(DummyGreeterBean.DEFAULT_GREETING, greeting);
	}	
}

Con la instancia de javax.naming.Context podemos obtener las referencias a los EJBs para los tests, teniendo en cuenta que, por defecto
OpenEJB publica los EJBs con el nombre NombreDelEjbTipodeinterfaz; de ahí que el SLSB que nosotros llamamos DummyGreeterBean
se publique como DummyGreeterBeanLocal y DummyGreeterBeanRemote.

5. Test de EJBs de entidad.

Para la ejecución de los tests de persistencia no hemos tenido que realizar modificaciones significativas, salvo crear programáticamente un datasource
con el nombre DefaultDS, que tendrá el nombre jndi java:openejb/Resource/DefaultDS, al que ya hacíamos referencia en el fichero persistence.xml.

package com.autentia.openejb;

import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import com.autentia.training.ejb3.entities.User;
import com.autentia.training.ejb3.persistence.Dao;

/**
 * Tests de persistencia
 * @author jmsanchez@autentia.com
 */
public class PersistenceTest {

	static Context context;
	
	/**
	 * Inicialización del contenedor de EJBs y configuración del datasource.
	 * @throws NamingException 
	 */
	@BeforeClass
	public static void setUpBeforeAllTest() throws NamingException {
		Properties props = new Properties();
        props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
                "org.apache.openejb.client.LocalInitialContextFactory");

        props.put("DefaultDS", "new://Resource?type=DataSource");
        props.put("DefaultDS.JdbcDriver", "org.hsqldb.jdbcDriver");
        props.put("DefaultDS.JdbcUrl",    "jdbc:hsqldb:.");
        
        context = new InitialContext(props);
	}
    
	/**
	 * Parada del contenedor de EJBs.
	 * @throws NamingException 
	 */
	@AfterClass
	public static void tearDownAfterAllTest() throws NamingException {
		context.close();
	}

	/**
	 *  Tests de persistencia sobre la entidad User.
	 * @throws NamingException 
	 */
	@Test
	public void userCrudOperations() throws javax.naming.NamingException  {
		
		Dao dao = (Dao) context.lookup("GenericDaoLocal");
		
		User user = new User();
		user.setName("Jose Manuel Sánchez");
		user.setPassword("password");
		
		dao.persist(user);

		Assert.assertNotNull("User not found by id:" + user.getId(), 
				dao.get(User.class, user.getId()));

	}
}

Con ello quedan cubiertas nuestras necesidades.

6. Conclusiones.

Mucho más simple y muchos menos quebraderos de cabeza.

Si nuestro servidor de aplicaciones es Jboss Server tiene sentido que en el entorno de tests usemos su versión Embedded, aunque después de ver la sencillez con la que
podemos montar el entorno de tests con OpenEJB, quizás deje de tenerlo.

Un saludo.

Jose

mailto:jmsanchez@autentia.com

1 COMENTARIO

  1. Hola Jose Manuel…
    Estoy haciendo unos tests justo con OpenEJB, pero a la final el test me lanza siempre un

    org.hibernate.PersistentObjectException: detached entity passed to persist: it.f2informatica.rc.ejb.entities.Role

    El DAO, la transaccionalidad y los EJB creo tenerlos hechos correctamente, uso Hibernate… Si es un error comun quizas me darias un enderezada, gracias 😉

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