OpenJPA 与 Glassfish 配合得很好吗?

发布于 2024-11-24 00:54:29 字数 3868 浏览 2 评论 0原文

有人成功地将 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

澉约 2024-12-01 00:54:29

注意:以下假设使用 OpenJPA 2.1Glassfish 3.1。两个版本的结果可能会有所不同。

抛出的异常是执行失败的典型情况 OpenJPA 在运行时增强字节码。字节码增强可以在构建时或运行时完成。获得运行时支持的更好选项之一是使用 javaagent,但需要一些奇怪的配置:

  • 它要求您在 Glassfish 域配置文件中指定 javaagent (通过在 java-config 元素下指定额外的 jvm-options 元素),
  • 并修改类路径的默认值${com.sun.aas.installRoot}/modules/glassfish.jar 包含 commons-lang-2.4.jar (我懒得做,因为它会导致非常脆弱的设置)。

可以在运行时使用的其他选项非常不稳定,选择使用 Serp 作为字节码增强器是部署时抛出异常的原因。显然,部署时间增强功能无法找到持久性上下文中使用的类,因为使用了不正确的类加载器来定位类。就我而言,Glassfish EarClassLoaderEarLibClassLoader 类加载器用于在两个单独的调用中加载类,两者都失败并显示以下消息(堆栈跟踪在这里并不重要) :

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>

上述配置源自 使用 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 插件部署应用程序失败。

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:

  • it requires you to specify a javaagent in the Glassfish domain configuration file (by specifying an additional jvm-options element under the java-config element),
  • and also modify the classpath from the default value of ${com.sun.aas.installRoot}/modules/glassfish.jar to include commons-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 Glassfish EarClassLoader and EarLibClassLoader classloaders were used to load the classes in two separate invocations, with both failing with the following messages (the stack traces are immaterial here):

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

...

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:

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

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)

  • 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

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-* and org.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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文