这是我的拦截器类
public class AuditInterceptor extends EmptyInterceptor {
private static final long serialVersionUID = 1L;
private Set<Auditable> inserts = new HashSet<>();
private Set<Auditable> updates = new HashSet<>();
private Set<Auditable> deletes = new HashSet<>();
// @PrePersist
// public void doPrePersist(final Auditable entity) {
// if (entity.isAudited()) {
// logIt("Create", entity);
// }
// }
//
// @PreUpdate
// public void doPreUpdate(final Auditable entity) {
// if (entity.isAudited()) {
// logIt("Update", entity);
// }
// }
//
// @PreRemove
// public void doPreRemove(final Auditable entity) {
// if (entity.isAudited()) {
// logIt("Delete", entity);
// }
// }
//
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
throws CallbackException {
if (entity instanceof Auditable && ((Auditable)entity).isAudited()){
inserts.add((Auditable)entity);
}
return super.onSave(entity, id, state, propertyNames, types);
}
@Override
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types)
throws CallbackException {
if (entity instanceof Auditable && ((Auditable)entity).isAudited()){
updates.add((Auditable)entity);
}
return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);
}
@Override
public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
if (entity instanceof Auditable && ((Auditable)entity).isAudited()){
deletes.add((Auditable)entity);
}
}
//called before commit into database
@Override
public void preFlush(Iterator iterator) {
}
//called after committed into database
@Override
public void postFlush(Iterator iterator) {
try {
for (Auditable entity : inserts) {
logIt("Saved", entity);
}
for (Auditable entity : updates) {
logIt("Updated", entity); // This is getting called multiple times
}
for (Auditable entity : deletes) {
logIt("Deleted", entity);
}
} finally {
inserts.clear();
updates.clear();
deletes.clear();
}
}
public void logIt(String action, Auditable entity) {
if (!entity.isAudited()) {
return;
}
// I read somewhere that you can't use the same session to write to the db.
// So I get my ejb session bean (SessionHelper.getSession()).
// Then I get the injected entitymanager session (.getSession()).
// Then I get the SessionFactory and open a new session (.getSessionFactory().openSession()).
Session tempSession = SessionHelper.getSession().getSession().getSessionFactory().openSession();
Audit auditRecord = new Audit(); // This is an entity
auditRecord.setAction(action);
// auditRecord.setDetail(entity.toString());
auditRecord.setCreatedTimestamp(new Timestamp(System.currentTimeMillis()));
auditRecord.setEntityPK(entity.getPrimaryKeyDisplay());
auditRecord.setEntityName(entity.getClass().toString());
tempSession.save(auditRecord);
tempSession.flush(); // this is doing the calling the next postFlush
// Since this is a different session, I don't see why it should cascade into an infinite loop since the Audit entity is not itself Auditable (.isAuditable() == false).
}
}
我们所有的EJB实体都扩展了一个抽象类Auditable
,但是它们的.isAuditable()标志可能会也可能不会设置为true。如果是,则应在Set
期间将其添加到相应的Audit
,然后由postFlush
实体记录。但审计是在一个单独的会话中,它是一个不同的实体Audit
,其isAuditable
标志设置为false,所以我不确定为什么它显然陷入无限循环。
以下是请求的堆栈跟踪
Exception in thread "Thread-42" javax.ejb.EJBTransactionRolledbackException: Transaction rolled back
at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleEndTransactionException(CMTTxInterceptor.java:137)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.endTransaction(CMTTxInterceptor.java:117)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:282)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:330)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:242)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.remote.EJBRemoteTransactionPropagatingInterceptor.processInvocation(EJBRemoteTransactionPropagatingInterceptor.java:79)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.component.invocationmetrics.WaitTimeInterceptor.processInvocation(WaitTimeInterceptor.java:43)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:89)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:59)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:55)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ee.component.TCCLInterceptor.processInvocation(TCCLInterceptor.java:45)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:185)
at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler.invokeMethod(MethodInvocationMessageHandler.java:319)
at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler.access$100(MethodInvocationMessageHandler.java:68)
at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler$1.run(MethodInvocationMessageHandler.java:201)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:473)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:622)
at java.lang.Thread.run(Thread.java:748)
at org.jboss.threads.JBossThread.run(JBossThread.java:122)
at ...asynchronous invocation...(Unknown Source)
at org.jboss.ejb.client.remoting.InvocationExceptionResponseHandler$MethodInvocationExceptionResultProducer.getResult(InvocationExceptionResponseHandler.java:99)
at org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:270)
at org.jboss.ejb.client.TransactionInterceptor.handleInvocationResult(TransactionInterceptor.java:47)
at org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:272)
at org.jboss.ejb.client.ReceiverInterceptor.handleInvocationResult(ReceiverInterceptor.java:132)
at org.jboss.ejb.client.EJBClientInvocationContext.getResult(EJBClientInvocationContext.java:260)
at org.jboss.ejb.client.EJBClientInvocationContext.awaitResponse(EJBClientInvocationContext.java:399)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:140)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:121)
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:104)
at com.sun.proxy.$Proxy11.updateIssue(Unknown Source)
at com.kable.newsstand.knet.issue.FrmIssue2$SavingThread.doSave(FrmIssue2.java:3810)
at com.kable.newsstand.knet.issue.FrmIssue2$SavingThread.run(FrmIssue2.java:3752)
Caused by: javax.transaction.RollbackException: ARJUNA016053: Could not commit transaction.
at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1223)
at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:126)
at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:75)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.endTransaction(CMTTxInterceptor.java:91)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:282)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:330)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:242)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.remote.EJBRemoteTransactionPropagatingInterceptor.processInvocation(EJBRemoteTransactionPropagatingInterceptor.java:79)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.component.invocationmetrics.WaitTimeInterceptor.processInvocation(WaitTimeInterceptor.java:43)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:89)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:59)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:55)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.as.ee.component.TCCLInterceptor.processInvocation(TCCLInterceptor.java:45)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:185)
at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler.invokeMethod(MethodInvocationMessageHandler.java:319)
at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler.access$100(MethodInvocationMessageHandler.java:68)
at org.jboss.as.ejb3.remote.protocol.versionone.MethodInvocationMessageHandler$1.run(MethodInvocationMessageHandler.java:201)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:473)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:622)
at java.lang.Thread.run(Thread.java:748)
at org.jboss.threads.JBossThread.run(JBossThread.java:122)
Caused by: java.lang.StackOverflowError
at java.security.AccessController.doPrivileged(Native Method)
at sun.reflect.ClassDefiner.defineClass(ClassDefiner.java:57)
at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:399)
at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:396)
at java.security.AccessController.doPrivileged(Native Method)
at sun.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:395)
at sun.reflect.MethodAccessorGenerator.generateSerializationConstructor(MethodAccessorGenerator.java:113)
at sun.reflect.ReflectionFactory.generateConstructor(ReflectionFactory.java:388)
at sun.reflect.ReflectionFactory.newConstructorForSerialization(ReflectionFactory.java:351)
at org.jboss.marshalling.reflect.SerializableClass.lookupNonInitConstructor(SerializableClass.java:556)
at org.jboss.marshalling.reflect.SerializableClass.<init>(SerializableClass.java:156)
at org.jboss.marshalling.reflect.SerializableClassRegistry.lookup(SerializableClassRegistry.java:90)
at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:165)
at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:128)
at org.jboss.marshalling.cloner.SerializingCloner.cloneFields(SerializingCloner.java:393)
at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:301)
at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:276)
at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:276)
at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:276)
at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:251)
at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:128)
at org.jboss.marshalling.cloner.SerializingCloner.cloneFields(SerializingCloner.java:393)
at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:301)
at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:276)
at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:251)
at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:128)
at org.jboss.as.ejb3.remote.LocalEjbReceiver.clone(LocalEjbReceiver.java:313)
at org.jboss.as.ejb3.remote.LocalEjbReceiver.clone(LocalEjbReceiver.java:304)
at org.jboss.as.ejb3.remote.LocalEjbReceiver.processInvocation(LocalEjbReceiver.java:271)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:184)
at org.jboss.ejb.client.EJBObjectInterceptor.handleInvocation(EJBObjectInterceptor.java:58)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186)
at org.jboss.ejb.client.EJBHomeInterceptor.handleInvocation(EJBHomeInterceptor.java:83)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186)
at org.jboss.ejb.client.TransactionInterceptor.handleInvocation(TransactionInterceptor.java:42)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186)
at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:125)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186)
at org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:255)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:200)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183)
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146)
at com.sun.proxy.$Proxy317.getSession(Unknown Source)
at com.kable.newsstand.kdsejb.audit.AuditInterceptor.logIt(AuditInterceptor.java:107)
at com.kable.newsstand.kdsejb.audit.AuditInterceptor.postFlush(AuditInterceptor.java:89)
at org.hibernate.event.internal.AbstractFlushingEventListener.postPostFlush(AbstractFlushingEventListener.java:401)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:66)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1195)
这最后一部分不断重复
at com.kable.newsstand.kdsejb.audit.AuditInterceptor.logIt(AuditInterceptor.java:115)
at com.kable.newsstand.kdsejb.audit.AuditInterceptor.postFlush(AuditInterceptor.java:89)
at org.hibernate.event.internal.AbstractFlushingEventListener.postPostFlush(AbstractFlushingEventListener.java:401)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:66)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1195)
答案 0 :(得分:0)
您的一些假设是错误的,您需要按顺序检查它们。
首先,您需要检查是否确实获得了新会话。如果您遇到相同的会话,则遇到麻烦,因为从Datime <- structure(list(Day = c("11/7/2016 11:51", "11/7/2016 17:57",
"12/7/2016 9:17", "12/7/2016 21:08", "13-07-2016 08:33:16",
"13-07-2016 21:57:28",
"14-07-2016 06:15:32", "15-07-2016 05:11:52", "15-07-2016 17:57:27"
)), .Names = "Day",
class = "data.frame", row.names = c(NA, -9L
))
调用的onFlush
将开始迭代要审核的相同实体集合。
另一个可能的原因是logIt
返回Audit.isAudited
。你也需要检查一下。
答案 1 :(得分:0)
因此,我提出的解决方案是在logIt()之前从集合中删除实体。
public void postFlush(Iterator iterator) {
try {
for (Iterator<Auditable> iter = inserts.iterator(); iter.hasNext();) {
// for (Auditable entity : inserts) {
Auditable entity = iter.next();
iter.remove();
logIt("Saved", entity);
}
for (Iterator<Auditable> iter = updates.iterator(); iter.hasNext();) {
// for (Auditable entity : updates) {
Auditable entity = iter.next();
iter.remove();
logIt("Updated", entity);
}
for (Iterator<Auditable> iter = deletes.iterator(); iter.hasNext();) {
// for (Auditable entity : deletes) {
Auditable entity = iter.next();
iter.remove();
logIt("Deleted", entity);
}
} finally {
inserts.clear();
updates.clear();
deletes.clear();
}
}