Description
The situation being an error in toString() throwing an InvocationTargetException, as part of the processing of ChangedObjectsService in the preCommit().
Although this preCommit() code catches RuntimeExceptions, the InvocationTargetException thrown is actually an Exception (even though not in any throws clause).
What therefore happened was that the catch block in endTransaction did not fire, and was then caught a layer further out (in WebRequestCycleForIsis), which incorrectly created a new transaction but with the current transaction's state / transaction manager's transactionLevel in invalid states.
The net effect was a transaction with the current transaction still in progress, but with transactionLevel = 0. A subsequent endTransaction took the transactionLevel to -1, then resulting in the infinite loop.
Fixes are:
1. catch Exception rather than just RuntimeException in endTransaction
2. also change the order in which transactionLevel is decremented, so that it is only done after the preCommit stuff has completed ok
3. in the place where we throw an exception if transactionLevel is found to be -1, then also ensure that the state of the current transaction is set appropriately.
All of these have been implemented (and any is sufficient to prevent the infinite loop).
In addition, further logging to detect when there is an invalid end state of transactionLevel and transaction state has been added.
Original root cause that was not caught in endTransaction :
Caused by: java.lang.reflect.InvocationTargetException sun.reflect.GeneratedMethodAccessor367#invoke(null:-1) sun.reflect.DelegatingMethodAccessorImpl#invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method#invoke(Method.java:498) org.apache.isis.core.runtime.services.ServiceInstantiator$2#invoke(ServiceInstantiator.java:219) org.apache.isis.core.runtime.services.changes.ChangedObjectsServiceInternal_$$_jvst301_6#getChangedObjectProperties(ChangedObjectsServiceInternal_$$_jvst301_6.java:-1) org.apache.isis.core.runtime.services.auditing.AuditingServiceInternal#audit(AuditingServiceInternal.java:79) org.apache.isis.core.runtime.system.transaction.IsisTransaction#preCommit(IsisTransaction.java:424) org.apache.isis.core.runtime.system.transaction.IsisTransactionManager#endTransaction(IsisTransactionManager.java:363) org.apache.isis.viewer.wicket.viewer.integration.wicket.WebRequestCycleForIsis#onRequestHandlerExecuted(WebRequestCycleForIsis.java:129) Caused by: java.lang.IllegalArgumentException No such method ' getSent' or 'isSent' org.apache.isis.applib.util.Clause#getValueOf(ObjectContracts.java:372) org.apache.isis.applib.util.ObjectContracts#asString(ObjectContracts.java:282) org.apache.isis.applib.util.ObjectContracts#toStringOf(ObjectContracts.java:276) org.apache.isis.applib.util.ObjectContracts#toStringOf(ObjectContracts.java:270) org.apache.isis.applib.util.ObjectContracts#toString(ObjectContracts.java:127) org.incode.module.communications.dom.impl.comms.Communication#toString(Communication.java:324) org.apache.isis.core.runtime.services.changes.ChangedObjectsServiceInternal#asString(ChangedObjectsServiceInternal.java:292) org.apache.isis.core.runtime.services.changes.PreAndPostValues#setPost(PreAndPostValues.java:90) org.apache.isis.core.runtime.services.changes.ChangedObjectsServiceInternal#capturePostValuesAndDrain(ChangedObjectsServiceInternal.java:241) org.apache.isis.core.runtime.services.changes.ChangedObjectsServiceInternal#getChangedObjectProperties(ChangedObjectsServiceInternal.java:222) Caused by: java.lang.NoSuchMethodException org.incode.module.communications.dom.impl.comms.Communication.getSent() java.lang.Class#getMethod(Class.java:1786) org.apache.isis.applib.util.Clause#getValueOf(ObjectContracts.java:364) org.apache.isis.applib.util.ObjectContracts#asString(ObjectContracts.java:282) org.apache.isis.applib.util.ObjectContracts#toStringOf(ObjectContracts.java:276) org.apache.isis.applib.util.ObjectContracts#toStringOf(ObjectContracts.java:270) org.apache.isis.applib.util.ObjectContracts#toString(ObjectContracts.java:127) org.incode.module.communications.dom.impl.comms.Communication#toString(Communication.java:324) org.apache.isis.core.runtime.services.changes.ChangedObjectsServiceInternal#asString(ChangedObjectsServiceInternal.java:292)