oh goody...
On 29 April 2014 20:46, GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>wrote: > > Hi, Dan. > > It makes sense to me ... > > I'll send now another one that is the origin I'm becoming crazy... this > one seems related with DataNucleus. > > Thanks, > > Oscar > > > > El 29/04/2014, a las 21:42, Dan Haywood <d...@haywood-associates.co.uk> > escribió: > > > Hmm, nasty. I think I can see what's going on (but a code fix will be > needed). > > > Looking at IsisTransactionManager#executeWithinTransaction() method, I see: > > public <Q> Q executeWithinTransaction(final > TransactionalClosureWithReturn<Q> closure) { > final boolean initiallyInTransaction = inTransaction(); > if (!initiallyInTransaction) { > startTransaction(); > } > try { > closure.preExecute(); > final Q retVal = closure.execute(); > closure.onSuccess(); > if (!initiallyInTransaction) { > endTransaction(); > } > return retVal; > } catch (final RuntimeException ex) { > closure.onFailure(); > if (!initiallyInTransaction) { > abortTransaction(); > } > throw ex; > } > } > > public boolean inTransaction() { > return getTransaction() != null && > !getTransaction().getState().isComplete(); > } > > > So presumably inTransaction is returning false, that there is no > transaction in progress. > > > ~~~ > Looking at IsisTransactionManager#endTransaction(), I see (simplified): > > public synchronized void endTransaction() { > > ... > > transactionLevel--; > if (transactionLevel == 0) { > > ... > > // Isis' transaction > getTransaction().commit(); > > ... > > // JDO transaction > transactionalResource.endTransaction(); > > ... > > } > } > > > Unfortunately IsisTransaction#commit() does too much work: > > > public synchronized final void commit() { > > ... > > // update services > > doAudit(getChangedObjectProperties()); > > final String currentUser = > getTransactionManager().getAuthenticationSession().getUserName(); > final Timestamp endTimestamp = Clock.getTimeAsJavaSqlTimestamp(); > > publishActionIfRequired(currentUser, endTimestamp); > doFlush(); > > publishedChangedObjectsIfRequired(currentUser, endTimestamp); > doFlush(); > > closeServices(); > doFlush(); > > > // set as comitted > setState(State.COMMITTED); > > ... > } > > > > We want the services to be updated prior to the JDO transaction being > committed, but we want the Isis Transaction's state to be left as in > progress until after the JDO transaction is committed. > > > ~~~ > Do you agree? If so, I'll raise a ticket to fix (probably split > IsisTransaction#commit into a precommit and a postcommit. > > > Thx > Dan > > > > > On 29 April 2014 20:14, GESCONSULTOR - Óscar Bou <o....@gesconsultor.com > >wrote: > > Hi to all. > > I have an "Asset" entity with inserted() and updated() lifecycle callback > methods. > > Inside that "updated()" method, I have the following code: > > public void updated() { > this.insertOrUpdateRelationships(); > } > > public void persisted() { > this.insertOrUpdateRelationships(); > } > > private void insertOrUpdateRelationships() { > // Insert/Update Relationships. > for (final Relationship current : > this.relationshipsDerivedFromAnnnotations()) { > > > this.wrap(current.getSourceAsset()).addDirectlyImpactedAsset(current.getTargetAsset(), > current.getType()); > } > } > > > When executed inside a test, the following exception is thrown right after > finalizing the Test method (no exceptions thrown while in the Test body): > > > javax.jdo.JDOException: Unexpected error during precommit > at > > org.datanucleus.api.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:596) > at > org.datanucleus.api.jdo.JDOTransaction.commit(JDOTransaction.java:165) > at > > org.apache.isis.objectstore.jdo.datanucleus.DataNucleusObjectStore.commitJdoTransaction(DataNucleusObjectStore.java:278) > at > > org.apache.isis.objectstore.jdo.datanucleus.DataNucleusObjectStore.endTransaction(DataNucleusObjectStore.java:260) > at > > org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.endTransaction(IsisTransactionManager.java:406) > at > > org.apache.isis.core.integtestsupport.IsisSystemForTest.commitTran(IsisSystemForTest.java:610) > at > > org.apache.isis.core.integtestsupport.IntegrationTestAbstract$IsisTransactionRule$1.evaluate(IntegrationTestAbstract.java:164) > at > > org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2$1.evaluate(JUnitRuleMockery2.java:149) > at > > org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:168) > at org.junit.rules.RunRules.evaluate(RunRules.java:20) > at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) > at > > org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) > at > > org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) > at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) > at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) > at > org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) > at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) > at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) > at > > org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) > at org.junit.runners.ParentRunner.run(ParentRunner.java:309) > at > > org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) > at > > org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) > at > > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) > at > > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) > at > > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) > at > > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) > NestedThrowablesStackTrace: > java.lang.RuntimeException: > org.apache.isis.core.metamodel.spec.DomainModelException: Callback failed. > Calling > UpdatedCallbackFacetViaMethod[type=UpdatedCallbackFacet,methods=[public > void com.xms.framework.architecture.domain.model.Asset.updated()]] on > PojoAdapter@6dc5f0ba > [PR~:com.xms.framework.architecture.domain.model.business.extensions.product.Product:L_0,specification=Product,version=null,pojo-toString= > [name=Product, [tenantId=301, [id=2ED03E03-2894-485B-8491-CE88230788B2, > class > > name=com.xms.framework.architecture.domain.model.business.extensions.product.Product]]],pojo-hash=#64164b49] > at > > org.apache.isis.objectstore.jdo.datanucleus.persistence.FrameworkSynchronizer.withLogging(FrameworkSynchronizer.java:278) > at > > org.apache.isis.objectstore.jdo.datanucleus.persistence.FrameworkSynchronizer.withLogging(FrameworkSynchronizer.java:287) > at > > org.apache.isis.objectstore.jdo.datanucleus.persistence.FrameworkSynchronizer.postStoreProcessingFor(FrameworkSynchronizer.java:140) > at > > org.apache.isis.objectstore.jdo.datanucleus.persistence.IsisLifecycleListener$2.doRun(IsisLifecycleListener.java:95) > at > > org.apache.isis.objectstore.jdo.datanucleus.persistence.IsisLifecycleListener$RunnableAbstract.run(IsisLifecycleListener.java:201) > at > > org.apache.isis.objectstore.jdo.datanucleus.persistence.IsisLifecycleListener.withLogging(IsisLifecycleListener.java:180) > at > > org.apache.isis.objectstore.jdo.datanucleus.persistence.IsisLifecycleListener.postStore(IsisLifecycleListener.java:91) > at > > org.datanucleus.api.jdo.JDOCallbackHandler.postStore(JDOCallbackHandler.java:158) > at > org.datanucleus.state.JDOStateManager.flush(JDOStateManager.java:5035) > at > > org.datanucleus.state.JDOStateManager.runReachability(JDOStateManager.java:3652) > at > > org.datanucleus.store.fieldmanager.ReachabilityFieldManager.processPersistable(ReachabilityFieldManager.java:69) > at > > org.datanucleus.store.fieldmanager.ReachabilityFieldManager.storeObjectField(ReachabilityFieldManager.java:121) > at > > org.datanucleus.state.JDOStateManager.providedObjectField(JDOStateManager.java:1269) > at > > com.xms.framework.architecture.domain.model.business.extensions.businessservice.BusinessService.jdoProvideField(BusinessService.java) > at > > com.xms.framework.api.domain.model.isis.AbstractXMSDomainObject.jdoProvideFields(AbstractXMSDomainObject.java) > at > > org.datanucleus.state.JDOStateManager.provideFields(JDOStateManager.java:1346) > at > > org.datanucleus.state.JDOStateManager.runReachability(JDOStateManager.java:3678) > at > > org.datanucleus.ExecutionContextImpl.performReachabilityAtCommit(ExecutionContextImpl.java:4437) > at > > org.datanucleus.ExecutionContextImpl.preCommit(ExecutionContextImpl.java:4230) > at > > org.datanucleus.ExecutionContextImpl.transactionPreCommit(ExecutionContextImpl.java:654) > at > org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:379) > at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:268) > at > org.datanucleus.api.jdo.JDOTransaction.commit(JDOTransaction.java:98) > at > > org.apache.isis.objectstore.jdo.datanucleus.DataNucleusObjectStore.commitJdoTransaction(DataNucleusObjectStore.java:278) > at > > org.apache.isis.objectstore.jdo.datanucleus.DataNucleusObjectStore.endTransaction(DataNucleusObjectStore.java:260) > at > > org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.endTransaction(IsisTransactionManager.java:406) > at > > org.apache.isis.core.integtestsupport.IsisSystemForTest.commitTran(IsisSystemForTest.java:610) > at > > org.apache.isis.core.integtestsupport.IntegrationTestAbstract$IsisTransactionRule$1.evaluate(IntegrationTestAbstract.java:164) > at > > org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2$1.evaluate(JUnitRuleMockery2.java:149) > at > > org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:168) > at org.junit.rules.RunRules.evaluate(RunRules.java:20) > at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) > at > > org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) > at > > org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) > at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) > at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) > at > org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) > at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) > at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) > at > > org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) > at org.junit.runners.ParentRunner.run(ParentRunner.java:309) > at > > org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) > at > > org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) > at > > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) > at > > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) > at > > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) > at > > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) > Caused by: org.apache.isis.core.metamodel.spec.DomainModelException: > Callback failed. Calling > UpdatedCallbackFacetViaMethod[type=UpdatedCallbackFacet,methods=[public > void com.xms.framework.architecture.domain.model.Asset.updated()]] on > PojoAdapter@6dc5f0ba > [PR~:com.xms.framework.architecture.domain.model.business.extensions.product.Product:L_0,specification=Product,version=null,pojo-toString= > [name=Product, [tenantId=301, [id=2ED03E03-2894-485B-8491-CE88230788B2, > class > > name=com.xms.framework.architecture.domain.model.business.extensions.product.Product]]],pojo-hash=#64164b49] > at > > org.apache.isis.core.metamodel.facets.object.callbacks.CallbackUtils.callCallback(CallbackUtils.java:37) > at > > org.apache.isis.objectstore.jdo.datanucleus.persistence.FrameworkSynchronizer$2.run(FrameworkSynchronizer.java:176) > at > > org.apache.isis.objectstore.jdo.datanucleus.persistence.FrameworkSynchronizer$7.call(FrameworkSynchronizer.java:291) > at > > org.apache.isis.objectstore.jdo.datanucleus.persistence.FrameworkSynchronizer$7.call(FrameworkSynchronizer.java:287) > at > > org.apache.isis.objectstore.jdo.datanucleus.persistence.FrameworkSynchronizer.withLogging(FrameworkSynchronizer.java:276) > ... 46 more > Caused by: java.lang.IllegalStateException: Transaction already active > at > > org.apache.isis.objectstore.jdo.datanucleus.DataNucleusObjectStore.beginJdoTransaction(DataNucleusObjectStore.java:270) > at > > org.apache.isis.objectstore.jdo.datanucleus.DataNucleusObjectStore.startTransaction(DataNucleusObjectStore.java:256) > at > > org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.startTransaction(IsisTransactionManager.java:290) > at > > org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.executeWithinTransaction(IsisTransactionManager.java:219) > at > > org.apache.isis.core.runtime.transaction.facets.ActionInvocationFacetWrapTransaction.invoke(ActionInvocationFacetWrapTransaction.java:54) > at > > org.apache.isis.core.metamodel.specloader.specimpl.ObjectActionImpl.execute(ObjectActionImpl.java:342) > at > > org.apache.isis.core.wrapper.internal.DomainObjectInvocationHandler.handleActionMethod(DomainObjectInvocationHandler.java:509) > at > > org.apache.isis.core.wrapper.internal.DomainObjectInvocationHandler.invoke(DomainObjectInvocationHandler.java:236) > at > > org.apache.isis.core.wrapper.internal.InvocationHandlerMethodInterceptor.intercept(InvocationHandlerMethodInterceptor.java:37) > at > > com.xms.framework.architecture.domain.model.business.extensions.product.Product$$EnhancerByCGLIB$$1432358f.addDirectlyImpactedAsset(<generated>) > at > > com.xms.framework.architecture.domain.model.Asset.insertOrUpdateRelationships(Asset.java:847) > at > com.xms.framework.architecture.domain.model.Asset.updated(Asset.java:837) > 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 > > org.apache.isis.core.commons.lang.MethodExtensions.invoke(MethodExtensions.java:50) > at > > org.apache.isis.core.commons.lang.MethodExtensions.invoke(MethodExtensions.java:45) > at > org.apache.isis.core.commons.lang.MethodUtil.invoke(MethodUtil.java:35) > at > > org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils.invokeAll(AdapterInvokeUtils.java:40) > at > > org.apache.isis.core.progmodel.facets.object.callbacks.update.UpdatedCallbackFacetViaMethod.invoke(UpdatedCallbackFacetViaMethod.java:63) > at > > org.apache.isis.core.metamodel.facets.object.callbacks.CallbackUtils.callCallback(CallbackUtils.java:35) > ... 50 more > > > > If I change the code to this one (removing the "wrap") it works ok... > > public void updated() { > this.insertOrUpdateRelationships(); > } > > public void persisted() { > this.insertOrUpdateRelationships(); > } > > private void insertOrUpdateRelationships() { > // Insert/Update Relationships. > for (final Relationship current : > this.relationshipsDerivedFromAnnnotations()) { > > current.getSourceAsset().addDirectlyImpactedAsset(current.getTargetAsset(), > current.getType()); > } > } > > > Seems that it's not properly detected that a transaction is opened. > > Seems there's a hard-to-debug bug deep inside? > > > Thanks, > > Oscar > > > > > Óscar Bou Bou > Responsable de Producto > Auditor Jefe de Certificación ISO 27001 en BSI > CISA, CRISC, APMG ISO 20000, ITIL-F > > 902 900 231 / 620 267 520 > http://www.twitter.com/oscarbou > > http://es.linkedin.com/in/oscarbou > > http://www.GesConsultor.com <http://www.gesconsultor.com/> > > > > Este mensaje y los ficheros anexos son confidenciales. Los mismos > contienen información reservada que no puede ser difundida. Si usted ha > recibido este correo por error, tenga la amabilidad de eliminarlo de su > sistema y avisar al remitente mediante reenvío a su dirección electrónica; > no deberá copiar el mensaje ni divulgar su contenido a ninguna persona. > Su dirección de correo electrónico junto a sus datos personales constan en > un fichero titularidad de Gesdatos Software, S.L. cuya finalidad es la de > mantener el contacto con Ud. Si quiere saber de qué información disponemos > de Ud., modificarla, y en su caso, cancelarla, puede hacerlo enviando un > escrito al efecto, acompañado de una fotocopia de su D.N.I. a la siguiente > dirección: Gesdatos Software, S.L. , Paseo de la Castellana, 153 bajo - > 28046 (Madrid), y Avda. Cortes Valencianas num. 50, 1ºC - 46015 (Valencia). > Asimismo, es su responsabilidad comprobar que este mensaje o sus archivos > adjuntos no contengan virus informáticos, y en caso que los tuvieran > eliminarlos. > > > > > >