Java EE 6 - 嵌入式容器 EJB 测试

4
这个问题涉及到使用 glassfish v3 embedded-allJava EE 6。我有一个单元测试,使用 EJBContainer 来测试我的无状态 EJB。问题是我在使用 JNDI 查找 EJB(远程)时遇到了困难:
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 {
...
}

抛出异常:

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

甚至:

java:global/BookShelf-1.0-SNAPSHOT/BookServiceEJB

没有任何东西起作用。

我没有配置任何xml部署文件,只有一个在META-INF中的。

测试正在使用maven surefire:

mvn clean test

非常感谢您的帮助!

注意:将应用程序完全部署到Glassfish服务器上是可行的(使用appclient和@EJB注入)。


注意:完整部署到Glassfish服务器是可行的(使用appclient和@EJB注入)。 - Dzhu
3个回答

6

经过多次搜索,我找到了适合我的解决方案...

您需要使用属性EJBContainer.MODULES来配置EJBContainer,并指定模块类所在的位置(如果使用maven,则为“target/classes”)。

例如:

...
props = new Properties();
props.put(EJBContainer.MODULES, new File("target/classes"));
ec = EJBContainer.createEJBContainer(props);
...

如果您的EJB使用JPA,那么还有一个问题是您将无法在嵌入式容器中定义数据源,因此必须使用默认数据源:'jdbc / __default'。因此,例如,我的persistence.xml如下所示:
<?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> 

我还没有想出如何配置嵌入式容器测试以使用一个DS(jdbc / __default),而我的应用程序使用另一个DS(例如jdbc / booksDS)。
参见: http://www.mentby.com/glassfish/embedded-testing-woes.html 参见: http://forums.java.net/jive/thread.jspa?messageID=395759 老实说,我不知道为什么人们会费心去使用Java EE,因为像Spring这样的解决方案要简单得多...这让我感到非常沮丧,浪费了很多时间...希望这可以帮助到你。

此外,JNDI名称将采用以下格式:'java:global/classes/EJBClass!com.fully.qualified.remote.EJBRemoteInterface',即在JNDI字符串中不包括应用程序/模块组件。 - Dzhu
在定义了persistence.xml中的jta-data-source之后,我还收到了一个错误...内部异常:java.sql.SQLException:分配连接时出错。原因:无法分配连接,因为:java.net.ConnectException:连接服务器localhost的端口1527时出错,消息为Connection refused: connect。 错误代码:0 在org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:309)处。 - user237673

3

为确保可以通过context.lookup加载bean而避免NamingException,您需要检查以下几个项目。

  1. 确保您有一个bean。这可能听起来很明显,但我花了很多时间试图弄清楚为什么无法在测试中获取服务实例。原因是我缺少了Stateless注释。

  2. 在创建容器时添加模块,如@Dzhu所指出的。对于maven,classes将是target/classes,对于maven tests将是target/test-classes

  3. 如果在控制台上发现类似SEVERE: EJB6005:No EJB modules found的消息,则说明有问题。它告诉您没有Stateless注释的类。

  4. 查看嵌入式glassfish控制台!在那里,您将看到bean的查找名称。注意格式为INFO: EJB5181:Portable JNDI names for EJB YourBean: [java:global/classes/YourBean!bean.package.YourBean, java:global/classes/YourBean]的消息。这意味着您可以通过调用context.lookup("java:global/classes/YourBean!bean.package.YourBean")或较短的名称context.lookup("java:global/classes/YourBean")来查找bean,如果没有名称冲突,则可以很有用。

希望这对某人有所帮助。如果有这些提示将会非常有用。


2

我现在也在学习同一章节。我发现你的博客文章非常有帮助。谢谢你。 - b3bop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接