Hi Dan. It's ok for me.
Sure is a less risky approach. It still had the problem on the refactored Guava based implementation of not throwing an Exception when one was thrown on an event handler. Thanks, Oscar > El 19/2/2015, a las 13:50, Dan Haywood <[email protected]> > escribió: > > HI Oscar, > > Just coming back to you on this pull request for providing an alternate > Axon event bus. > > I know previously (offline) I said I'd look to do the work to bring this > change in for 1.8.0, but I've changed my mind, for a couple of reasons: > > * it's a fairly deep change to bring in at quite a late stage > * if we did bring it in, it would make the Axon framework a new dependency > of Isis. > * we could in any case instead make the code available as a new Isis addon. > > Thus, for those that want to use it, it should just be a matter of updating > the pom.xml and registering in isis.properties (anything registered there > takes precedence over the default @DomainServices). > > This isn't to rule out moving to an Axon-based implementation in the future > - I know you have a lot of experience with Axon and rate it highly - but I > think starting off with an Isisaddon is a lower-risk approach. It also > allows you to iterate and refine the implementation if required without the > overhead of doing a full ASF release. > > ~~~ > If you're happy with that, I'll create a new Isis addon module and put the > code there. > > Let me know, > > Dan > > > > > On 8 February 2015 at 21:59, GESCONSULTOR - Óscar Bou < > [email protected]> wrote: > >> Hi, Dan. >> >> I've updated the pull request. >> >> It still has an unexpected behavior when using the refactored >> EventBusServiceJdo, being that when an Exception is thrown during action >> processing (ie, on EXECUTING) the transaction is marked to be aborted but >> the execution flow continues (and seems not to abort). >> >> Perhaps an Exception might be thrown when detected or something similar? >> I had tests expecting an Exception that were previously passing and >> currently not. >> But not sure when the exception might be thrown. >> >> >> Thanks, >> >> Oscar >> >> >> >>>> El 8/2/2015, a las 13:04, GESCONSULTOR - Óscar Bou < >>> [email protected]> escribió: >>> >>> Hi, Dan. >>> >>> I've just sent a pull request [1] containing an initial implementation >> of an Axon-based EventBusService. >>> >>> I've refactored some classes in order to reuse Isis logic as much as >> possible. >>> >>> >>> Please, can you review it? >>> >>> Thanks, >>> >>> Oscar >>> >>> >>> [1] https://github.com/apache/isis/pull/23 < >> https://github.com/apache/isis/pull/23> >>> >>> >>>> El 6/2/2015, a las 19:47, Dan Haywood <[email protected] >> <mailto:[email protected]>> escribió: >>>> >>>> Hi Oscar, >>>> sorry not to reply on this post... just getting around to it. >>>> >>>> Yes, your email makes sense to me; I hadn't known that Guava buffered >> events, but I can see why the fact that it does could cause this >> multi-level cascade issue. >>>> >>>> I had a poke around its Javadoc but couldn't see any way to turn it off. >>>> >>>> It ought to be possible to swap in an Axion-based event bus instead >> though. Write a service implementing Isis' EventBusService API, and make >> sure that the subscribers use Axion's own subscription API, obviously. >>>> >>>> With the Guava implementation I had to install a special exception >> handler [8] so that a subscriber could veto or abort an transaction; an >> Axion implementation would need to do something similar. >>>> >>>> If you do write an implementation, then it can be registered (and take >> precedence over the built-in guava impl) just by explicitly registering in >> isis.properties, like we used to do. >>>> >>>> ~~~ >>>> As for CQRS.... Jeroen and I joke about my antipathy for it as a >> pattern. But actually, it's not really true... I can, truth be told, see >> benefits from applying some of its ideas, if only to help decouple the app >> (different rates of change of behaviour = commands vs structure = query). >>>> >>>> So, in Isis a CQRS app one would have dumb entities, and all behaviour >> would be either contributed actions or event bus subscribers. Indeed, we >> are gradually refactoring Estatio into this structure, so that we can (a) >> focus on its core domain - an invoice calculation engine - and (b) >> potentially reuse some of its building block modules in other apps. >>>> >>>> Cheers >>>> Dan >>>> >>>> >>>> [8] >> https://github.com/apache/isis/blob/b5f73ec3dcae8015d11004915c15dd81c2945238/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusServiceDefault.java#L91 >> < >> https://github.com/apache/isis/blob/b5f73ec3dcae8015d11004915c15dd81c2945238/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusServiceDefault.java#L91 >>> >>>> >>>> >>>> On 17 January 2015 at 16:17, GESCONSULTOR - Óscar Bou < >> [email protected] <mailto:[email protected]>> wrote: >>>> Hi all. >>>> >>>> I'm "fighting" against current Event Bus implementation, as it's >> currently based on Guava Event Bus. >>>> >>>> It has one characteristic that is not allowing me to implement, for >> example, cascade deleting of Domain Entities, nested in 3 levels (Entity2 >> references Entity1, and Entity3 references Entity2. When deleting an >> Entity1 instance I want to delete - or set to null, etc. - Entity2 and >> Entity3 also). >>>> >>>> This is due to Guava EventBus current implementation, that enqueues >> Events posted instead of dispatching them at the very moment [1] as a >> programmer would expect with a sequential execution flow. >>>> >>>> That originates limitations on "nested" behaviors when you post an >> Event once you're processing an Event (ie, you're entered a @Subscriber). >>>> For example, Events dispatched from actions that act on the EXECUTING >> phase: >>>> - if invoked by the user from the UI the @Subscriber's code will be >> executed PRIOR to the action's code. >>>> - but if invoked as part of a previous Event handler (ie, when still >> executing a previous Event @Subscriber's code) it will be queued and will >> be executed AFTER the action's code. >>>> >>>> In [1] the problem is explained quite clearly, and also the solution if >> this one is not the desired behavior (to "delete" 3 lines, as currently >> it's not configurable...). >>>> >>>> >>>> >>>> I'm trying to explain this over Estatio. >>>> >>>> On [2], the Party entity declares a "remove" action that posts an Event. >>>> >>>> On 3], the AgreementRoles service is subscribed to the Event. >>>> But imagine that we want to delete all "AgreementRole" instances >> instead of setting the reference to null or to another Party. >>>> For that, we would declare and invoke a similar "remove" action to the >> one defined for Party ([2]), with an @ActionInteraction for posting an >> Event, and invoking it inside a "wrap" for the Event to be published. >>>> >>>> If I only have Party and AgreementRole, when Party.RemoveEvent is >> processed on the EXECUTING phase I can delete (or set to null) the >> AgreementRole instances referencing it. >>>> So by now, all is ok. >>>> >>>> >>>> But now imagine that there's another Entity that holds a reference to >> the "AgreementRole" we are removing. >>>> For that, I subscribe to AgreementRole.Remove Events hoping that >> @Subscriber to be called BEFORE an "AgreementRole" is removed, in order to >> "clear" (set to null) the reference to it, avoiding a referential integrity >> Exception. >>>> >>>> In fact, I can define a test that asserts that, when an AgreementRole >> is removed, the Event is posted and the reference is set to null. >>>> >>>> But what happens if the "AgreementRole.remove()" action is invoked >> WHILE still processing the Party.RemoveEvent on the "AgreementRoles" >> @Subscriber? >>>> >>>> That the Event will be queued, instead of being processed when posted >> (and the AgreementRole @Subscriber being invoke then) !!! >>>> >>>> >>>> As the execution flow will return to the "Party.RemoveEvent", where the >> container().remove(...) method will be invoked, a JDO exception will be >> thrown, similar to this one: >>>> >>>> javax.jdo.JDODataStoreException: Ha tirado una excepci�n al hacer >> flush() a la base de datos >>>> at >> org.datanucleus.api.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:451) >>>> at >> org.datanucleus.api.jdo.JDOPersistenceManager.flush(JDOPersistenceManager.java:2029) >>>> at >> org.apache.isis.objectstore.jdo.datanucleus.DataNucleusObjectStore.executeCommands(DataNucleusObjectStore.java:361) >>>> at >> org.apache.isis.objectstore.jdo.datanucleus.DataNucleusObjectStore.execute(DataNucleusObjectStore.java:353) >>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransaction.doFlush(IsisTransaction.java:502) >>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransaction.flush(IsisTransaction.java:451) >>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.flushTransaction(IsisTransactionManager.java:392) >>>> at >> org.apache.isis.core.runtime.persistence.internal.RuntimeContextFromSession$7.flush(RuntimeContextFromSession.java:238) >>>> at >> org.apache.isis.core.metamodel.services.container.DomainObjectContainerDefault.flush(DomainObjectContainerDefault.java:247) >>>> at >> com.xms.framework.api.domain.model.isis.AbstractIsisDomainRepositoryAndFactory.doRemove(AbstractIsisDomainRepositoryAndFactory.java:353) >>>> at >> com.xms.framework.api.domain.model.isis.AbstractIsisDomainRepositoryAndFactory$3.execute(AbstractIsisDomainRepositoryAndFactory.java:346) >>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.executeWithinTransaction(IsisTransactionManager.java:160) >>>> at >> com.xms.framework.api.domain.model.isis.AbstractIsisDomainRepositoryAndFactory.remove(AbstractIsisDomainRepositoryAndFactory.java:342) >>>> at >> com.xms.framework.api.domain.model.isis.DomainRepositoryService.deleteEntity(DomainRepositoryService.java:221) >>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) >>>> at >> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) >>>> at >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >>>> at java.lang.reflect.Method.invoke(Method.java:606) >>>> at >> org.apache.isis.core.metamodel.facets.actions.interaction.ActionInvocationFacetForInteractionAbstract.internalInvoke(ActionInvocationFacetForInteractionAbstract.java:314) >>>> at >> org.apache.isis.core.metamodel.facets.actions.interaction.ActionInvocationFacetForInteractionAbstract.invoke(ActionInvocationFacetForInteractionAbstract.java:188) >>>> at >> org.apache.isis.core.runtime.transaction.facets.ActionInvocationFacetWrapTransaction$1.execute(ActionInvocationFacetWrapTransaction.java:57) >>>> at >> org.apache.isis.core.runtime.transaction.facets.ActionInvocationFacetWrapTransaction$1.execute(ActionInvocationFacetWrapTransaction.java:1) >>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.executeWithinTransaction(IsisTransactionManager.java:205) >>>> 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:367) >>>> at >> org.apache.isis.core.wrapper.handlers.DomainObjectInvocationHandler.handleActionMethod(DomainObjectInvocationHandler.java:563) >>>> at >> org.apache.isis.core.wrapper.handlers.DomainObjectInvocationHandler.invoke(DomainObjectInvocationHandler.java:229) >>>> at >> org.apache.isis.core.wrapper.proxy.ProxyInstantiatorForJavassist$1.invoke(ProxyInstantiatorForJavassist.java:52) >>>> at >> com.xms.framework.api.domain.model.isis.DomainRepositoryService_$$_jvst9b5_6.deleteEntity(DomainRepositoryService_$$_jvst9b5_6.java) >>>> at >> com.xms.framework.api.integration.tests.isis.AbstractIsisDomainRepositoryAndFactoryTests.deleteDomainObjectWithAnnotation_referenced_isDeleted_ifEventHandlerDeletesTheReference_nested(AbstractIsisDomainRepositoryAndFactoryTests.java:108) >>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) >>>> at >> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) >>>> at >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >>>> at java.lang.reflect.Method.invoke(Method.java:606) >>>> at >> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) >>>> at >> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) >>>> at >> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) >>>> at >> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) >>>> at >> org.apache.isis.core.integtestsupport.IntegrationTestAbstract$IsisTransactionRule$1.evaluate(IntegrationTestAbstract.java:199) >>>> at >> org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2$1.evaluate(JUnitRuleMockery2.java:146) >>>> 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.sql.BatchUpdateException: violación del restricción de integridad: >> sin acción para la clave foránea; AGREEMENTROLE_FK1 table: AGREEMENTROLE >>>> at org.hsqldb.jdbc.JDBCPreparedStatement.executeBatch(Unknown >> Source) >>>> at >> org.datanucleus.store.rdbms.datasource.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297) >>>> at >> org.datanucleus.store.rdbms.datasource.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297) >>>> at >> org.datanucleus.store.rdbms.ParamLoggingPreparedStatement.executeBatch(ParamLoggingPreparedStatement.java:372) >>>> at >> org.datanucleus.store.rdbms.SQLController.processConnectionStatement(SQLController.java:628) >>>> at >> org.datanucleus.store.rdbms.SQLController.processStatementsForConnection(SQLController.java:596) >>>> at >> org.datanucleus.store.rdbms.SQLController$1.transactionFlushed(SQLController.java:683) >>>> at >> org.datanucleus.store.connection.AbstractManagedConnection.transactionFlushed(AbstractManagedConnection.java:86) >>>> at >> org.datanucleus.store.connection.ConnectionManagerImpl$2.transactionFlushed(ConnectionManagerImpl.java:454) >>>> at org.datanucleus.TransactionImpl.flush(TransactionImpl.java:203) >>>> at >> org.datanucleus.ExecutionContextImpl.flushInternal(ExecutionContextImpl.java:4125) >>>> at >> org.datanucleus.ExecutionContextImpl.flush(ExecutionContextImpl.java:4070) >>>> at >> org.datanucleus.api.jdo.JDOPersistenceManager.flush(JDOPersistenceManager.java:2010) >>>> at >> org.apache.isis.objectstore.jdo.datanucleus.DataNucleusObjectStore.executeCommands(DataNucleusObjectStore.java:361) >>>> at >> org.apache.isis.objectstore.jdo.datanucleus.DataNucleusObjectStore.execute(DataNucleusObjectStore.java:353) >>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransaction.doFlush(IsisTransaction.java:502) >>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransaction.flush(IsisTransaction.java:451) >>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.flushTransaction(IsisTransactionManager.java:392) >>>> at >> org.apache.isis.core.runtime.persistence.internal.RuntimeContextFromSession$7.flush(RuntimeContextFromSession.java:238) >>>> at >> org.apache.isis.core.metamodel.services.container.DomainObjectContainerDefault.flush(DomainObjectContainerDefault.java:247) >>>> at >> com.xms.framework.api.domain.model.isis.AbstractIsisDomainRepositoryAndFactory.doRemove(AbstractIsisDomainRepositoryAndFactory.java:353) >>>> at >> com.xms.framework.api.domain.model.isis.AbstractIsisDomainRepositoryAndFactory$3.execute(AbstractIsisDomainRepositoryAndFactory.java:346) >>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.executeWithinTransaction(IsisTransactionManager.java:160) >>>> at >> com.xms.framework.api.domain.model.isis.AbstractIsisDomainRepositoryAndFactory.remove(AbstractIsisDomainRepositoryAndFactory.java:342) >>>> at >> com.xms.framework.api.domain.model.isis.DomainRepositoryService.deleteEntity(DomainRepositoryService.java:221) >>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) >>>> at >> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) >>>> at >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >>>> at java.lang.reflect.Method.invoke(Method.java:606) >>>> at >> org.apache.isis.core.metamodel.facets.actions.interaction.ActionInvocationFacetForInteractionAbstract.internalInvoke(ActionInvocationFacetForInteractionAbstract.java:314) >>>> at >> org.apache.isis.core.metamodel.facets.actions.interaction.ActionInvocationFacetForInteractionAbstract.invoke(ActionInvocationFacetForInteractionAbstract.java:188) >>>> at >> org.apache.isis.core.runtime.transaction.facets.ActionInvocationFacetWrapTransaction$1.execute(ActionInvocationFacetWrapTransaction.java:57) >>>> at >> org.apache.isis.core.runtime.transaction.facets.ActionInvocationFacetWrapTransaction$1.execute(ActionInvocationFacetWrapTransaction.java:1) >>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.executeWithinTransaction(IsisTransactionManager.java:205) >>>> 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:367) >>>> at >> org.apache.isis.core.wrapper.handlers.DomainObjectInvocationHandler.handleActionMethod(DomainObjectInvocationHandler.java:563) >>>> at >> org.apache.isis.core.wrapper.handlers.DomainObjectInvocationHandler.invoke(DomainObjectInvocationHandler.java:229) >>>> at >> org.apache.isis.core.wrapper.proxy.ProxyInstantiatorForJavassist$1.invoke(ProxyInstantiatorForJavassist.java:52) >>>> at >> com.xms.framework.api.domain.model.isis.DomainRepositoryService_$$_jvst9b5_6.deleteEntity(DomainRepositoryService_$$_jvst9b5_6.java) >>>> at >> com.xms.framework.api.integration.tests.isis.AbstractIsisDomainRepositoryAndFactoryTests.deleteDomainObjectWithAnnotation_referenced_isDeleted_ifEventHandlerDeletesTheReference_nested(AbstractIsisDomainRepositoryAndFactoryTests.java:108) >>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) >>>> at >> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) >>>> at >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >>>> at java.lang.reflect.Method.invoke(Method.java:606) >>>> at >> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) >>>> at >> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) >>>> at >> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) >>>> at >> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) >>>> at >> org.apache.isis.core.integtestsupport.IntegrationTestAbstract$IsisTransactionRule$1.evaluate(IntegrationTestAbstract.java:199) >>>> at >> org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2$1.evaluate(JUnitRuleMockery2.java:146) >>>> 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) >>>> >>>> >>>> >>>> >>>> Am I missing something here? Perhaps a better way to solve this? >>>> >>>> >>>> >>>> >>>> If not, for this to be avoided, possible solutions that come to my mind >> are: >>>> 1. To modify the current Guava's EventBus implementation to not queue >> Event calls. >>>> 2. To change current EventBus implementation to another one that will >> not affect the business logic execution flow. >>>> >>>> >>>> I've being a long-time user of the Axon framework's EventBus, and I'm >> going to try it to resolve this use case. >>>> >>>> They have really amazing Event Bus implementations for "simple" >> scenarios as mostly ours regarding one virtual machine (see SimpleEventBus >> [4]) and for really advance scenarios involving Domain Events in clusters >> (see ClusteredEventBus [5]). >>>> >>>> So using the SimpleEventBus seems the best way here ... >>>> >>>> Also, I think it would be interesting for Apache Isis to integrate it, >> as it could be the initial alignment of Apache Isis DDD implementation with >> CQRS, which quite people on the DDD community consider are closely related >> (see references on the "Implementing DDD" book, and some links like [7], . >>>> >>>> >>>> >>>> >>>> Excuse me for this long email. Events are hard to explain ... :-)) >>>> >>>> Many thanks in advance, >>>> >>>> Oscar >>>> >>>> >>>> >>>> >>>> >>>> [1] >> https://github.com/estatio/estatio/blob/master/estatioapp/dom/src/main/java/org/estatio/dom/party/Party.java#L177 >> < >> https://github.com/estatio/estatio/blob/master/estatioapp/dom/src/main/java/org/estatio/dom/party/Party.java#L177 >>> >>>> >>>> [2] >> https://github.com/estatio/estatio/blob/master/estatioapp/dom/src/main/java/org/estatio/dom/agreement/AgreementRoles.java#L143 >> < >> https://github.com/estatio/estatio/blob/master/estatioapp/dom/src/main/java/org/estatio/dom/agreement/AgreementRoles.java#L143 >>> >>>> >>>> [3] >> http://stackoverflow.com/questions/21947936/guava-eventbus-dispatching < >> http://stackoverflow.com/questions/21947936/guava-eventbus-dispatching> >>>> >>>> [4] http://www.axonframework.org <http://www.axonframework.org/> >>>> >>>> [5] >> https://github.com/AxonFramework/AxonFramework/blob/master/core/src/main/java/org/axonframework/eventhandling/SimpleEventBus.java >> < >> https://github.com/AxonFramework/AxonFramework/blob/master/core/src/main/java/org/axonframework/eventhandling/SimpleEventBus.java >>> >>>> >>>> [6] >> https://github.com/AxonFramework/AxonFramework/blob/master/core/src/main/java/org/axonframework/eventhandling/ClusteringEventBus.java >> < >> https://github.com/AxonFramework/AxonFramework/blob/master/core/src/main/java/org/axonframework/eventhandling/ClusteringEventBus.java >>> >>>> >>>> [7] >> http://www.kenneth-truyers.net/2013/12/05/introduction-to-domain-driven-design-cqrs-and-event-sourcing/ >> < >> http://www.kenneth-truyers.net/2013/12/05/introduction-to-domain-driven-design-cqrs-and-event-sourcing/ >>> >>>> >>>> >>>> >>>> >>>>> El 14/1/2015, a las 10:07, GESCONSULTOR - Óscar Bou < >> [email protected] <mailto:[email protected]>> escribió: >>>>> >>>>> Just to notice. >>>>> >>>>> As I was simply trying that, when removing an Entity (Relationship), >> declared on a "core" module, it would automatically remove a dependent >> object (RelationshipBCMInformation) declared on another module without >> creating a direct dependency on the "core" module, I also tried to use >> foreign keys declaration through JDO. >>>>> >>>>> So I annotated the RelationshipBCMInformation with @Element as this: >>>>> >>>>> >>>>> public class RelationshipBCMInformation extends >> AbstractMultiTenantUnnamedEntity { >>>>> >>>>> >>>>> // {{ Relationship (property) >>>>> private Relationship relationship; >>>>> >>>>> @Hidden >>>>> @XMSField(locales = { @XMSLocale(locale = "es", caption = >> "Relación") }) >>>>> @Column(allowsNull = "false") >>>>> @MemberOrder(sequence = "010") >>>>> @Element(deleteAction = ForeignKeyAction.CASCADE) >>>>> public Relationship getRelationship() { >>>>> return this.relationship; >>>>> } >>>>> >>>>> public void setRelationship(final Relationship relationship) { >>>>> this.relationship = relationship; >>>>> } >>>>> >>>>> .... >>>>> >>>>> } >>>>> >>>>> Seems that HSQLDB does not properly support DELETE CASCADE, but over >> PostgreSQL it declares de Foreign Key and deletes de object. >>>>> >>>>> But seems that Isis does not get notified about it and the following >> exception is thrown when ending the Isis transaction: >>>>> >>>>> Rerun >> com.xms.framework.risk.integration.tests.continuity.RelationshipsBCMInformationTests.testDeleteColletionWithRelationshipAlsoDeletesRelationshipBCMInformation >> testDeleteColletionWithRelationshipAlsoDeletesRelationshipBCMInformation(com.xms.framework.risk.integration.tests.continuity.RelationshipsBCMInformationTests) >>>>> javax.jdo.JDOUserException: No es posible leer campos de un objeto >> borrado >> FailedObject:1[OID]com.xms.framework.architecture.domain.model.Relationship >>>>> at >> org.datanucleus.api.jdo.state.PersistentNewDeleted.transitionReadField(PersistentNewDeleted.java:106) >>>>> at >> org.datanucleus.state.AbstractStateManager.transitionReadField(AbstractStateManager.java:650) >>>>> at >> org.datanucleus.state.JDOStateManager.isLoaded(JDOStateManager.java:3194) >>>>> at >> com.xms.framework.api.domain.model.isis.AbstractMultiTenantObject.getTenantId(AbstractMultiTenantObject.java) >>>>> at >> com.xms.framework.api.domain.model.isis.AbstractMultiTenantObject.toString(AbstractMultiTenantObject.java:72) >>>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransaction.asString(IsisTransaction.java:703) >>>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransaction.access$0(IsisTransaction.java:702) >>>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransaction$PreAndPostValues.setPost(IsisTransaction.java:1197) >>>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransaction.updatePostValues(IsisTransaction.java:1325) >>>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransaction.getChangedObjectProperties(IsisTransaction.java:1310) >>>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransaction.preCommit(IsisTransaction.java:733) >>>>> at >> org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.endTransaction(IsisTransactionManager.java:481) >>>>> at >> org.apache.isis.core.integtestsupport.IsisSystemForTest.endTran(IsisSystemForTest.java:667) >>>>> at >> org.apache.isis.core.integtestsupport.IntegrationTestAbstract$IsisTransactionRule$1.evaluate(IntegrationTestAbstract.java:200) >>>>> at >> org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2$1.evaluate(JUnitRuleMockery2.java:146) >>>>> 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) >>>>> >>>>> >>>>> >>>>> I will try to reimplement it using Events, but perhaps this is >> relevant for other use cases. >>>>> >>>>> HTH, >>>>> >>>>> Oscar >>>>> >>>>> >>>>> >>>>> >>>>> >>>>>> El 13/1/2015, a las 19:25, GESCONSULTOR - Óscar Bou < >> [email protected] <mailto:[email protected]>> escribió: >>>>>> >>>>>> Hi Dan. >>>>>> >>>>>> I’ve just updated the issue description. >>>>>> >>>>>> Just an “idiomatic issue”. >>>>>> >>>>>> I understand that an object can be saved when initially created, and >> after updating an existing object. >>>>>> >>>>>> So for me domainEventOnSave would be triggered both when saving newly >> created objects, and when updating previously created objects. >>>>>> >>>>>> Would it be better naming it something like “domainEventOnCreate” ? >>>>>> >>>>>> Seems JDO lifecycle callbacks are named something similar [1]. >>>>>> >>>>>> Regards, >>>>>> >>>>>> Oscar >>>>>> >>>>>> >>>>>> [1] >> http://www.datanucleus.org/products/datanucleus/jdo/lifecycle_callbacks.html >> < >> http://www.datanucleus.org/products/datanucleus/jdo/lifecycle_callbacks.html >>> >>>>>> >>>>>> >>>>>>> El 13/1/2015, a las 18:39, Dan Haywood <[email protected] >> <mailto:[email protected]>> escribió: >>>>>>> >>>>>>> >>>>>>> >>>>>>> On 13 January 2015 at 17:19, GESCONSULTOR - Óscar Bou < >> [email protected] <mailto:[email protected]>> wrote: >>>>>>> ok, Dan. >>>>>>> >>>>>>> But that would include something like @DomainObjectInteraction, in >> order to customize the event (and the event handler) ? >>>>>>> >>>>>>> >>>>>>> >>>>>>> Yeah, though into @DomainObject rather than a new annotation. >>>>>>> >>>>>>> Why? because in ISIS-970 the existing annotations @ActionInteraction >> / @PropertyInteraction / @CollectionInteraction are being deprecated to be >> replaced by into @Action / @Property / @Collection, >>>>>>> >>>>>>> eg: >>>>>>> @ActionInteraction(SomethingChangedEvent.class) >>>>>>> >>>>>>> will become >>>>>>> >>>>>>> @Action(domainEvent=SomethingChangedEvent.class) >>>>>>> >>>>>>> >>>>>>> ~~~ >>>>>>> >>>>>>> Therefore I suggest >>>>>>> >>>>>>> @DomainObject( >>>>>>> domainEventOnLoad = ..., >>>>>>> domainEventOnSave = ..., >>>>>>> domainEventOnUpdate = ..., >>>>>>> domainEventOnDelete = ..., >>>>>>> ) >>>>>>> >>>>>>> I don't think there's any need to have a pairs of hooks (eg >> domainEventOnSaving / domainEventOnSaved), because the domainEvent itself >> has "phases", ie EXECUTING and EXECUTED. So we can reuse that. >>>>>>> >>>>>>> I'm not sure at this stage if the other "vetoing" phases >> (HIDE/DISABLE/VALIDATE) all makes sense, though possibly the OnLoad event >> could honour HIDE and DISABLE (providing a way by which a subscriber could >> prevent an object from being either viewed or being edited). >>>>>>> >>>>>>> If the above sounds ok, can you do me a favour and copy/paste some >> of the above into the ISIS-803 ticket? >>>>>>> >>>>>>> >>>>>>> Cheers >>>>>>> Dan >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>>> El 13/1/2015, a las 15:21, Dan Haywood < >> [email protected] <mailto:[email protected]>> >> escribió: >>>>>>>> >>>>>>>> Hi Oscar >>>>>>>> >>>>>>>> Although we probably won't use this in Estatio, it is (I think) a >> valid use case. >>>>>>>> >>>>>>>> We do in fact have a ticket for it already, ISIS-803 [1]. And the >> original ticket that introduced the event bus, ISIS-550 [2], although it >> didn't implement the feature, did mention it. >>>>>>>> >>>>>>>> In a similar vein, if we implement ISIS-803 then I think the >> recently raised ISIS-1005 [3] is probably redundant (or at least, is part >> of ISIS-803). >>>>>>>> >>>>>>>> In terms of priorities, I want to get my @Action / @Property / >> @Collection stuff finished off. Then I'll take a look at this and see how >> much work it is to squeeze in for 1.8.0 or not. >>>>>>>> >>>>>>>> HTH >>>>>>>> Dan >>>>>>>> >>>>>>>> >>>>>>>> [1] https://issues.apache.org/jira/browse/ISIS-803 < >> https://issues.apache.org/jira/browse/ISIS-803> >>>>>>>> [2] https://issues.apache.org/jira/browse/ISIS-550 < >> https://issues.apache.org/jira/browse/ISIS-550> >>>>>>>> [3] https://issues.apache.org/jira/browse/ISIS-1005 < >> https://issues.apache.org/jira/browse/ISIS-1005> >>>>>>>> >>>>>>>> >>>>>>>> ~~~~~~~~~~~~~ >>>>>>>> >>>>>>>> >>>>>>>> On 13 January 2015 at 14:06, GESCONSULTOR - Óscar Bou < >> [email protected] <mailto:[email protected]>> wrote: >>>>>>>> Hi, Dan and Jeroen for your pointing me towards those examples. >>>>>>>> >>>>>>>> As I'm seeing on Estatio, event publishing is made through an >> @ActionInteraction annotation, which requires to always delete entities by >> means of that action. >>>>>>>> >>>>>>>> I attached the event post to the "removing" framework method for >> publishing the event every time an object is going to be delete, >> independently it's made through a custom action or through >> "container().remove()". >>>>>>>> That way, I can be sure the business logic is going to be executed >> ALWAYS despite how the other developers implement this. >>>>>>>> >>>>>>>> We can re-implement all this event logic for assuring that we >> always delete this kind of domain objects through that action, but I >> thought previous solution would work better, as it's directly attached to >> the object's lifecycle. >>>>>>>> >>>>>>>> In previous threads we talked about the option of being notified of >> framework's events. >>>>>>>> >>>>>>>> Perhaps implementing a @DomainObjectInteraction annotation in a >> similar way to @ActionInteraction could have sense. >>>>>>>> >>>>>>>> What do you think? >>>>>>>> >>>>>>>> Thanks, >>>>>>>> >>>>>>>> Oscar >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>>> El 12/1/2015, a las 20:38, Jeroen van der Wal <[email protected] >> <mailto:[email protected]>> escribió: >>>>>>>>> >>>>>>>>> >>>>>>>>> Here's a sample of invalidating the removal of a Party in case it >> plays >>>>>>>>> role in an agreement: >> https://github.com/estatio/estatio/blob/master/estatioapp/dom/src/main/java/org/estatio/dom/agreement/AgreementRoles.java#L143 >> < >> https://github.com/estatio/estatio/blob/master/estatioapp/dom/src/main/java/org/estatio/dom/agreement/AgreementRoles.java#L143 >>> >>>>>>>>> >>>>>>>>> HTH >>>>>>>>> >>>>>>>>> On 12 January 2015 at 19:38, Dan Haywood < >> [email protected] <mailto:[email protected]>> >>>>>>>>> wrote: >>>>>>>>> >>>>>>>>>> Hi Oscar, >>>>>>>>>> >>>>>>>>>> I think we can support this use case, but admittedly it isn't - >> yet - well >>>>>>>>>> documented. >>>>>>>>>> >>>>>>>>>> First thing to say is that the "removing" lifecycle code hook >> method that >>>>>>>>>> you quote isn't actually part of your stacktrace. As it happens, >> that's >>>>>>>>>> probably a good thing... support for them is a little bit patchy >> (there >>>>>>>>>> might be bugs). >>>>>>>>>> >>>>>>>>>> So, when I look at your stack trace, what's actually happening is >> that: >>>>>>>>>> * BusinessEntity.deleteFromAssignedToBusinessProcesses(...) is >> performing a >>>>>>>>>> "removeElement" on a wrapped collection, which fires an event via: >>>>>>>>>> * CollectionRemoveFromFacetForInteractionAbstract, which is >> handled by >>>>>>>>>> * RelationshipsBCMInformationEventHandler.on >>>>>>>>>> >>>>>>>>>> So, what you should do in the handler is to look at the event's >> "phase". >>>>>>>>>> In fact, you really must pay attention to the phase because it is >> called >>>>>>>>>> multiple times: >>>>>>>>>> >>>>>>>>>> switch(ev,getPhase()) { >>>>>>>>>> case HIDE: >>>>>>>>>> ... >>>>>>>>>> case DISABLE: >>>>>>>>>> ... >>>>>>>>>> case VALIDATE: >>>>>>>>>> ... >>>>>>>>>> case EXECUTING: >>>>>>>>>> ... >>>>>>>>>> case EXECUTED: >>>>>>>>>> ... >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> As you have probably guessed, your code wants to go into the >> "EXECUTING" >>>>>>>>>> bit, which is the pre-execute callback. I imagine at the moment >> it is >>>>>>>>>> firing for all the cases, including the EXECUTED bit, and that's >> most >>>>>>>>>> likely why JDO then complains at you when you try to access that >> deleted >>>>>>>>>> object. >>>>>>>>>> >>>>>>>>>> Hope that makes sense / works... if not, then we can go round the >> loop. >>>>>>>>>> >>>>>>>>>> Cheers >>>>>>>>>> Dan >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> Two things about >>>>>>>>>> Rather than do this on the removing() callback, I suggest you >> emit an event >>>>>>>>>> on the action that The event that >>>>>>>>>> >>>>>>>>>> On 12 January 2015 at 18:24, GESCONSULTOR - Óscar Bou < >>>>>>>>>> [email protected] <mailto:[email protected]>> wrote: >>>>>>>>>> >>>>>>>>>>> Hi all. >>>>>>>>>>> >>>>>>>>>>> I want to get notified when a domain object is going to be >> removed. >>>>>>>>>>> >>>>>>>>>>> I have defined it as this: >>>>>>>>>>> >>>>>>>>>>> public class Relationship { >>>>>>>>>>> >>>>>>>>>>> … >>>>>>>>>>> >>>>>>>>>>> public void removing() { >>>>>>>>>>> this.eventBusService.post(new >> RelationshipRemovingEvent(this)); >>>>>>>>>>> } >>>>>>>>>>> ... >>>>>>>>>>> >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> And an Event Handler like this: >>>>>>>>>>> >>>>>>>>>>> public class RelationshipsBCMInformationEventHandler extends >>>>>>>>>>> AbstractXMSService { >>>>>>>>>>> >>>>>>>>>>> // {{ RELATIONSHIPS EVENTS HANDLER >>>>>>>>>>> >>>>>>>>>>> @Subscribe >>>>>>>>>>> @Programmatic >>>>>>>>>>> public void on(final RelationshipRemovingEvent event) { >>>>>>>>>>> try { >>>>>>>>>>> final RelationshipBCMInformation >> relationshipBCMInformation = >> this.wrap(this.relationshipsBCMInformation).businessContinuityInformation(event.getRelationship()); >> this.getContainer().remove(relationshipBCMInformation); >>>>>>>>>>> this.getContainer().flush(); >>>>>>>>>>> } catch (final Exception e) { >>>>>>>>>>> e.printStackTrace(); >>>>>>>>>>> throw new ApplicationException(e); >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> // }} >>>>>>>>>>> >>>>>>>>>>> // {{ injected: RelationshipsBCMInformation >>>>>>>>>>> @Inject >>>>>>>>>>> private RelationshipsBCMInformation >> relationshipsBCMInformation; >>>>>>>>>>> >>>>>>>>>>> // }} >>>>>>>>>>> >>>>>>>>>>> // {{ injected: EventBusService >>>>>>>>>>> @Programmatic >>>>>>>>>>> @PostConstruct >>>>>>>>>>> public void postConstruct() { >>>>>>>>>>> this.eventBusService.register(this); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> @Programmatic >>>>>>>>>>> @PreDestroy >>>>>>>>>>> public void preDestroy() { >>>>>>>>>>> this.eventBusService.unregister(this); >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> @javax.inject.Inject >>>>>>>>>>> private EventBusService eventBusService; >>>>>>>>>>> // }} >>>>>>>>>>> >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Problem is that when the code enters the “on” event handler, the >>>>>>>>>> reference >>>>>>>>>>> to the relationship accessed on "event.getRelationship()” is >> already >>>>>>>>>> marked >>>>>>>>>>> as deleted: >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> javax.jdo.JDOUserException: No es posible leer campos de un >> objeto >>>>>>>>>> borrado >> FailedObject:0[OID]com.xms.framework.architecture.domain.model.Relationship >>>>>>>>>>> at >> org.datanucleus.api.jdo.state.PersistentNewDeleted.transitionReadField(PersistentNewDeleted.java:106) >>>>>>>>>>> at >> org.datanucleus.state.AbstractStateManager.transitionReadField(AbstractStateManager.java:650) >>>>>>>>>>> at >> org.datanucleus.state.JDOStateManager.isLoaded(JDOStateManager.java:3194) >>>>>>>>>>> at >> com.xms.framework.api.domain.model.isis.AbstractXMSDomainObject.getId(AbstractXMSDomainObject.java) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.api.domain.model.isis.AbstractXMSDomainObject.hashCode(AbstractXMSDomainObject.java:431) >>>>>>>>>>> at java.util.Objects.hashCode(Objects.java:96) >>>>>>>>>>> at java.util.HashMap$Entry.hashCode(HashMap.java:847) >>>>>>>>>>> at java.util.AbstractMap.hashCode(AbstractMap.java:494) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.datanucleus.query.QueryUtils.getKeyForQueryResultsCache(QueryUtils.java:1306) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.datanucleus.store.query.QueryManager.getDatastoreQueryResult(QueryManager.java:470) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.datanucleus.store.rdbms.query.JDOQLQuery.performExecute(JDOQLQuery.java:605) >>>>>>>>>>> at >>>>>>>>>> org.datanucleus.store.query.Query.executeQuery(Query.java:1786) >>>>>>>>>>> at >>>>>>>>>>> org.datanucleus.store.query.Query.executeWithMap(Query.java:1690) >>>>>>>>>>> at >>>>>>>>>>> >> org.datanucleus.api.jdo.JDOQuery.executeWithMap(JDOQuery.java:334) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.api.domain.model.isis.AbstractXMSDomainObjectRepositoryAndFactory.doFindByPropMultiTenant(AbstractXMSDomainObjectRepositoryAndFactory.java:759) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.api.domain.model.isis.AbstractXMSDomainObjectRepositoryAndFactory.findByPropMultiTenant(AbstractXMSDomainObjectRepositoryAndFactory.java:776) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.api.domain.model.isis.AbstractXMSDomainObjectRepositoryAndFactory.findByProp(AbstractXMSDomainObjectRepositoryAndFactory.java:769) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.api.domain.model.isis.AbstractSingletonMultiTenantObjectRepositoryAndFactory.singletonInstance(AbstractSingletonMultiTenantObjectRepositoryAndFactory.java:16) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.risk.domain.model.continuity.RelationshipsBCMInformation.businessContinuityInformation(RelationshipsBCMInformation.java:47) >>>>>>>>>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native >> Method) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >>>>>>>>>>> at java.lang.reflect.Method.invoke(Method.java:606) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.metamodel.facets.actions.interaction.ActionInvocationFacetForInteractionAbstract.internalInvoke(ActionInvocationFacetForInteractionAbstract.java:314) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.metamodel.facets.actions.interaction.ActionInvocationFacetForInteractionAbstract.invoke(ActionInvocationFacetForInteractionAbstract.java:188) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.runtime.transaction.facets.ActionInvocationFacetWrapTransaction$1.execute(ActionInvocationFacetWrapTransaction.java:57) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.runtime.transaction.facets.ActionInvocationFacetWrapTransaction$1.execute(ActionInvocationFacetWrapTransaction.java:1) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.executeWithinTransaction(IsisTransactionManager.java:205) >>>>>>>>>>> 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:367) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.wrapper.handlers.DomainObjectInvocationHandler.handleActionMethod(DomainObjectInvocationHandler.java:563) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.wrapper.handlers.DomainObjectInvocationHandler.invoke(DomainObjectInvocationHandler.java:229) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.wrapper.proxy.ProxyInstantiatorForJavassist$1.invoke(ProxyInstantiatorForJavassist.java:52) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.risk.domain.model.continuity.RelationshipsBCMInformation_$$_jvstb07_2b.businessContinuityInformation(RelationshipsBCMInformation_$$_jvstb07_2b.java) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.risk.domain.model.continuity.RelationshipsBCMInformationEventHandler.on(RelationshipsBCMInformationEventHandler.java:23) >>>>>>>>>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native >> Method) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >>>>>>>>>>> at java.lang.reflect.Method.invoke(Method.java:606) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.google.common.eventbus.EventSubscriber.handleEvent(EventSubscriber.java:74) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.google.common.eventbus.SynchronizedEventSubscriber.handleEvent(SynchronizedEventSubscriber.java:47) >>>>>>>>>>> at >>>>>>>>>> com.google.common.eventbus.EventBus.dispatch(EventBus.java:322) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.google.common.eventbus.EventBus.dispatchQueuedEvents(EventBus.java:304) >>>>>>>>>>> at >> com.google.common.eventbus.EventBus.post(EventBus.java:275) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.applib.services.eventbus.EventBusService.post(EventBusService.java:202) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.metamodel.facets.InteractionHelper.postEventForCollection(InteractionHelper.java:202) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.metamodel.facets.collections.interaction.CollectionRemoveFromFacetForInteractionAbstract.remove(CollectionRemoveFromFacetForInteractionAbstract.java:103) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.runtime.transaction.facets.CollectionRemoveFromFacetWrapTransaction$1.execute(CollectionRemoveFromFacetWrapTransaction.java:55) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.executeWithinTransaction(IsisTransactionManager.java:160) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.runtime.transaction.facets.CollectionRemoveFromFacetWrapTransaction.remove(CollectionRemoveFromFacetWrapTransaction.java:52) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.metamodel.specloader.specimpl.OneToManyAssociationImpl.removeElement(OneToManyAssociationImpl.java:190) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.wrapper.handlers.DomainObjectInvocationHandler.handleCollectionRemoveFromMethod(DomainObjectInvocationHandler.java:526) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.wrapper.handlers.DomainObjectInvocationHandler.invoke(DomainObjectInvocationHandler.java:218) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.wrapper.proxy.ProxyInstantiatorForJavassist$1.invoke(ProxyInstantiatorForJavassist.java:52) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.architecture.domain.model.business.extensions.businessactor.Person_$$_jvstb07_28.removeFromAssignedToBusinessProcesses(Person_$$_jvstb07_28.java) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.architecture.domain.model.business.BusinessEntity.deleteFromAssignedToBusinessProcesses(BusinessEntity.java:93) >>>>>>>>>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native >> Method) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >>>>>>>>>>> at java.lang.reflect.Method.invoke(Method.java:606) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.metamodel.facets.actions.interaction.ActionInvocationFacetForInteractionAbstract.internalInvoke(ActionInvocationFacetForInteractionAbstract.java:314) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.metamodel.facets.actions.interaction.ActionInvocationFacetForInteractionAbstract.invoke(ActionInvocationFacetForInteractionAbstract.java:188) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.runtime.transaction.facets.ActionInvocationFacetWrapTransaction$1.execute(ActionInvocationFacetWrapTransaction.java:57) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.runtime.transaction.facets.ActionInvocationFacetWrapTransaction$1.execute(ActionInvocationFacetWrapTransaction.java:1) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.executeWithinTransaction(IsisTransactionManager.java:205) >>>>>>>>>>> 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:367) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.wrapper.handlers.DomainObjectInvocationHandler.handleActionMethod(DomainObjectInvocationHandler.java:563) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.wrapper.handlers.DomainObjectInvocationHandler.invoke(DomainObjectInvocationHandler.java:229) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.wrapper.proxy.ProxyInstantiatorForJavassist$1.invoke(ProxyInstantiatorForJavassist.java:52) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.architecture.domain.model.business.extensions.businessactor.Person_$$_jvstb07_28.deleteFromAssignedToBusinessProcesses(Person_$$_jvstb07_28.java) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.architecture.domain.model.business.BusinessProcess.deleteFromRequiredBusinessEntities(BusinessProcess.java:476) >>>>>>>>>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native >> Method) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >>>>>>>>>>> at java.lang.reflect.Method.invoke(Method.java:606) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.metamodel.facets.actions.interaction.ActionInvocationFacetForInteractionAbstract.internalInvoke(ActionInvocationFacetForInteractionAbstract.java:314) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.metamodel.facets.actions.interaction.ActionInvocationFacetForInteractionAbstract.invoke(ActionInvocationFacetForInteractionAbstract.java:188) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.runtime.transaction.facets.ActionInvocationFacetWrapTransaction$1.execute(ActionInvocationFacetWrapTransaction.java:57) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.runtime.transaction.facets.ActionInvocationFacetWrapTransaction$1.execute(ActionInvocationFacetWrapTransaction.java:1) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.runtime.system.transaction.IsisTransactionManager.executeWithinTransaction(IsisTransactionManager.java:205) >>>>>>>>>>> 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:367) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.wrapper.handlers.DomainObjectInvocationHandler.handleActionMethod(DomainObjectInvocationHandler.java:563) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.wrapper.handlers.DomainObjectInvocationHandler.invoke(DomainObjectInvocationHandler.java:229) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.wrapper.proxy.ProxyInstantiatorForJavassist$1.invoke(ProxyInstantiatorForJavassist.java:52) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.architecture.domain.model.business.BusinessProcess_$$_jvstb07_27.deleteFromRequiredBusinessEntities(BusinessProcess_$$_jvstb07_27.java) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> com.xms.framework.risk.integration.tests.continuity.RelationshipsBCMInformationTests.testDeleteColletionWithRelationshipAlsoDeletesRelationshipBCMInformation(RelationshipsBCMInformationTests.java:72) >>>>>>>>>>> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native >> Method) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >>>>>>>>>>> at java.lang.reflect.Method.invoke(Method.java:606) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.integtestsupport.IntegrationTestAbstract$IsisTransactionRule$1.evaluate(IntegrationTestAbstract.java:199) >>>>>>>>>>> at >>>>>>>>>>> >>>>>>>>>> >> org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2$1.evaluate(JUnitRuleMockery2.java:146) >>>>>>>>>>> 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) >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> So, as it could be a quite “common” events-related use case >> (referencing >>>>>>>>>>> the same entity “before” deleting it), could the event be >> dispatched >>>>>>>>>> BEFORE >>>>>>>>>>> sending the object to DN to mark it as deleted? >>>>>>>>>>> >>>>>>>>>>> Or, is there any other way to detect when an object is going to >> be >>>>>>>>>> deleted >>>>>>>>>>> (previously to being deleted, obviously) ? >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Thanks in advance, >>>>>>>>>>> >>>>>>>>>>> Oscar >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>> >>>>>>> >>>>>> >>>>> >>>> >>> >> >> >> >> >>
