java - 嵌入式 GlassFish 忽略 Maven 测试资源

标签 java jakarta-ee jpa maven glassfish

我已经为几个 session 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 使用正确的持久性单元的任何提示!谢谢!

最佳答案

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

当嵌入式 Glassfish 域准备好部署的分散存档时,要部署的文件通常会复制到一个展开的目录中,该目录包含应用程序所需的所有类(包括所有依赖项)。此目录通常恰好出现在 GF_EMBED_DOMAIN_HOME/applications/<application_name> 中目录。 persistence.xml来自您的 src/main/resources/META-INF 的文件和 src/test/resources/META-INF目录被复制到这里的 <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 项目根目录中(也已 checkin 版本控制); glassfish目录必须包含 domain1/config 的目录结构表示 Glassfish 域名的目录结构 domain1 .项目中的结构可以在下面的屏幕截图中看到。其他相关文件(JDBC 资源适配器 JAR 等)可以从 Glassfish 安装目录中获取,但如果配置正确,通常这些文件也可能由嵌入式 Glassfish 运行时放置在正确位置。

Glassfish domain configuration file location

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


注意:

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

关于java - 嵌入式 GlassFish 忽略 Maven 测试资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6739987/

相关文章:

java - Windows 和 Mac 上的 Android 库项目

java - 我的应用程序在启动时崩溃

jakarta-ee - 可以在 Weblogic 中不同应用程序的 EJB 之间传播事务吗?

java - 持久化 JPA 域对象的良好设计

java - 如何使用 java.nio.ByteBuffer 从 C++ 返回到 Java

java - 死锁时出现奇怪的线程转储

java - JSP Hello 页面错误

java - 聚合根与复合根有何不同?

java - 当 tomcat lib 文件夹中存在 postgre 驱动程序时,为什么 oracle jdbc 上的 hibernate 失败

spring - Spring Data JPA 是 JPA 实现吗?