EclipseLink分布式缓存导致空主键,什么?

时间:2014-06-20 18:29:35

标签: java java-ee caching jpa eclipselink

好的,这将是很长的,所以这里是tl;dr:当启用分布式缓存协调时,其中一个应用程序的完整性会慢慢降低并引发一个非常奇怪的异常。修复'是禁用缓存。哪个很烂。请帮助我们在EclipseLink中找到问题,以便我们对其进行修补!

EclipseLink 2.5.1

我们有这些实体:

@MappedSuperclass public abstract class Identifiable implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "id", nullable = false, updatable = false) @GeneratedValue(strategy = GenerationType.IDENTITY) public Integer id; @Version @Column(name = "meta__version") private Integer version; }

@Entity @Table(name = "customers", indexes = { @Index(columnList = "phone_number"), @Index(columnList = "email_address") }) @Cacheable public class Customer extends Identifiable { private static final long serialVersionUID = 1L; @Column(name = "last_name") public String lastName; @Column(name = "first_name") public String firstName; .... }

@Entity @Table(name = "notes", indexes = { @Index(columnList = "customer_id, is_cleared") }) @Cacheable public class Note extends Identifiable { private static final long serialVersionUID = 1L; @ManyToOne @JoinColumn(name = "customer_id") public Customer customer; @ManyToOne @JoinColumn(name = "agent_id") public Agent agent; @Size(min = 1, max = 32767) @Column(name = "text", length = 32767) public String text; @Column(name = "is_cleared") public Boolean isCleared; }

<?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="databunker">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/databunker</jta-data-source>
        <mapping-file>databunker.orm.xml</mapping-file>
        <class>com.mycompany.Customer</class>
        <class>com.mycompany.Note</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
        <properties>
            <!-- un-comment these properties to dump generated SQL -->
            <!-- <property -->
            <!-- name="eclipselink.logging.level.sql" -->
            <!-- value="FINE" /> -->
            <!-- <property -->
            <!-- name="eclipselink.logging.parameters" -->
            <!-- value="true" /> -->
            <property
                name="eclipselink.ddl-generation.output-mode"
                value="database" />
            <property
                name="eclipselink.ddl-generation"
                value="create-or-extend-tables" />
            <property
                name="eclipselink.weaving.changetracking"
                value="false" />
            <property
                name="javax.persistence.query.timeout"
                value="15000" />
            <property
                name="eclipselink.cache.size.default"
                value="10000" />
            <property
                name="eclipselink.cache.coordination.protocol"
                value="jms" />
            <property
                name="eclipselink.cache.coordination.jms.topic"
                value="openejb:Resource/jms/EclipseLinkTopic" />
            <property
                name="eclipselink.cache.coordination.jms.factory"
                value="openejb:Resource/jms/EclipseLinkTopicConnectionFactory" />
            <property
                name="eclipselink.cache.coordination.jms.reuse-topic-publisher"
                value="true" />
            <property
                name="eclipselink.cache.coordination.remove-connection-on-error"
                value="true" />
        </properties>
    </persistence-unit>
</persistence>

我们有两个应用程序。 App1在客户上编写/更新,App2在Notes上编写/更新。它们都使用完全相同的持久单元库jar。运行一段时间后,最终Notes应用程序开始因特定客户对象的堆栈跟踪而失败。重新启动服务器可以解决问题,直到另一个Customer对象开始发生。

[http-apr-8080-exec-1] ERROR c.mycompany.notes.restapi.RestExceptionMapper - toResponse() unexpected exception
javax.transaction.RollbackException: Unable to commit: transaction marked for rollback
at org.apache.geronimo.transaction.manager.TransactionImpl.commit(TransactionImpl.java:272) ~[geronimo-transaction-3.1.1.jar:3.1.1]
at org.apache.geronimo.transaction.manager.TransactionManagerImpl.commit(TransactionManagerImpl.java:252) ~[geronimo-transaction-3.1.1.jar:3.1.1]
at org.apache.openejb.core.transaction.JtaTransactionPolicy.completeTransaction(JtaTransactionPolicy.java:328) ~[openejb-core-4.6.0.1.jar:4.6.0.1]
at org.apache.openejb.core.transaction.TxRequired.commit(TxRequired.java:75) ~[openejb-core-4.6.0.1.jar:4.6.0.1]
at org.apache.openejb.core.transaction.EjbTransactionUtil.afterInvoke(EjbTransactionUtil.java:76) ~[openejb-core-4.6.0.1.jar:4.6.0.1]
at org.apache.openejb.core.stateless.StatelessContainer._invoke(StatelessContainer.java:231) ~[openejb-core-4.6.0.1.jar:4.6.0.1]
at org.apache.openejb.core.stateless.StatelessContainer.invoke(StatelessContainer.java:181) ~[openejb-core-4.6.0.1.jar:4.6.0.1]
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.synchronizedBusinessMethod(EjbObjectProxyHandler.java:268) ~[openejb-core-4.6.0.1.jar:4.6.0.1]
at org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod(EjbObjectProxyHandler.java:263) ~[openejb-core-4.6.0.1.jar:4.6.0.1]
at org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke(EjbObjectProxyHandler.java:86) ~[openejb-core-4.6.0.1.jar:4.6.0.1]
at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:303) ~[openejb-core-4.6.0.1.jar:4.6.0.1]
at com.sun.proxy.$Proxy108.getNotes(Unknown Source) ~[na:na]
at com.mycompany.notes.restapi.NoteTakerController.getNotes(NoteTakerController.java:68) ~[NoteTakerController.class:na]
at com.mycompany.notes.restapi.NoteTakerController$$OwbNormalScopeProxy0.getNotes(com/mycompany/notes/restapi/NoteTakerController.java) ~[na:na]
at sun.reflect.GeneratedMethodAccessor70.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_60]
at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_60]
at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180) ~[cxf-api-2.6.9.jar:2.6.9]
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) ~[cxf-api-2.6.9.jar:2.6.9]
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:165) [cxf-rt-frontend-jaxrs-2.6.9.jar:2.6.9]
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:89) [cxf-rt-frontend-jaxrs-2.6.9.jar:2.6.9]
at org.apache.openejb.server.cxf.rs.AutoJAXRSInvoker.invoke(AutoJAXRSInvoker.java:66) [openejb-cxf-rs-4.6.0.1.jar:4.6.0.1]
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:57) [cxf-api-2.6.9.jar:2.6.9]
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:93) [cxf-api-2.6.9.jar:2.6.9]
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262) [cxf-api-2.6.9.jar:2.6.9]
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) [cxf-api-2.6.9.jar:2.6.9]
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:237) [cxf-rt-transports-http-2.6.9.jar:2.6.9]
at org.apache.openejb.server.cxf.rs.CxfRsHttpListener.onMessage(CxfRsHttpListener.java:170) [openejb-cxf-rs-4.6.0.1.jar:4.6.0.1]
at org.apache.openejb.server.rest.RsServlet.service(RsServlet.java:53) [openejb-rest-4.6.0.1.jar:4.6.0.1]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) [servlet-api.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) [catalina.jar:7.0.53]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.53]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat7-websocket.jar:7.0.53]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.53]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.53]
at com.mycompany.notes.restapi.security.HMACSecurityFilter.doFilter(HMACSecurityFilter.java:79) [HMACSecurityFilter.class:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.53]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.53]
at com.mycompany.cdi.RequestBufferingFilter.doFilter(RequestBufferingFilter.java:50) [java-common-1.0.10.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.53]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.53]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [catalina.jar:7.0.53]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [catalina.jar:7.0.53]
at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:45) [tomee-catalina-1.6.0.1.jar:1.6.0.1]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) [catalina.jar:7.0.53]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) [catalina.jar:7.0.53]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) [catalina.jar:7.0.53]
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) [catalina.jar:7.0.53]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [catalina.jar:7.0.53]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) [catalina.jar:7.0.53]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) [tomcat-coyote.jar:7.0.53]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) [tomcat-coyote.jar:7.0.53]
at org.apache.tomcat.util.net.AprEndpoint$SocketWithOptionsProcessor.run(AprEndpoint.java:2378) [tomcat-coyote.jar:7.0.53]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_60]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_60]
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_60]
Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.5.2.v20131113-a7346c6): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null or zero primary key encountered in unit of work clone [Customer[agent=Agent[agentName=Api User,id=1,version=1],address=Address[streetAddress=somewhere road,city=KANSAS CITY,zipcode=66210,state=State[postalAbbreviation=KS,id=38,version=1],id=298219,version=1],leadStatus=LeadStatus[name=New,id=1,version=1],leadSource=LeadSource[name=IRMS,id=9,version=1],project=Project[campaignName=Outbound59734,id=2,version=1],version=7]], primary key [null]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl$1.handleException(EntityManagerSetupImpl.java:696) ~[eclipselink-2.5.2-M1.jar:2.5.2.v20131113-a7346c6]
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.handleException(AbstractSynchronizationListener.java:275) ~[eclipselink-2.5.2-M1.jar:2.5.2.v20131113-a7346c6]
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:170) ~[eclipselink-2.5.2-M1.jar:2.5.2.v20131113-a7346c6]
at org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:68) ~[eclipselink-2.5.2-M1.jar:2.5.2.v20131113-a7346c6]
at org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion(TransactionImpl.java:527) ~[geronimo-transaction-3.1.1.jar:3.1.1]
at org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion(TransactionImpl.java:511) ~[geronimo-transaction-3.1.1.jar:3.1.1]
at org.apache.geronimo.transaction.manager.TransactionImpl.beforePrepare(TransactionImpl.java:413) ~[geronimo-transaction-3.1.1.jar:3.1.1]
at org.apache.geronimo.transaction.manager.TransactionImpl.commit(TransactionImpl.java:262) ~[geronimo-transaction-3.1.1.jar:3.1.1]
... 55 common frames omitted
Caused by: org.eclipse.persistence.exceptions.ValidationException: 
Exception Description: Null or zero primary key encountered in unit of work clone [Customer[agent=Agent[agentName=Api User,id=1,version=1],address=Address[streetAddress=somewhere road,city=KANSAS CITY,zipcode=66210,state=State[postalAbbreviation=KS,id=38,version=1],id=298219,version=1],leadStatus=LeadStatus[name=New,id=1,version=1],leadSource=LeadSource[name=IRMS,id=9,version=1],project=Project[campaignName=Outbound59734,id=2,version=1],version=7]], primary key [null]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
at org.eclipse.persistence.exceptions.ValidationException.nullPrimaryKeyInUnitOfWorkClone(ValidationException.java:1469) ~[eclipselink-2.5.2-M1.jar:2.5.2.v20131113-a7346c6]
at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChanges(DeferredChangeDetectionPolicy.java:109) ~[eclipselink-2.5.2-M1.jar:2.5.2.v20131113-a7346c6]
at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChangesForExistingObject(DeferredChangeDetectionPolicy.java:56) ~[eclipselink-2.5.2-M1.jar:2.5.2.v20131113-a7346c6]
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:664) ~[eclipselink-2.5.2-M1.jar:2.5.2.v20131113-a7346c6]
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1516) ~[eclipselink-2.5.2-M1.jar:2.5.2.v20131113-a7346c6]
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:3168) ~[eclipselink-2.5.2-M1.jar:2.5.2.v20131113-a7346c6]
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:352) ~[eclipselink-2.5.2-M1.jar:2.5.2.v20131113-a7346c6]
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:158) ~[eclipselink-2.5.2-M1.jar:2.5.2.v20131113-a7346c6]
... 60 common frames omitted

2 个答案:

答案 0 :(得分:3)

Eclipselink默认执行分布式更新。尝试使用@Cache(coordinationType = CacheCoordinationType.INVALIDATE_CHANGED_OBJECTS)

答案 1 :(得分:1)

必须是深埋在EclipseLink内部的错误...禁用其他优化可以解决问题:

 <property
         name="eclipselink.weaving.internal"
         value="false" />

糟糕,