Adam Bien's Weblog

Monday Sep 28, 2009

Embedding EJB 3.1 Container Into Your Unit Tests - Boot Time: 5 Seconds

It simpler and faster, than you may think. The following no-interface view EJB 3.1:

@Stateless

public class HelloWorld {

    public String hello(String message){

        return "Echo: " + message;

    }

...is tested with - the following unit test with embeddable EJB 3.1 container: 

public class HelloWorldTest {

  @Test

  public void hello() throws NamingException{

    EJBContainer ejbC = EJBContainer.createEJBContainer();

    Context ctx = ejbC.getContext();

    HelloWorld helloWorld = (HelloWorld) ctx.lookup("java:global/classes/HelloWorld");

    assertNotNull(helloWorld);

    String expected = "duke";

    String hello = helloWorld.hello(expected);

    assertNotNull(hello);

    assertTrue(hello.endsWith(expected));

    ejbC.close();

  }

It was tested with Glassfish v3 b66 - it is important to use at least the build 66. The sample was developed with Netbeans 6.8 daily builds (should work with 6.7.1 as well).

There is absolutely no configuration or classpath changes needed. You will see an exception first - this issue is already reported. It doesn't, however, impact the test. 

The entire test, with booting the container, takes on my machine about 5 seconds. The project [EmbeddableGlassfishEJB31Test] was already checked-in into: http://kenai.com/projects/javaee-patterns/

[See BeanLocator, page 108 in "Real World Java EE Patterns Rethinking Best Practices" book for EJB 3.0 embeddable test practices, and page 111 for testing with transactions]


NEW: Java EE 7 Testing and Quality Workshop

A book about rethinking Java EE Patterns

Comments:

Thank you Adam. Very useful...waiting for the final release :)

Posted by abdrabba yassine on September 28, 2009 at 02:21 PM CEST #

hi,
I get this error, when running on GlassFish v3 (build 65)

No EJBContainer provider available: no provider names had been found.
javax.ejb.EJBException: No EJBContainer provider available: no provider names had been found.
at javax.ejb.embeddable.EJBContainer.reportError(EJBContainer.java:184)
at javax.ejb.embeddable.EJBContainer.createEJBContainer(EJBContainer.java:121)
at javax.ejb.embeddable.EJBContainer.createEJBContainer(EJBContainer.java:78)
at com.abien.business.hello.HelloWorldTest.hello(HelloWorldTest.java:23)

Do you have any ideas ??

Posted by abdrabba yassine on September 28, 2009 at 08:27 PM CEST #

@Abdrabba

1. You are right - it is an error :-)
2. Try it with build 66

And - it works?

adam

Posted by Adam Bien on September 29, 2009 at 01:03 AM CEST #

I'm just wondering if you still can call such tests UNIT TESTS.

Posted by Bartek Majsak on September 29, 2009 at 02:02 AM CEST #

Where does this container come from? I use Maven so I imagine I would need to add a dependency on some EJB container artifact for test scope. I'm wondering how Java SE knows where the container is and how to load it. I imagine the default NetBeans ant project is configured with a dependency on .jar files in the GlassFish V3 installation directory, and I'm not sure how portable that is to a build server. I like to be able to check out my Maven project to any computer on any OS, have it pull down dependencies from our repo, then build.

Do you get transactions? What if you query two different databases within one transaction, is XA supported? I wonder if it is XA or local transactions in the unit testing environment.

I'd like to see some information on unit testing JAX-WS and JAX-RS EJB endpoints. I think SOAP UI might be helpful but I haven't used it yet.

Once I finish reading my current book and one other, I plan to buy your Java EE 6 patterns book! NBDT promo code? :)

Posted by Ryan de Laplante on September 29, 2009 at 08:49 AM CEST #

> I wonder if it is XA or local transactions in the unit testing environment.

I meant to say "I wonder if it is JTA or ...."

Posted by Ryan de Laplante on September 29, 2009 at 08:51 AM CEST #

If my EJB's inject or look up things from JNDI such as JDBC DataSources, JavaMail Sessions, JCA connectors, etc. how do I test that?

Posted by Ryan de Laplante on September 29, 2009 at 08:52 AM CEST #

@Bartek,

"I'm just wondering if you still can call such tests UNIT TESTS."

I would call it integration-unit. "Real" unit tests are rather primitive: http://www.adam-bien.com/roller/abien/entry/unit_testing_ejb_3_1

However you call it - it is useful,

thanks!,

adam

Posted by Adam Bien on September 29, 2009 at 10:24 AM CEST #

Of course such setups are useful and indeed this solution looks really promising. Keep up great writing!

Cheers,
Bartek

Posted by Bartek on September 29, 2009 at 10:37 PM CEST #

Hi adam,
I tested the example on GlassFish v3 (build 66) and I have the same error I googled and can't find a fix for that. any advice ?

Posted by abdrabba yassine on October 02, 2009 at 11:18 AM CEST #

You may find this useful for the Maven and JPA questions: http://blogs.sun.com/alexismp/entry/testing_ejb_3_1_s

Posted by Alexis MP on October 05, 2009 at 11:23 PM CEST #

Hi Adam,
Using Netbeans 6.8M1 and glassfish-b66, I'm getting the following error at the line.

EJBContainer ejbC = EJBContainer.createEJBContainer();

java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/ejb/embeddable/EJBContainer

Do you have any idea how to avoid this problem?

Posted by Sean on October 09, 2009 at 01:35 PM CEST #

Wurde auch langsam Zeit

Posted by Heiko Scherrer on October 12, 2009 at 02:28 AM CEST #

Looks very cool. How does the classpath look like if the container shall be launched from the commandline or an ordinary Ant build, without NetBeans classpath magic?

Posted by Karl Peterbauer on October 27, 2009 at 11:31 PM CET #

"java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/ejb/embeddable/EJBContainer"

I also have this issue. And browsing around for a solution does not give me any help. Suggestions?

Posted by Rodrigo Hartmann on January 26, 2010 at 10:10 PM CET #

It seems that the "...Absent Code attribute in method ..." error is due to the javaee-api jar being used instead of the real Glassfish implementation. http://forums.java.net/jive/message.jspa?messageID=226931
http://docs.codehaus.org/pages/viewpage.action?pageId=26408

Even if it is scoped as "provided", the test classpath contains "provided". This is somehow logical, but Maven provides no alternatives, as for now.

You may try to put the javaee-api dependency as the last dependency in the pom file. It worked for me, until I ran in a MDB/JMS related problem, but I think that MDB isn't supoprted yet.

Posted by Bruno on February 24, 2010 at 05:37 PM CET #

Repeating Ryan De La Plante's question:

If my EJB's inject or look up things from JNDI such as JDBC DataSources, JavaMail Sessions, JCA connectors, etc. how do I test that?

I have found a blog entry by Arun Gupta that does this using Glassfish internal APIs (http://blogs.sun.com/arungupta/entry/totd_133_jpa2_jpql_criteria).

Another blog entry suggests building a domain.xml and telling the embedded container to use these settings (http://ctpjava.blogspot.com/2009/10/unit-testing-ejbs-and-jpa-with.html)

And something from IBM seems to suggest setting some magical mysterious properties and passing these into createEJBContainer(Map<?,?>) (http://publib.boulder.ibm.com/infocenter/wasinfo/beta/index.jsp?topic=/com.ibm.websphere.nd.doc/info/ae/ae/tejb_dvemcontainer.html)

None of these seem particularly nice...the IBM one seems most "server agnostic" (maybe this doesn't matter). Any good advice for testing this?

Posted by Christopher Rued on September 28, 2010 at 10:03 PM CEST #

Die aktuelle Version 3.0.1 des embedded GlassFish scheint leider Probleme zu verursachen. Version 3.0 läuft. Also aufpassen beim Benutzen der Dependencies.

siehe auch:
http://java-abwaschbar.blogspot.com/2011/01/integrational-unit-tests-mit-ejb31.html

Posted by Frederik Mortensen on January 23, 2011 at 11:36 PM CET #

This is exactly the kind of rubbish that wastes so much time when trying to develop with frameworks.

It may have worked under some conditions, but not for most people who will have the misfortune to find it using Google.

Posted by Geoffrey Chaucer on January 25, 2012 at 01:05 AM CET #

In my case recipe for success was very sudden. I've just changed an order for dependencies:

Wrong sequence:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
</dependency>

<dependency>
<groupId>org.glassfish</groupId>
<artifactId>maven-embedded-glassfish-plugin</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.glassfish.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<scope>test</scope>
</dependency>

Right sequence: javax must be added last

Posted by Eugene on April 16, 2012 at 04:58 PM CEST #

@Eugene,

please remove the dependency to javaee-api completely. Everything you need is already included in glassfish-embedded. Please see: http://www.adam-bien.com/roller/abien/entry/trouble_with_crippled_java_ee

thanks your comment!,

adam

Posted by Adam Bien on April 18, 2012 at 02:32 AM CEST #

You Can see please remove the dependency to javaee-api completely. Everything you need is already included in glassfish-embedded. Please see::http://www.adam-bien.com/roller/abien/entry/trouble_with_crippled_java_ee

Posted by Programming Pad on January 20, 2013 at 02:22 AM CET #

I followed all the steps, the official link net beans, but I get this error:

GRAVE: EJB6001: Caught exception instantiating EmbeddedContainer.
java.lang.NoSuchMethodError: org.objectweb.asm.ClassReader.accept (Lorg / ObjectWeb / asm / ClassVisitor, I) V
at
at
at
at org.glassfish.ejb.embedded.EJBContainerProviderImpl.addModule (EJBContainerProviderImpl.java: 376)
at org.glassfish.ejb.embedded.EJBContainerProviderImpl.addModules (EJBContainerProviderImpl.java: 279)
at
at javax.ejb.embeddable.EJBContainer.createEJBContainer (EJBContainer.java: 127)
at javax.ejb.embeddable.EJBContainer.createEJBContainer (EJBContainer.java: 102)
at ejb.MyBeanTest.testAddNumbers (MyBeanTest.java: 48)
at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java: 39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java: 25)
at java.lang.reflect.Method.invoke (Method.java: 597)
org.junit.runners.model.FrameworkMethod at $ 1.runReflectiveCall (FrameworkMethod.java: 45)
at org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java: 15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java: 42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate (InvokeMethod.java: 20)
at org.junit.internal.runners.statements.RunBefores.evaluate (RunBefores.java: 28)
at org.junit.internal.runners.statements.RunAfters.evaluate (RunAfters.java: 30)
at org.junit.runners.ParentRunner.runLeaf (ParentRunner.java: 263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java: 68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java: 47)
at org.junit.runners.ParentRunner $ 3.run (ParentRunner.java: 231)
at org.junit.runners.ParentRunner $ 1.schedule (ParentRunner.java: 60)
at org.junit.runners.ParentRunner.runChildren (ParentRunner.java: 229)
org.junit.runners.ParentRunner.access at $ 000 (ParentRunner.java: 50)
at org.junit.runners.ParentRunner $ 2.evaluate (ParentRunner.java: 222)
at org.junit.internal.runners.statements.RunBefores.evaluate (RunBefores.java: 28)
at org.junit.internal.runners.statements.RunAfters.evaluate (RunAfters.java: 30)
at org.junit.runners.ParentRunner.run (ParentRunner.java: 300)
at junit.framework.JUnit4TestAdapter.run (JUnit4TestAdapter.java: 39)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run (JUnitTestRunner.java: 520)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch (JUnitTestRunner.java: 1060)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main (JUnitTestRunner.java: 911)
03/01/2013 11:11:45 AM org.glassfish.ejb.embedded.EJBContainerProviderImpl createEJBContainer
INFO: [EJBContainerProviderImpl] Cleaning up on failure ...
03/01/2013 11:11:45 AM org.glassfish.admin.mbeanserver.JMXStartupService shutdown
INFO: JMXStartupService and JMXConnectors Have Been Shut Down.
03/01/2013 11:11:45 AM org.glassfish.admin.mbeanserver.JMXStartupService shutdown
INFO: JMXStartupService and JMXConnectors Have Been Shut Down.
03/01/2013 11:11:45 AM com.sun.enterprise.v3.server.AppServerStartup stop
INFO: The shutdown procedure is complete
03/01/2013 11:11:45 AM AppServerStartup run
INFO: [Thread [GlassFish Kernel Main Thread, 5, main]] exiting

Posted by Javier on March 01, 2013 at 08:21 PM CET #

Post a Comment:
  • HTML Syntax: NOT allowed
realworldpatterns.com
...the last 150 posts
...the last 10 comments
Links
License