首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在Hibernate Interceptor审计中避免StackOverflowException

如何在Hibernate Interceptor审计中避免StackOverflowException
EN

Stack Overflow用户
提问于 2018-06-05 02:52:10
回答 1查看 274关注 0票数 0

下面是我的Interceptor类

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()标志可能设置为真,也可能没有设置为真。如果为真,则应将其添加到适当的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)
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50687022

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档