OpenJPA 与 Glassfish 配合得很好吗?
有人成功地将 OpenJPA 与 Glassfish 结合使用吗?
我正在尝试将 OpenJPA 2.1 与 Glassfish 3.1 开源一起使用。我已按照此处的说明将两者集成 -> http://weblogs.java.net/blog/ss141213/archive /2006/07/using_openjpa_a.html
我在 Eclipse Indigo 中有一个非常简单的 EJB 项目,其中包含以下内容:
- com.rares.test.Person - @Entity
- com.rares.test.PersonManager - 接口
- com.rares.test.PersonDao - @Stateless
但是,当我尝试部署时,我的 Person @Entity 上出现了 ClassNotFoundException。投诉似乎是在我的 PersonDao 中实现的创建方法上的 Person 参数(请参阅下面的所有代码)。
我尝试过相同的项目,但没有在 persistence.xml 中指定提供程序,并且该项目工作正常(能够将 Person @Entity 持久保存到 MySql 中的 PERSON 表)。如果我不指定提供程序,我认为我正在使用 EclipseLink(如果我错了,请纠正我)。这让我相信我没有正确配置 Glassfish 的 OpenJPA。
堆栈跟踪
Caused by: java.lang.IllegalArgumentException: java.lang.ClassNotFoundException: com.rares.test.Person
at serp.util.Strings.toClass(Strings.java:164)
at serp.util.Strings.toClass(Strings.java:108)
at serp.bytecode.BCClass.getType(BCClass.java:566)
at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:283)
at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:254)
at org.apache.openjpa.enhance.PCClassFileTransformer.transform0(PCClassFileTransformer.java:144)
at org.apache.openjpa.enhance.PCClassFileTransformer.transform(PCClassFileTransformer.java:124)
at org.apache.openjpa.persistence.PersistenceProviderImpl$ClassTransformerImpl.transform(PersistenceProviderImpl.java:294)
at org.glassfish.persistence.jpa.ServerProviderContainerContractInfo$1.transform(ServerProviderContainerContractInfo.java:98)
at com.sun.enterprise.loader.ASURLClassLoader.findClass(ASURLClassLoader.java:742)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
at java.lang.Class.privateGetPublicMethods(Class.java:2547)
at java.lang.Class.getMethods(Class.java:1410)
at com.sun.enterprise.deployment.EjbDescriptor.addAllInterfaceMethodsIn(EjbDescriptor.java:2327)
at com.sun.enterprise.deployment.EjbDescriptor.getLocalRemoteBusinessMethodDescriptors(EjbDescriptor.java:2290)
... 40 more
com.rares.test.Person
@Entity
@Table (name="PERSON")
public class Person implements Serializable {
private static final long serialVersionUID = 3707476467775531463L;
@Id
@GeneratedValue (strategy=GenerationType.IDENTITY)
@Column private Long id;
@Column private String name;
com.rares.test.PersonManager
public interface PersonManager {
void create (com.rares.test.Person p);
}
com.rares.test.PersonDao
@Stateless
public class PersonDao implements PersonManager {
@PersistenceContext (unitName="RarePersistUnit")
protected EntityManager mgr;
@Override
public void create(com.rares.test.Person p) {
mgr.persist(p);
}
}
persistence.xml
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="RarePersistUnit">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>jdbc/RaresMySql</jta-data-source>
<class>com.rares.test.Person</class>
<properties>
</properties>
</persistence-unit>
</persistence>
Is anyone successfully using OpenJPA with Glassfish?
I'm trying to use OpenJPA 2.1 with Glassfish 3.1 Open Source. I've followed the instructions to integrate the two here -> http://weblogs.java.net/blog/ss141213/archive/2006/07/using_openjpa_a.html
I have a very simple EJB project in Eclipse Indigo with the following:
- com.rares.test.Person - @Entity
- com.rares.test.PersonManager - interface
- com.rares.test.PersonDao - @Stateless
However, when I try to deploy I get a ClassNotFoundException on my Person @Entity. The complaint seems to be the Person parm on a create method that's being implemented in my PersonDao (see all code below).
I've tried the same project without specifying a provider in my persistence.xml and the project works fine (able to persist a Person @Entity to a PERSON table in MySql). I think I'm using EclipseLink if I don't specify a provider (please correct me if I'm wrong). This leads me to believe that I haven't configured OpenJPA with Glassfish correctly.
Stack Trace
Caused by: java.lang.IllegalArgumentException: java.lang.ClassNotFoundException: com.rares.test.Person
at serp.util.Strings.toClass(Strings.java:164)
at serp.util.Strings.toClass(Strings.java:108)
at serp.bytecode.BCClass.getType(BCClass.java:566)
at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:283)
at org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:254)
at org.apache.openjpa.enhance.PCClassFileTransformer.transform0(PCClassFileTransformer.java:144)
at org.apache.openjpa.enhance.PCClassFileTransformer.transform(PCClassFileTransformer.java:124)
at org.apache.openjpa.persistence.PersistenceProviderImpl$ClassTransformerImpl.transform(PersistenceProviderImpl.java:294)
at org.glassfish.persistence.jpa.ServerProviderContainerContractInfo$1.transform(ServerProviderContainerContractInfo.java:98)
at com.sun.enterprise.loader.ASURLClassLoader.findClass(ASURLClassLoader.java:742)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
at java.lang.Class.privateGetPublicMethods(Class.java:2547)
at java.lang.Class.getMethods(Class.java:1410)
at com.sun.enterprise.deployment.EjbDescriptor.addAllInterfaceMethodsIn(EjbDescriptor.java:2327)
at com.sun.enterprise.deployment.EjbDescriptor.getLocalRemoteBusinessMethodDescriptors(EjbDescriptor.java:2290)
... 40 more
com.rares.test.Person
@Entity
@Table (name="PERSON")
public class Person implements Serializable {
private static final long serialVersionUID = 3707476467775531463L;
@Id
@GeneratedValue (strategy=GenerationType.IDENTITY)
@Column private Long id;
@Column private String name;
com.rares.test.PersonManager
public interface PersonManager {
void create (com.rares.test.Person p);
}
com.rares.test.PersonDao
@Stateless
public class PersonDao implements PersonManager {
@PersistenceContext (unitName="RarePersistUnit")
protected EntityManager mgr;
@Override
public void create(com.rares.test.Person p) {
mgr.persist(p);
}
}
persistence.xml
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="RarePersistUnit">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>jdbc/RaresMySql</jta-data-source>
<class>com.rares.test.Person</class>
<properties>
</properties>
</persistence-unit>
</persistence>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
注意:以下假设使用 OpenJPA 2.1 和 Glassfish 3.1。两个版本的结果可能会有所不同。
抛出的异常是执行失败的典型情况 OpenJPA 在运行时增强字节码。字节码增强可以在构建时或运行时完成。获得运行时支持的更好选项之一是使用 javaagent,但需要一些奇怪的配置:
java-config
元素下指定额外的jvm-options
元素),${com.sun.aas.installRoot}/modules/glassfish.jar
包含commons-lang-2.4.jar
(我懒得做,因为它会导致非常脆弱的设置)。可以在运行时使用的其他选项非常不稳定,选择使用
Serp
作为字节码增强器是部署时抛出异常的原因。显然,部署时间增强功能无法找到持久性上下文中使用的类,因为使用了不正确的类加载器来定位类。就我而言,GlassfishEarClassLoader
和EarLibClassLoader
类加载器用于在两个单独的调用中加载类,两者都失败并显示以下消息(堆栈跟踪在这里并不重要) :显然,由于某种未知的原因,EJB 的生成类区域在运行时不包含 JPA 实体类,导致在部署时无法找到类。最可能失败的原因是实体类虽然封装在 EJB 模块中,但它们本身可能尚未放置在生成的类目录中;只有带注释的 EJB 类可能被放置在那里。
因此,唯一合理的选择是使用构建时间增强,这是使用 Maven POM 中的以下配置适当完成的:
上述配置源自 使用 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
)显然,将这些 JAR 放在
${com.sun.aas.instanceRoot}/lib
中会导致通过 Maven Glassfish 插件部署应用程序失败。OpenJPA 2.1 发行版中存在的其他 JAR(
geronimo-*
、derby-*
和org.apache.bval*
)由 Glassfish 提供3.1 作为 Java EE 6 SDK、Java DB 实现或 Derby 客户端以及 JSR 303 bean 验证框架(Hibernate Validator)的一部分。Note: The below assumes OpenJPA 2.1 and Glassfish 3.1. Results may vary across versions of both.
The exception thrown is typical of a failure to perform bytecode enchancement at runtime by OpenJPA. Bytecode enhancement can be done at either build time or at runtime. One of the better options available to get runtime support is to use a
javaagent
but requires some kooky configuration in that:javaagent
in the Glassfish domain configuration file (by specifying an additionaljvm-options
element under thejava-config
element),${com.sun.aas.installRoot}/modules/glassfish.jar
to includecommons-lang-2.4.jar
(which I didn't bother doing, as it would have leady to a very fragile setup).Other options that can be used at runtime are quite flaky, and the choice of using
Serp
as the bytecode enhancer is the cause of the exception thrown at deploy time. Apparently, the deploy time enhancement fails to locate the classes used in the persistence context, due to incorrect classloaders being used to locate the classes. In my case, the GlassfishEarClassLoader
andEarLibClassLoader
classloaders were used to load the classes in two separate invocations, with both failing with the following messages (the stack traces are immaterial here):Apparently, for some unknown reason the generated classes area for EJBs did not contain the JPA entity classes at runtime, leading to the failure to locate the classes at deployment. The most possible reason for failure, is the fact that the entity classes although packaged within the EJB module, may themselves not have been placed in the generated classes directory; only the annotated EJB classes may have been placed there.
The only reasonable option is to therefore use build time enhancement, which was duly done using the following configuration in the Maven POM:
The above configuration was derived from the OpenJPA documentation on enhancing classes with Maven. Note that I did not use the
openjpa-maven-plugin
, as version 2.2.0 of OpenJPA is available only as a snapshot at the time of writing this.Of course, any of the above also required installation of OpenJPA 2.1 in Glassfish 3.1, which was duly done by copying the following JARs to
${com.sun.aas.installRoot}/glassfish/lib
(for instance,C:/glassfishv3/glassfish/lib
), as opposed to the advice offered on the older blog posts of copying to${com.sun.aas.instanceRoot}/lib
(for instance,C:/glassfishv3/glassfish/domains/domain1/lib
)Apparently, placing these JARs in
${com.sun.aas.instanceRoot}/lib
lead to a failure to deploy the application by the Maven Glassfish plugin.The other JARs (
geronimo-*
,derby-*
andorg.apache.bval*
) present in the OpenJPA 2.1 distribution are provided by Glassfish 3.1 as part of the Java EE 6 SDK, the Java DB implementation or the Derby client, and within the JSR 303 bean validation framework (Hibernate Validator).