【问题标题】:Embedded GlassFish ignores Maven test resources嵌入式 GlassFish 忽略 Maven 测试资源
【发布时间】:2011-10-08 01:45:42
【问题描述】:

我有几个会话 bean,我已经为其编写了单元测试。我已将 Maven 设置为在 src/main/resources/META-INF 目录中包含一个 persistence.xml,该目录引用本地 MySQL 数据库以用于开发目的。我在 src/test/resources/META-INF 目录中有另一个 persistence.xml,它引用了嵌入式 Derby 数据库 __default。测试部署到嵌入式 GlassFish 3.1 容器。

但是,当我运行测试时,我收到以下错误:

java.lang.RuntimeException: javax.naming.NamingException: Lookup failed for 'jdbc/mylog' 

jdbc/mylog 是主目录中的持久化单元所引用的 MySQL 数据库。它显然忽略了测试目录中的持久性单元,但我不知道为什么。

据我所知,Maven 正在正确设置类路径,在类之前使用测试类,并且在实际的 target/test-classes/META-INF 目录中一瞥表明它复制了正确的嵌入式 Derby 持久性单元.

[DEBUG] Test Classpath :
[DEBUG]   C:\Users\Laurens\Documents\Projects\Mylog\target\test-classes
[DEBUG]   C:\Users\Laurens\Documents\Projects\Mylog\target\classes
[DEBUG]   C:\Users\Laurens\.m2\repository\org\eclipse\persistence\eclipselink\2.2.0\eclipselink-2.2.0.jar
[DEBUG]   C:\Users\Laurens\.m2\repository\org\eclipse\persistence\javax.persistence\2.0.3\javax.persistence-2.0.3.jar
[DEBUG]   C:\Users\Laurens\.m2\repository\org\eclipse\persistence\org.eclipse.persistence.jpa.modelgen.processor\2.2.0\org.eclipse.persistence.jpa.modelgen.processor-2.2.0.jar
[DEBUG]   C:\Users\Laurens\.m2\repository\org\glassfish\extras\glassfish-embedded-all\3.1\glassfish-embedded-all-3.1.jar
[DEBUG]   C:\Users\Laurens\.m2\repository\javax\javaee-web-api\6.0\javaee-web-api-6.0.jar
[DEBUG]   C:\Users\Laurens\.m2\repository\junit\junit\4.8.1\junit-4.8.1.jar

非常感谢任何有关如何让 GlassFish 使用适当的持久性单元的提示!谢谢!

【问题讨论】:

  • 我在不同的架构条件下遇到了类似的问题,而肮脏的解决方案是将persistente单元,生产和测试合并到一个persistence.xml中。

标签: java jakarta-ee jpa maven glassfish


【解决方案1】:

使用嵌入式 Glassfish 运行测试时,JPA 提供程序在执行 maven-surefire-plugin 目标(用于运行测试阶段)之前不使用命令行上显示的类路径。 Embedded Glassfish 将作为测试范围的一部分可用的工件部署为ScatteredArchive。这个分散的存档通常创建在 java.io.tmpdir 目录中,通常名称为 gfembed<a_random_number>tmp,除非嵌入式 Glassfish 配置指定了 Glassfish 安装根目录和 Glassfish 域的位置。

当嵌入式 Glassfish 域准备好已部署的分散存档时,要部署的文件通常会复制到一个展开的目录中,该目录包含应用程序所需的所有类(包括所有依赖项)。该目录通常恰好出现在GF_EMBED_DOMAIN_HOME/applications/<application_name> 目录中。您的src/main/resources/META-INFsrc/test/resources/META-INF 目录中的persistence.xml 文件在此处复制到<application-name>/META-INF 目录中。不用说,最后被复制的那个,或者没有被覆盖的那个是 JPA 提供者在测试期间使用的那个。这总是恰好是src/main/resources/META-INF 中的文件。

您可以通过两种方式克服这种情况:

1.使用自定义 Glassfish 域配置文件

您可以指定一个域配置文件 (domain.xml),其中将包含 jdbc/mylog 的数据源定义。这是我目前所做的,因为它非常灵活,域配置文件也可以包含其他配置。配置文件,需要通过以下方式指定为测试设置的一部分:

Map<String, Object> props = new HashMap<String, Object>();
props.put("org.glassfish.ejb.embedded.glassfish.installation.root", "./glassfish-install/glassfish");
container = EJBContainer.createEJBContainer(props);
context = container.getContext();
datasource = (DataSource) context.lookup("jdbc/mylog"); //You can lookup the datasource too, to confirm that your setup is successful.

上述glassfish-install 目录及其子目录glassfish 存在于Maven 项目根目录中(并且也已签入版本控制); glassfish 目录必须包含 domain1/config 的目录结构,以表示名称为 domain1 的 Glassfish 域的目录结构。项目中的结构可以在下面的屏幕截图中看到。其他相关文件(JDBC 资源适配器 JAR 等)可以从 Glassfish 安装目录中获得,但如果配置正确,通常这些文件也可能由嵌入式 Glassfish 运行时放置在正确的位置。

Glassfish 域配置文件的内容与嵌入式 Glassfish 使用的默认配置文件不同,除了数据源和连接池配置(在我执行集成测试的用例中添加的相关条目已在下面发布):

<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="MyPool" jndi-name="jdbc/mylog"/>
    ...
    <jdbc-connection-pool driver-classname="" datasource-classname="org.apache.derby.jdbc.ClientDataSource" res-type="javax.sql.DataSource" description="" name="MyPool" ping="true">
      <property name="User" value="APP"></property>
      <property name="RetrieveMessageText" value="true"></property>
      <property name="CreateDatabase" value="true"></property>
      <property name="ServerName" value="localhost"></property>
      <property name="Ssl" value="off"></property>
      <property name="SecurityMechanism" value="4"></property>
      <property name="TraceFileAppend" value="false"></property>
      <property name="TraceLevel" value="-1"></property>
      <property name="PortNumber" value="1527"></property>
      <property name="LoginTimeout" value="0"></property>
      <property name="Password" value="APP"></property>
      <property name="databaseName" value="MYDB"></property>
    </jdbc-connection-pool>
    ...
  </resources>
  <servers>
    <server name="server" config-ref="server-config"> 
      <resource-ref ref="jdbc/__TimerPool"/>
      <resource-ref ref="jdbc/__default"/>
      <resource-ref ref="jdbc/mylog"/>
    </server>
  </servers>
  ...
...

default domain.xml file can be downloaded from the java.net site 已修改,如果您希望尽可能减少更改,而不是从 Glassfish 安装中复制一个。

2。复制 persistence.xml 文件

可以在 Maven POM 文件中添加目标,在test 阶段之前将persistence.xml 文件从src/test/resources/META-INF 备份和复制到src/main/resources/META-INF。测试阶段完成后,恢复原件。我不会对此进行详细介绍,因为a related StackOverflow question 已经讨论了类似的解决方案。我没有将这种方法用于集成测试,因为我需要在persistence.xml 中进行的更改之外进行更改,例如创建自定义领域。然而,我将它用于单元测试,因为 JPA 提供程序将从 target/classes 而不是 target/test-classes 获取 persistence.xml 文件,尽管后者首先出现在类路径顺序中。如果您使用 Hibernate 作为您的 JPA 提供程序,为 org.hibernate.ejb 记录器启用 TRACE 日志记录(因为 Ejb3Configuration 类负责执行查找)将使您确信 test-classes 中的文件不会被拾取。


注意:

大部分答案都假设 Glassfish 3.1,但也可能适用于即将推出的版本。

【讨论】:

  • 哇,这是非常详细的 Vineet!我选择了最灵活的选项一,它现在可以完美运行。谢谢一百万!
  • @Laurens,好吧,很高兴知道它有帮助。
  • 很好的答案,Vineet。升级到 3.1.2 后,嵌入式 Glassfish 停止为我工作,但在按照您在此处解释的操作后,我设法让它再次工作。谢谢!
【解决方案2】:

“嵌入式 glassfish 容器”是指为您运行 glassfish 的 maven 插件吗? maven 插件的类路径与 maven 测试类路径不同,管理方式也不同。您可能需要使用不同的类路径。

【讨论】:

  • 嗨瑞恩,感谢您的快速响应!我没有使用插件。我的 POM 中有 glassfish-embedded-all-3.1 作为测试范围的依赖项。
  • @Laurens:所以您的测试类是在运行测试的同一 JVM 中启动 glassfish?我对GF不熟悉,但是您所描述的确实是错误的。你能提供一个小的、可执行的问题示例吗?
  • 是的。我的印象是,这就是使用嵌入式 GlassFish 进行单元测试的全部意义所在,因此您无需在构建服务器上进行完整安装。我设法使用 Vineets 的建议让事情顺利进行。非常感谢!
【解决方案3】:

这个答案可能听起来很傻,但我正在寻找一种方法,让我通过 Run As -> JUnit Test 从 eclipse 运行这些测试。我就是这样做的:

@BeforeClass
public static void setUp() throws IOException {
    Files.copy(new File("target/test-classes/META-INF/persistence.xml"), new File("target/classes/META-INF/persistence.xml"));
    // ...
}

我只是将 test/persistence.xml 复制到 classes/persistence.xml。这行得通。

【讨论】:

    猜你喜欢
    • 2011-08-06
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 1970-01-01
    • 1970-01-01
    • 2016-02-14
    相关资源
    最近更新 更多