注:以下假设OpenJPA 2.1 and 玻璃鱼3.1。两个版本的结果可能会有所不同。
抛出的异常是典型的执行失败字节码增强在运行时由 OpenJPA 执行。字节码增强可以在构建时或运行时完成。获得运行时支持的更好选择之一是使用javaagent
但需要一些奇怪的配置:
- 它要求您指定一个
javaagent
在 Glassfish 域配置文件中(通过指定附加的jvm-options
下的元素java-config
元素),
- 并修改类路径的默认值
${com.sun.aas.installRoot}/modules/glassfish.jar
包括commons-lang-2.4.jar
(我懒得这样做,因为这会导致一个非常脆弱的设置)。
其他可以在运行时使用的选项非常不稳定,并且选择使用Serp
因为字节码增强器是部署时抛出异常的原因。显然,部署时间增强无法找到持久性上下文中使用的类,因为使用了不正确的类加载器来定位类。就我而言,玻璃鱼EarClassLoader
and EarLibClassLoader
类加载器用于在两次单独的调用中加载类,两次调用都失败并显示以下消息(堆栈跟踪在这里并不重要):
WARNING: LDR5207: ASURLClassLoader EarLibClassLoader :
doneCalled = true
doneSnapshot = ASURLClassLoader.done() called ON EarLibClassLoader :
urlSet = []
doneCalled = false
Parent -> org.glassfish.internal.api.DelegatingClassLoader@10e3c8c
AT Sun Jul 17 13:27:54 IST 2011
BY :java.lang.Throwable: printStackTraceToString
at com.sun.enterprise.util.Print.printStackTraceToString(Print.java:639)
at com.sun.enterprise.loader.ASURLClassLoader.done(ASURLClassLoader.java:211)
...
...
WARNING: LDR5207: ASURLClassLoader EarClassLoader :
doneCalled = true
doneSnapshot = ASURLClassLoader.done() called ON EarClassLoader :
urlSet = [URLEntry : file:/C:/glassfish3/glassfish/domains/domain1/eclipseApps/app-ear/app-jsf-0.0.1-SNAPSHOT_war/WEB-INF/classes/, URLEntry : file:/C:/glassfish3/glassfish/domains/domain1/eclipseApps/app-ear/app-jsf-0.0.1-SNAPSHOT_war/WEB-INF/lib/commons-fileupload-1.2.1.jar, URLEntry : file:/C:/glassfish3/glassfish/domains/domain1/eclipseApps/app-ear/app-jsf-0.0.1-SNAPSHOT_war/WEB-INF/lib/commons-io-1.4.jar, URLEntry : file:/C:/glassfish3/glassfish/domains/domain1/eclipseApps/app-ear/app-jsf-0.0.1-SNAPSHOT_war/WEB-INF/lib/primefaces-3.0.M2.jar, URLEntry : file:/C:/glassfish3/glassfish/domains/domain1/generated/ejb/app-ear/app-jsf-0.0.1-SNAPSHOT_war/, URLEntry : file:/C:/glassfish3/glassfish/domains/domain1/eclipseApps/app-ear/app-ejb-0.0.1-SNAPSHOT_jar/, URLEntry : file:/C:/glassfish3/glassfish/domains/domain1/generated/ejb/app-ear/app-ejb-0.0.1-SNAPSHOT_jar]
doneCalled = false
Parent -> org.glassfish.internal.api.DelegatingClassLoader@1a3fe65
AT Sun Jul 17 13:27:54 IST 2011
BY :java.lang.Throwable: printStackTraceToString
at com.sun.enterprise.util.Print.printStackTraceToString(Print.java:639)
at com.sun.enterprise.loader.ASURLClassLoader.done(ASURLClassLoader.java:211)
...
...
显然,由于某种未知的原因,EJB 生成的类区域在运行时不包含 JPA 实体类,导致在部署时无法找到这些类。最可能失败的原因是实体类虽然封装在 EJB 模块中,但它们本身可能尚未放置在生成的类目录中;只有带注释的 EJB 类可能被放置在那里。
因此,唯一合理的选择是使用构建时间增强,这是使用 Maven POM 中的以下配置适当完成的:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>process-classes</phase>
<configuration>
<tasks>
<taskdef name="openjpac" classname="org.apache.openjpa.ant.PCEnhancerTask" classpathref="maven.compile.classpath"/>
<openjpac>
<classpath refid="maven.compile.classpath"/>
</openjpac>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
上述配置源自 OpenJPA 文档使用 Maven 增强类。请注意,我没有使用openjpa-maven-plugin
,因为在撰写本文时,OpenJPA 2.2.0 版本仅作为快照提供。
当然,上述任何一个都需要在 Glassfish 3.1 中安装 OpenJPA 2.1,这是通过将以下 JAR 复制到${com.sun.aas.installRoot}/glassfish/lib
(例如,C:/glassfishv3/glassfish/lib
),而不是旧博客文章中提供的复制到的建议${com.sun.aas.instanceRoot}/lib
(例如,C:/glassfishv3/glassfish/domains/domain1/lib
)
- commons-beanutils-1.8.3.jar
- commons-collections-3.2.1.jar
- commons-dbcp-1.4.jar
- commons-lang-2.4.jar
- commons-logging-1.0.4.jar
- commons-pool-1.5.4.jar
- serp-1.13.1.jar
- openjpa-2.1.0.jar
显然,将这些 JAR 放入${com.sun.aas.instanceRoot}/lib
导致 Maven Glassfish 插件部署应用程序失败。
其他 JAR(geronimo-*
, derby-*
and org.apache.bval*
)存在于 OpenJPA 2.1 发行版中,由 Glassfish 3.1 作为 Java EE 6 SDK、Java DB 实现或 Derby 客户端的一部分提供,并且位于 JSR 303 bean 验证框架(Hibernate Validator)内。