嵌入式GlassFish会忽略Maven测试资源 [英] Embedded GlassFish ignores Maven test resources

查看:127
本文介绍了嵌入式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:'jdbc / mylog'的查找失败

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



Maven正如我所知道的那样正确地设置类路径,并通过测试在类和实际的目标/测试类/ 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\.m 2\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将作为测试范围一部分提供的构件部署为 ScatteredArchive 。这个分散的文档通常是在 java.io.tmpdir 目录中创建的,通常名称为 gfembed< a_random_number> tmp ,除非嵌入的Glassfish配置指定了Glassfish安装根目录和Glassfish域的位置。


$ b 当嵌入的Glassfish域使用部署的分散存档准备时,通常会被复制到一个展开目录中,该目录包含应用程序所需的所有类(包括所有依赖项)。此目录通常恰好存在于 GF_EMBED_DOMAIN_HOME / applications /< application_name> 目录中。您的 src / main / resources / META-INF src中的 persistence.xml 文件/ 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(道具);
context = container.getContext();
datasource =(DataSource)context.lookup(jdbc / mylog); //你也可以查找数据源,以确认你的设置是否成功。

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





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

 < domain log-root =$ {com.sun.aas.instanceRoot} / logsapplication- root =$ {com.sun.aas.instanceRoot} / applicationsversion =10.0> 
< system-applications />
< applications />
<资源>
...
< property name =Uservalue =APP>< / property>
< property name =RetrieveMessageTextvalue =true>< / property>
< property name =ServerNamevalue =localhost>< / property>
< property name =SecurityMechanismvalue =4>< / property>
< property name =TraceFileAppendvalue =false>< / property>
< property name =TraceLevelvalue = - 1>< / property>
< property name =Passwordvalue =APP>< / property>
< property name =databaseNamevalue =MYDB>< / property>
< / jdbc-connection-pool>
...
< /资源>
<服务器>
< server name =serverconfig-ref =server-config>
< resource-ref ref =jdbc / __ TimerPool/>
< resource-ref ref =jdbc / __ default/>
< resource-ref ref =jdbc / mylog/>
< / server>
< /服务器>
...
...

默认的domain.xml文件可以从java.net网站下载并修改,如果您希望保持更改尽可能最小化,而不是从Glassfish安装中复制一个。



2。通过persistence.xml文件复制



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






注意:

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

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!

解决方案

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 the java.io.tmpdir directory usually with the name gfembed<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. The persistence.xml files from your src/main/resources/META-INF and src/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 in src/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 for jdbc/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:

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.

The afore-mentioned glassfish-install directory and its sub-directory glassfish are present in the Maven project root (and also checked into version control); the glassfish directory must contain a directory structure of domain1/config to represent the directory structure of the Glassfish domain of name domain1. 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):

<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>
  ...
...

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 from src/test/resources/META-INF to src/main/resources/META-INF, before the test 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 in persistence.xml, like creation of a custom realm. I use it for unit-tests however, due to the fact that the JPA provider will fetch the persistence.xml file from target/classes instead of target/test-classes, despite the latter appearing first in the classpath order. If you use Hibernate as your JPA provider, enabling TRACE logging for the org.hibernate.ejb logger (as the Ejb3Configuration class is responsible for performing the lookup) would convince you that file in test-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会忽略Maven测试资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆