Home > Java > How to test EJB3.1 with embedded container?

How to test EJB3.1 with embedded container?

This is how you can test your EJB3.1 or the one I made here using an new embedded container provided in the new EJB. You can download the full package to test this here

We start off with creating an pom.xml so we can start using maven.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>coralic</groupId>
	<artifactId>ejbembeddedtest</artifactId>
	<packaging>jar</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>ejbembeddedtest</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.glassfish.extras</groupId>
			<artifactId>glassfish-embedded-all</artifactId>
			<version>3.0</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.0.2</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Now we take the sources from here and copy them to src/main/java/nl/coralic/blog/ejb31/

The presistance.xml from that sample goes here src/main/resources/META-INF

To be able to run the embedded container you need an implementation of it, I am using glassfish ones. You need the domain.xml in here glassfish/domains/domain1/config and you need the ds_jdbc_ra in glassfish/lib/install/applications/__ds_jdbc_ra. Without domain.xml and the configuration files in the ds_jdbc_ra your embedded container is not able to use database (derby).

domain.xml sample

<domain log-root="${com.sun.aas.instanceRoot}/logs" application-root="${com.sun.aas.instanceRoot}/applications" version="10.0">
  <system-applications />
  <applications />
  <resources>
    <jdbc-resource pool-name="__TimerPool" jndi-name="jdbc/__TimerPool" object-type="system-admin" />
    <jdbc-resource pool-name="DerbyPool" jndi-name="jdbc/itemDataBase" />
    <jdbc-connection-pool name="__TimerPool" datasource-classname="org.apache.derby.jdbc.EmbeddedXADataSource" res-type="javax.sql.XADataSource">
      <property value="${com.sun.aas.instanceRoot}/lib/databases/ejbtimer" name="databaseName" />
      <property value=";create=true" name="connectionAttributes" />
    </jdbc-connection-pool>
    <jdbc-connection-pool name="DerbyPool" datasource-classname="org.apache.derby.jdbc.EmbeddedXADataSource" res-type="javax.sql.XADataSource">
     <property value="${com.sun.aas.instanceRoot}/lib/databases/default" name="databaseName" />
       <property value=";create=true" name="connectionAttributes" />
     </jdbc-connection-pool>
  </resources>
  <servers>
    <server name="server" config-ref="server-config">
      <resource-ref ref="jdbc/__TimerPool" />
      <resource-ref ref="jdbc/itemDataBase" />
    </server>
  </servers>
 <configs>
   <config name="server-config">
     <http-service>
        <access-log rotation-interval-in-minutes="15" rotation-suffix="yyyy-MM-dd" />
        <virtual-server id="server"></virtual-server>
        <property value="false" name="accessLoggingEnabled" />
      </http-service>
      <iiop-service>
        <orb use-thread-pool-ids="thread-pool-1" />
        <iiop-listener address="0.0.0.0" port="3700" id="orb-listener-1" />
        <iiop-listener security-enabled="true" address="0.0.0.0" port="3820" id="SSL">
          <ssl cert-nickname="s1as" />
        </iiop-listener>
        <iiop-listener security-enabled="true" address="0.0.0.0" port="3920" id="SSL_MUTUALAUTH">
          <ssl cert-nickname="s1as" client-auth-enabled="true" />
        </iiop-listener>
      </iiop-service>
      <admin-service type="das-and-server" system-jmx-connector-name="system">
        <jmx-connector enabled="false" auth-realm-name="admin-realm" security-enabled="false" address="0.0.0.0" port="8686" name="system" />
        <das-config autodeploy-enabled="false" dynamic-reload-enabled="true" deploy-xml-validation="full" autodeploy-dir="${com.sun.aas.instanceRoot}/autodeploy" />
        <property value="/admin" name="adminConsoleContextRoot" />
        <property value="${com.sun.aas.installRoot}/lib/install/applications/admingui.war" name="adminConsoleDownloadLocation" />
        <property value="${com.sun.aas.installRoot}/.." name="ipsRoot" />
      </admin-service>
      <connector-service shutdown-timeout-in-seconds="30">
      </connector-service>
      <ejb-container steady-pool-size="0" max-pool-size="32" session-store="${com.sun.aas.instanceRoot}/session-store" pool-resize-quantity="8">
        <ejb-timer-service />
      </ejb-container>
      <mdb-container steady-pool-size="0" max-pool-size="32" pool-resize-quantity="8" >
      </mdb-container>
      <jms-service type="EMBEDDED" default-jms-host="default_JMS_host">
        <jms-host name="default_JMS_host" host="localhost" port="7676" admin-user-name="admin" admin-password="admin"/>
      </jms-service>
      <log-service file="${com.sun.aas.instanceRoot}/logs/server.log" log-rotation-limit-in-bytes="2000000">
        <module-log-levels />
      </log-service>
      <security-service activate-default-principal-to-role-mapping="true" jacc="simple">
        <auth-realm classname="com.sun.enterprise.security.auth.realm.file.FileRealm" name="admin-realm">
          <property value="admin-keyfile" name="file" />
          <property value="fileRealm" name="jaas-context" />
        </auth-realm>
        <auth-realm classname="com.sun.enterprise.security.auth.realm.file.FileRealm" name="file">
          <property value="keyfile" name="file" />
          <property value="fileRealm" name="jaas-context" />
        </auth-realm>
        <auth-realm classname="com.sun.enterprise.security.auth.realm.certificate.CertificateRealm" name="certificate" />
        <jacc-provider policy-configuration-factory-provider="com.sun.enterprise.security.provider.PolicyConfigurationFactoryImpl" policy-provider="com.sun.enterprise.security.provider.PolicyWrapper" name="default">
          <property value="${com.sun.aas.instanceRoot}/generated/policy" name="repository" />
        </jacc-provider>
        <jacc-provider policy-configuration-factory-provider="com.sun.enterprise.security.jacc.provider.SimplePolicyConfigurationFactory" policy-provider="com.sun.enterprise.security.jacc.provider.SimplePolicyProvider" name="simple" />
        <audit-module classname="com.sun.enterprise.security.Audit" name="default">
          <property value="false" name="auditOn" />
        </audit-module>
        <message-security-config auth-layer="SOAP">
          <provider-config provider-id="XWS_ClientProvider" class-name="com.sun.xml.wss.provider.ClientSecurityAuthModule" provider-type="client">
            <request-policy auth-source="content" />
            <response-policy auth-source="content" />
            <property value="s1as" name="encryption.key.alias" />
            <property value="s1as" name="signature.key.alias" />
            <property value="false" name="dynamic.username.password" />
            <property value="false" name="debug" />
          </provider-config>
          <provider-config provider-id="ClientProvider" class-name="com.sun.xml.wss.provider.ClientSecurityAuthModule" provider-type="client">
            <request-policy auth-source="content" />
            <response-policy auth-source="content" />
            <property value="s1as" name="encryption.key.alias" />
            <property value="s1as" name="signature.key.alias" />
            <property value="false" name="dynamic.username.password" />
            <property value="false" name="debug" />
            <property value="${com.sun.aas.instanceRoot}/config/wss-server-config-1.0.xml" name="security.config" />
          </provider-config>
          <provider-config provider-id="XWS_ServerProvider" class-name="com.sun.xml.wss.provider.ServerSecurityAuthModule" provider-type="server">
            <request-policy auth-source="content" />
            <response-policy auth-source="content" />
            <property value="s1as" name="encryption.key.alias" />
            <property value="s1as" name="signature.key.alias" />
            <property value="false" name="debug" />
          </provider-config>
          <provider-config provider-id="ServerProvider" class-name="com.sun.xml.wss.provider.ServerSecurityAuthModule" provider-type="server">
            <request-policy auth-source="content" />
            <response-policy auth-source="content" />
            <property value="s1as" name="encryption.key.alias" />
            <property value="s1as" name="signature.key.alias" />
            <property value="false" name="debug" />
            <property value="${com.sun.aas.instanceRoot}/config/wss-server-config-1.0.xml" name="security.config" />
          </provider-config>
        </message-security-config>
      </security-service>
      <monitoring-service>
        <module-monitoring-levels />
      </monitoring-service>
      <transaction-service tx-log-dir="${com.sun.aas.instanceRoot}/logs" >
      </transaction-service>
      <network-config>
        <protocols>
        </protocols>
        <network-listeners>
        </network-listeners>
        <transports>
          <transport name="tcp"></transport>
        </transports>
      </network-config>
      <thread-pools>
          <thread-pool name="http-thread-pool" max-queue-size="4096"></thread-pool>
          <thread-pool name="thread-pool-1" max-thread-pool-size="200"/>
      </thread-pools>
    </config>
  </configs>
  <property name="administrative.domain.name" value="domain1"/>
</domain>

Now that we have prepared everything we need to create an junit test to start our container and to test our bean.

package test;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import javax.ejb.embeddable.EJBContainer;
import javax.naming.Context;
import javax.naming.NamingException;

import nl.coralic.blog.ejb31.*;

import org.junit.Test;

public class TestItem
{
	@Test
	public void saveAndGetKlant() throws NamingException, InterruptedException
	{
		Map<String, Object> properties = new HashMap<String, Object>();
		properties.put(EJBContainer.MODULES, new File("target/classes"));
		properties.put("org.glassfish.ejb.embedded.glassfish.installation.root", "glassfish");
		properties.put(EJBContainer.APP_NAME, "coralic");
		EJBContainer c = EJBContainer.createEJBContainer(properties);
		Context ic = c.getContext();
		ItemService itemService = (ItemService) ic.lookup("java:global/coralic/ItemService");
		Item item = new Item();
		item.setItemName("testname");
		itemService.save(item);

		System.out.println("Get all items from DB and show itemname for the first one: " + itemService.getItems().get(0).getItemName());

		c.close();
	}
}

All the required components ready to use, so lets start the test by running maven.

mvn clean compile jar:jar test

That’s it, this is all you have to do to test your EJB. Very easy and useful.

Share
Categories: Java Tags: , , ,
  1. Kaveen
    September 16th, 2010 at 04:54 | #1

    Hi

    Thanks for this great stuff!! I need to know where to place a mysql driver in order to connect to a mysql database? Can you help please? I am getting the error below:

    java.sql.SQLException: Error in allocating a connection. Cause: Class name is wrong or classpath is not set for : com.mysql.jdbc.jdbc2.optional.MysqlDataSource

  2. Amin
    September 16th, 2010 at 06:17 | #2

    Hi

    Thanks for this great solution.
    I have one question, what is the ds_jdbc_ra

  3. admin
    September 26th, 2010 at 16:01 | #3

    @Amin
    It should be the derby files.

    @Kaveen
    You could add them to you pom file.

  4. Bobby Jakachira
    November 18th, 2010 at 07:50 | #4

    Hi, Good article but i have a problem whenever I try to run my tests.

    I use JTA for my session beans. but when doing tests now i would like to rollback all database changes in at @AfterClass.. i will i do it..

  5. admin
    November 18th, 2010 at 12:35 | #5

    @Bobby Jakachira
    You could try to use the user transaction, something like this maybe:

    UserTransaction ut = context.getUserTransaction();
    ut.begin();
    DO YOUR TEST
    ut.commit(); OR ut.rollback();

  6. Luc De Graef
    August 24th, 2011 at 08:07 | #6

    Hello,
    I need to implement unit tests in a multi-module project (eclipse / maven / embedded GF).
    The unit test is located in a DomainService project, and the GF server is created in @BeforeClass as follows:
    Map props = new HashMap();
    props.put( EJBContainer.APP_NAME, MODULE_NAME );
    ejbContainer = EJBContainer.createEJBContainer( props );
    context = ejbContainer.getContext();

    This DomainService project does not have a persistence.xml

    Within the tests, calls are made towards a JPA project. This JPA project provides a src/main/resources/META-INF/persistence.xml as well as a src/test/resources/META-INF/persistence.xml.
    Of course the JPA jar file only contains the ‘main’ persistence.xml.

    –> From within Eclipse, running the Unit tests does not succeed, because multiple persistence.xml’s are found on the classpath :

    SEVERE: Could not resolve a persistence unit corresponding to the persistence-context-ref-name [com.cosmosworldwide.atoms.masterdatalookup.services.dao.ejb.MasterDataLookupDAOFactoryLocatorImpl/entityManager] in the scope of the module called [masterdata#classes.jar]. Please verify your application.

    –> From within Maven Command Line (surefire), the test version of the persistence.xml is of course not found.

    What are best practices to get unit tests working from within Eclipse & maven/surefire?
    - should I specify always the test persistence.xml as the ‘default one that is packaged’?
    - should we replace it ‘during the deployment to the actual application server’?

    Thanks for feedback

  1. March 9th, 2010 at 15:12 | #1
  2. March 9th, 2010 at 16:21 | #2