This questiong is regarding Java EE 6, using glassfish v3 embedded-all.
I have a unit test that uses EJBContainer to test my stateless EJB. Problem is I'm having trouble looking up the EJB (remote) using JNDI:
setup() {
ctx = EJBContainer.createEJBContainer().getContext();
}
...
test() {
BookService bookService = (BookService)ctx.lookup("java:global/BookServiceEJB!com.something.service.BookService");
...
}
@Stateless
public class BookServiceEJB implements BookService {
...
}
@Remote
public interface BookService {
...
}
gives the exception:
javax.naming.NamingException: Lookup failed for 'java:global/BookServiceEJB!com.something.service.BookService' in SerialContext [Root exception is javax.naming.NameNotFoundException: BookServiceEJB!com.something.service.BookService not found]
...
caused by: javax.naming.NameNotFoundException: BookServiceEJB!com.something.service.BookService not found
I have tried several JNDI resource paths:
e.g.
java:global/BookServiceEJB
java:global/BookService
even:
java:global/BookShelf-1.0-SNAPSHOT/BookServiceEJB
etc...
nothings works
I do not have any xml deployment files configured, only a persistence.xml
in META-INF.
The test is using maven surefire:
mvn clean test
Any help is greatly appreciated!
Note: a full deploy to Glassfish server works (using appclient, and @EJB
injection)
After much searching, found the solution that works for me...
You'll have to configure the EJBContainer with the property: EJBContainer.MODULES, and the location where the module classes are (if using maven, 'target/classes').
e.g.
...
props = new Properties();
props.put(EJBContainer.MODULES, new File("target/classes"));
ec = EJBContainer.createEJBContainer(props);
...
If your EJB uses JPA, theres another problem in that you will not be able to define a datasource in the embedded container, so have to use the default ds: 'jdbc/__default'.
so for example my persistence.xml looks like so:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
version="1.0">
<persistence-unit name="bookshelf" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.blah.domain.Book</class>
<jta-data-source>jdbc/__default</jta-data-source>
<properties>
<property name="eclipselink.logging.level" value="INFO"/>
</properties>
</persistence-unit>
</persistence>
I haven't figured out how to configure the embedded container test to use one DS (jdbc/__default), and my app to use another (e.g. jdbc/booksDS)
see: http://www.mentby.com/glassfish/embedded-testing-woes.html
see: http://forums.java.net/jive/thread.jspa?messageID=395759
To be honest I don't know why people are bothering with Java EE when solutions like spring is so much simpler...
It has been very frustrating and alot of time wasted... hope this helps.
There's a few items you need to check in order to make sure you can load the bean through the context.lookup avoiding a NamingException.
Make sure you have a bean. This may sound something obvious but I spent a lot of time trying to figure out why I wasn't able to get an instance of my service in the tests. The reason was that I was missing the Stateless annotation.
Add the module when creating the container as @Dzhu pointed out. For maven classes will be target/classes, for maven tests will be target/test-classes.
Something is wrong if you find a message like SEVERE: EJB6005:No EJB modules found
in the console. It tells you that there are no Stateless annotated classes
Take a look at the embedded glassfish console! In there you will see the lookup names for your beans. Pay attention to the messages in the format INFO: EJB5181:Portable JNDI names for EJB YourBean: [java:global/classes/YourBean!bean.package.YourBean,
java:global/classes/YourBean]
. That means you can lookup your bean either by calling context.lookup("java:global/classes/YourBean!bean.package.YourBean")
or by the shorter name context.lookup("java:global/classes/YourBean")
which can be useful if there's no name collisions.
Hope this helps someone. It would have been really helpful to have had this tips.
I have written a small tutorial on using the embedded glassfish 3.1 container, also addressing the issue for needing a different persistence.xml for tests. Also fixing container crashes with remote interfaces and webservices. You can check it out at http://pschyska.blogspot.com/2011/06/unit-testing-ejb-31-with-netbeans-maven.html