带有JTA的JPA正在遇到类加载器问题

时间:2014-09-02 16:11:50

标签: java jpa

我正在使用JPA 2.0,eclipselink 2.x和maven。这是我的persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<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="certifications" transaction-type="JTA">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/com/ni/ds_edata_soa_nontx</jta-data-source>
        <class>com.ni.apps.engineering.certification.entities.NicdsCliCertificationStg</class>
        <class>com.ni.apps.engineering.certification.entities.NicdsCliCertificationStgPK</class>
        <class>com.ni.apps.engineering.certification.entities.NicdsCliUpMapping</class>   
        <properties>                        
            <property name="javax.persistence.jdbc.password" value="ni"/>
            <!--property name="javax.persistence.jdbc.user" value="NI"/-->
            <property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
            <property name="eclipselink.logging.level.sql" value="FINE"/>       
        </properties>       
    </persistence-unit>
</persistence>

我有这个AbstractFacade

public abstract class AbstractFacade {

    @PersistenceUnit(unitName = "certifications")
    private static EntityManagerFactory emf;

    private EntityManager em;

    /**
     * Gets the entity manager
     * @return
     */
    protected EntityManager getEntityManager(){
        if(emf == null){
            emf = Persistence.createEntityManagerFactory("certifications");
        }
        if(em == null){
            em = emf.createEntityManager();
        }
        return em;
    }

}

这就是我实现它的方式

public class CertificationFacade extends AbstractFacade{

    /**
     * Gets the certifications for the paramenter upId
     * @param upId the upId
     * @return the certifications
     * @throws CertificationException
     */
    public List<NicdsCliCertificationStg> getCertificationsByUpId(String upId)
            throws CertificationException {
        String stringQuery = new StringBuilder(
                "select c from NicdsCliCertificationStg c, NicdsCliUpMapping d where c.id.contactsId = d.contactsId and d.profileId =")
                .append(upId).toString();
        try {
            TypedQuery<NicdsCliCertificationStg> query = getEntityManager().createQuery(stringQuery,
                    NicdsCliCertificationStg.class);            
            return query.getResultList();
        } catch (Exception e) {
            throw new CertificationException(
                    CertificationConstants.INTERNAL_ERROR_MESSAGE, e);
        }
    }
}

这是DAO

    public final class CertificationDAO {

    private CertificationDAO(){}

    /**
     **Gets the certifications for the requested upId
     * @param upId the upId
     * @return the certifications
     * @throws CertificationException
     */
    public static Certifications getCertificationByUpId(String upId) throws CertificationException{
        Certifications response = new Certifications();
        List<NicdsCliCertificationStg> certifications = new CertificationFacade().getCertificationsByUpId(upId);
        CertificationType newCertification = new CertificationType();
        for(NicdsCliCertificationStg cert : certifications){
            newCertification.setAlternateEmail(cert.getAlternateEmail());
            newCertification.setCertificationName(cert.getId().getCertName());
            newCertification.setContactId((int)cert.getId().getContactsId());
            newCertification.setFirstName(cert.getFirstName());
            newCertification.setLastName(cert.getLastName());
            newCertification.setPrimaryEmail(cert.getPrimaryEmail());
            newCertification.setStatus(cert.getCertStatus());
            response.getCertification().add(newCertification);
        }
        return response;        
    }
}

当我尝试遍历列表时会导致异常。我得到一个ClassCastException。我一直在阅读,这是由两个可能的原因引起的:1)类在类路径中重复(在我的情况下不是这样)和2)同时有2个不同的类加载器。当我将应用程序重新部署到我的weblogic时,也会发生此异常。似乎垃圾收集器没有足够快地回收旧的类加载器,当我运行应用程序时,我同时处理两个类加载器,导致了类转换异常。我不明白的是,因为我在我的persistence.xml中使用JTA事务类型,所以应该自动处理EntityManagerFactory的生命周期。一个选择是自己关闭工厂,但我更感兴趣的是为什么不是JTA为我处理这个问题。谢谢!

- EDIT-- 栈跟踪

java.lang.ClassCastException: com.ni.apps.engineering.certification.entities.NicdsCliCertificationStg
    at com.ni.apps.engineering.certification.dao.CertificationDAO.getCertificationByUpId(CertificationDAO.java:25)
    at com.ni.apps.engineering.certification.rest.implementation.CertificationService.getCertificationByUpId(CertificationService.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60)
    at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:205)
    at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75)
    at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:302)
    at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
    at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)
    at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
    at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1511)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1442)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1391)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1382)
    at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:538)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:717)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:821)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:301)
    at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:27)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:57)
    at com.ni.apps.engineering.certification.filter.ConfigurableRepRestServletFilter.doFilter(ConfigurableRepRestServletFilter.java:139)
    at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:57)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3730)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3696)
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
    at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
    at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2273)
    at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2179)
    at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1490)
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:256)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:221)

1 个答案:

答案 0 :(得分:0)

所以,这是我修复它的方式。

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import com.ni.apps.engineering.certification.controller.AbstractFacade;

public class ApplicationListener implements ServletContextListener {

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        AbstractFacade.closeFactory();
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {

    }

}

这样,每次我重新部署应用程序时,我都会确保已创建的工厂已关闭。

CNC中 为了说清楚,在创建了Listener类之后,我必须像这样添加侦听器到web.xml

<listener>
    <listener-class>com.ni.apps.engineering.certification.filter.ApplicationListener</listener-class>
</listener>

在验证emf不为null之后,closeFactory()只执行emf.close()。