【问题标题】:Does OpenJPA work well with Glassfish?OpenJPA 是否适用于 Glassfish?
【发布时间】:2011-07-17 04:44:18
【问题描述】:

是否有人成功地将 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 中实现的 create 方法的 Person 参数(请参阅下面的所有代码)。

我尝试了同一个项目,但没有在我的 persistence.xml 中指定提供程序,并且该项目运行良好(能够将 Person @Entity 持久保存到 MySql 中的 PERSON 表中)。如果我没有指定提供者,我想我正在使用 EclipseLink(如果我错了,请纠正我)。这让我相信我没有正确配置 OpenJPA 和 Glassfish。

堆栈跟踪

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>

【问题讨论】:

    标签: jpa glassfish ejb openjpa


    【解决方案1】:

    注意:以下假设是 OpenJPA 2.1Glassfish 3.1。结果可能因两个版本而异。

    抛出的异常是 OpenJPA 在运行时未能执行bytecode enchancement 的典型表现。字节码增强可以在构建时或运行时完成。获得运行时支持的更好选择之一是使用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>
    

    以上配置源自enhancing classes with Maven 上的 OpenJPA 文档。请注意,我没有使用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)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-31
      • 2013-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-30
      • 2011-11-09
      相关资源
      最近更新 更多