嵌入式 GlassFish 忽略 Maven 测试资源
我已经为几个会话 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 使用正确的持久性单元的提示!谢谢!
I have several session beans that I have written unit tests for. I have setup Maven to include a persistence.xml in the src/main/resources/META-INF directory that refers to a local MySQL database for development purposes. I have another persistence.xml in src/test/resources/META-INF directory that refers to the embedded Derby database __default. The tests are deployed to an embedded GlassFish 3.1 container.
When I run the tests however, I get the following error:
java.lang.RuntimeException: javax.naming.NamingException: Lookup failed for 'jdbc/mylog'
jdbc/mylog is the MySQL database that the persistence unit in the main directory refers to. It is obviously ignoring the persistence unit in the test directory but I have no clue as to why.
Maven is setting the classpath correctly as far as I can tell, with test-classes before classes and a peek in the actual target/test-classes/META-INF directory reveals that it copied the correct, embedded Derby, persistence unit.
[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
Any hint on how to have GlassFish use the proper persistence unit very much appreciated! Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用嵌入式 Glassfish 运行测试时,JPA 提供程序在执行 maven-surefire-plugin 目标(用于运行测试阶段)之前不使用命令行上显示的类路径。嵌入式 Glassfish 将测试范围内可用的工件部署为
ScatteredArchive
。此分散存档通常在java.io.tmpdir
目录中创建,通常名称为gfembedtmp
,除非嵌入式 Glassfish 配置指定了 Glassfish 安装的位置root 和 Glassfish 域。当嵌入式 Glassfish 域准备好部署的分散存档时,要部署的文件通常会复制到分解目录中,该目录包含应用程序所需的所有类(包括所有依赖项)。此目录通常恰好出现在
GF_EMBED_DOMAIN_HOME/applications/
目录中。复制src/main/resources/META-INF
和src/test/resources/META-INF
目录中的persistence.xml
文件进入/META-INF
目录。不用说,最后复制的那个或者没有被覆盖的那个是 JPA 提供者在测试期间使用的那个。这总是恰好是 src/main/resources/META-INF 中的文件。您可以通过两种方式克服这种情况:
1.使用自定义 Glassfish 域配置文件
您可以指定一个域配置文件 (
domain.xml
),其中将包含jdbc/mylog
的数据源定义。这就是我目前所做的,因为它非常灵活,并且域配置文件也可以包含其他配置。配置文件需要通过以下方式指定为测试设置的一部分:上述
glassfish-install
目录及其子目录glassfish
存在于 Maven 中项目根目录(也签入版本控制);glassfish
目录必须包含domain1/config
目录结构,以表示名称为domain1
的 Glassfish 域的目录结构。项目中的结构可以在下面的屏幕截图中看到。其他相关文件(JDBC 资源适配器 JAR 等)可以从 Glassfish 安装目录获取,但如果配置正确,通常这些文件也可能由嵌入式 Glassfish 运行时放置在正确的位置。Glassfish 域配置文件的内容与嵌入式 Glassfish 使用的默认内容不同,除了数据源和连接池配置(在我执行集成测试的用例中添加的相关条目已发布在下面):
默认的domain.xml 文件可以从java.net 站点下载并进行修改(如果您希望尽可能减少更改),而不是从Glassfish 安装中复制文件。
2.复制 persistence.xml 文件
可以将目标添加到 Maven POM 文件,以从 src/test/resources/META-INF 备份和复制 persistence.xml 文件 到
src/main/resources/META-INF
,在test
阶段之前。测试阶段完成后,将恢复原始状态。我不会详细介绍这一点,因为 相关的 StackOverflow 问题。我没有使用这种方法进行集成测试,因为我需要进行的更改超出了 persistence.xml 中可以携带的更改,例如创建自定义领域。然而,我将它用于单元测试,因为 JPA 提供程序将从target/classes
而不是target/test 获取
,尽管后者在类路径顺序中首先出现。如果您使用 Hibernate 作为 JPA 提供程序,为persistence.xml
文件-classesorg.hibernate.ejb
记录器启用 TRACE 日志记录(因为Ejb3Configuration
类负责执行查找)将使您确信test-classes
中的文件将不会被选取。注意:
大部分答案都假设 Glassfish 3.1,但也可能适用于即将推出的版本。
When running tests using embedded Glassfish, the JPA provider does not use the classpath displayed on the command-line, before executing the maven-surefire-plugin goal (that is used to run the test phase). Embedded Glassfish deploys the artifacts that are available as part of a test scope, as a
ScatteredArchive
. This scattered archive is typically created in thejava.io.tmpdir
directory usually with the namegfembed<a_random_number>tmp
, unless the embedded Glassfish configuration specified the location of a Glassfish installation root, and a Glassfish domain.When the embedded Glassfish domain is prepared with the deployed scattered archive, the files to be deployed are typically copied into an exploded directory that houses all the classes (including all dependencies) required by the application. This directory typically happens to be present in the
GF_EMBED_DOMAIN_HOME/applications/<application_name>
directory. Thepersistence.xml
files from yoursrc/main/resources/META-INF
andsrc/test/resources/META-INF
directories are copied here into the<application-name>/META-INF
directory. Needless to state, the one that gets copied last, or the one that doesn't get overwritten is the one that is used by the JPA provider during the tests. This always happens to be the file insrc/main/resources/META-INF
.You can overcome this situation in two ways:
1. Using a custom Glassfish domain configuration file
You can specify a domain configuration file (
domain.xml
) that will contain the datasource definition forjdbc/mylog
. This is what I do currently for it is very flexible and the domain configuration file can contain other configurations as well. The config file, needs to specified as part of test setup in the following way:The afore-mentioned
glassfish-install
directory and its sub-directoryglassfish
are present in the Maven project root (and also checked into version control); theglassfish
directory must contain a directory structure ofdomain1/config
to represent the directory structure of the Glassfish domain of namedomain1
. The structure in the project can be seen in the below screenshot. The other related files (the JDBC resource adapter JARs and the like), can be obtained from a Glassfish installation directory, but typically these might also be placed in the correct location by the embedded Glassfish runtime, if configured correctly.The contents of the Glassfish domain configuration file are different from the default one used by embedded Glassfish, except for the datasource and connection pool configuration (the relevant entries added in my usecase where I perform integration tests, have been posted below):
The default domain.xml file can be downloaded from the java.net site, and modified, in the event you wish to keep the changes as minimal as possible, instead of copying one from a Glassfish installation.
2. Copying over the persistence.xml files
One can add goals to the Maven POM file, to backup and copy the
persistence.xml
file fromsrc/test/resources/META-INF
tosrc/main/resources/META-INF
, before thetest
phase. After the test phase is complete, the original is restored. I will not go into details of this, as a similar solution is already discussed in a related StackOverflow question. I did not use this approach for integration tests as I required changes to be done beyond the ones that can be carried inpersistence.xml
, like creation of a custom realm. I use it for unit-tests however, due to the fact that the JPA provider will fetch thepersistence.xml
file fromtarget/classes
instead oftarget/test-classes
, despite the latter appearing first in the classpath order. If you use Hibernate as your JPA provider, enabling TRACE logging for theorg.hibernate.ejb
logger (as theEjb3Configuration
class is responsible for performing the lookup) would convince you that file intest-classes
will not be picked up.Note:
Most of the answer assumes Glassfish 3.1 but may hold good for upcoming versions as well.
“嵌入式 glassfish 容器”是指为您运行 glassfish 的 Maven 插件吗? Maven 插件的类路径与 Maven 测试类路径不同且管理方式不同。您可能需要使用不同的类路径。
By "embedded glassfish container", do you mean a maven plugin that runs glassfish for you? The classpath for a maven plugin is different and managed differently than the maven test classpath. You might need to be working with a different classpath.
这个答案可能听起来很愚蠢,但我一直在寻找一种方法,让我可以通过
Run As
-> 从 Eclipse 运行这些测试。JUnit 测试
。这就是我的制作方法:我只是将 test/persistence.xml 复制到classes/persistence.xml。这有效。
This answer might sounds silly but I was looking for a way which lets me run those tests from eclipse by
Run As
->JUnit Test
. This is how I made it:I'm just copying the test/persistence.xml to classes/persistence.xml. This works.