【问题标题】:Java EE 6 - Embedded container EJB testsJava EE 6 - 嵌入式容器 EJB 测试
【发布时间】:2011-04-25 16:46:18
【问题描述】:

这个问题是关于 Java EE 6,使用 glassfish v3 embedded-all。

我有一个单元测试,它使用 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

我尝试了几种JNDI资源路径:

例如

java:global/BookServiceEJB

java:global/BookService

甚至:

java:global/BookShelf-1.0-SNAPSHOT/BookServiceEJB

等等……

没有用

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

测试使用的是maven surefire:

mvn clean test

非常感谢任何帮助!

注意:可以完全部署到 Glassfish 服务器(使用 appclient 和 @EJB 注入)

【问题讨论】:

  • 注意:完全部署到 Glassfish 服务器工作(使用 appclient 和 @EJB 注入)

标签: jakarta-ee jndi java-ee-6 glassfish-3 glassfish-embedded


【解决方案1】:

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

您必须使用属性配置 EJBContainer:EJBContainer.MODULES,以及模块类所在的位置(如果使用 maven,则为“target/classes”)。

例如

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

如果您的 EJB 使用 JPA,还有一个问题是您将无法在嵌入式容器中定义数据源,因此必须使用默认 ds: '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),而我的应用程序使用另一个(例如 jdbc/booksDS)

见:http://www.mentby.com/glassfish/embedded-testing-woes.html

见:http://forums.java.net/jive/thread.jspa?messageID=395759

说实话,当像 spring 这样的解决方案如此简单时,我不知道为什么人们会为 Java EE 烦恼...

这非常令人沮丧并且浪费了很多时间......希望这会有所帮助。

【讨论】:

  • 此外,JNDI 名称将采用以下格式:'java:global/classes/EJBClass!com.fully.qualified.remote.EJBRemoteInterface' - 即 jndi 中没有应用程序/模块组件字符串。
  • 在 persistence.xml 中定义 jta-data-source 后,我也收到一个错误... 内部异常:java.sql.SQLException:分配连接时出错。原因:无法分配连接,因为:java.net.ConnectException:连接到端口 1527 上的服务器 localhost 时出错,消息连接被拒绝:连接。错误代码:org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:309) 处为 0
【解决方案2】:

您需要检查一些项目,以确保您可以通过 context.lookup 加载 bean,避免 NamingException。

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

  2. 正如@Dzhu 指出的那样,在创建容器时添加模块。对于 maven classes 将是 target/classes,对于 maven tests 将是 target/测试类。

  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,如果没有名称冲突,这将很有用。

希望这对某人有所帮助。拥有这些提示会非常有帮助。

【讨论】:

    【解决方案3】:

    我写了一个关于使用嵌入式 glassfish 3.1 容器的小教程,还解决了需要不同的 persistence.xml 进行测试的问题。还使用远程接口和 Web 服务修复容器崩溃。你可以在http://pschyska.blogspot.com/2011/06/unit-testing-ejb-31-with-netbeans-maven.html查看它

    【讨论】:

    • 我现在正在完成同一章。我发现你的博客条目非常有帮助。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2015-07-22
    • 2011-06-28
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    • 2011-01-02
    • 2010-10-05
    • 1970-01-01
    相关资源
    最近更新 更多