You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@isis.apache.org by GESCONSULTOR - Óscar Bou <o....@gesconsultor.com> on 2015/01/12 19:24:16 UTC

Domain Objects Lifecycle and Events published on "removing"

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




Re: Domain Objects Lifecycle and Events published on "removing"

Posted by GESCONSULTOR <o....@gesconsultor.com>.
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 <da...@haywood-associates.co.uk> 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 <
> o.bou@gesconsultor.com> 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 <
>>> o.bou@gesconsultor.com> 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 <dan@haywood-associates.co.uk
>> <ma...@haywood-associates.co.uk>> 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 <
>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <
>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <
>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <dan@haywood-associates.co.uk
>> <ma...@haywood-associates.co.uk>> escribió:
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> On 13 January 2015 at 17:19, GESCONSULTOR - Óscar Bou <
>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <
>> dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>>
>> 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 <
>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <jeroen@stromboli.it
>> <ma...@stromboli.it>> 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 <
>> dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>>
>>>>>>>>> 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 <
>>>>>>>>>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>> 
>>>>>> 
>>>>> 
>>>> 
>>> 
>> 
>> 
>> 
>> 
>> 

Re: Domain Objects Lifecycle and Events published on "removing"

Posted by Dan Haywood <da...@haywood-associates.co.uk>.
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 <
o.bou@gesconsultor.com> 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 <
> o.bou@gesconsultor.com> 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 <dan@haywood-associates.co.uk
> <ma...@haywood-associates.co.uk>> 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 <
> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <
> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <
> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <dan@haywood-associates.co.uk
> <ma...@haywood-associates.co.uk>> escribió:
> >>>>>
> >>>>>
> >>>>>
> >>>>> On 13 January 2015 at 17:19, GESCONSULTOR - Óscar Bou <
> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <
> dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>>
> 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 <
> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <jeroen@stromboli.it
> <ma...@stromboli.it>> 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 <
> dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>>
> >>>>>>> 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 <
> >>>>>>>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>
> >>>>>
> >>>>
> >>>
> >>
> >
>
>
>
>
>

Re: Domain Objects Lifecycle and Events published on "removing"

Posted by GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>.
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 <o....@gesconsultor.com> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>> escribió:
>>>>> 
>>>>> 
>>>>> 
>>>>> On 13 January 2015 at 17:19, GESCONSULTOR - Óscar Bou <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <jeroen@stromboli.it <ma...@stromboli.it>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>>
>>>>>>> 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 <
>>>>>>>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>> 
>>>>> 
>>>> 
>>> 
>> 
> 





Re: Domain Objects Lifecycle and Events published on "removing"

Posted by GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>.
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 <da...@haywood-associates.co.uk> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>> escribió:
>>>> 
>>>> 
>>>> 
>>>> On 13 January 2015 at 17:19, GESCONSULTOR - Óscar Bou <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <jeroen@stromboli.it <ma...@stromboli.it>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>>
>>>>>> 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 <
>>>>>>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>> 
>>>>> 
>>>>> 
>>>>> Óscar Bou Bou
>>>>> Responsable de Producto
>>>>> Auditor Jefe de Certificación ISO 27001 en BSI
>>>>> CISA, CRISC, APMG ISO 20000, ITIL-F
>>>>> 
>>>>> <contactenos.html.gif>   902 900 231 / 620 267 520
>>>>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
>>>>> 
>>>>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
>>>>> 
>>>>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
>>>>> 
>>>>> <gesconsultor_logo_blue_email.png>
>>>>> 
>>>>> 
>>>>> 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.
>>>> 
>>>> 
>>>> Óscar Bou Bou
>>>> Responsable de Producto
>>>> Auditor Jefe de Certificación ISO 27001 en BSI
>>>> CISA, CRISC, APMG ISO 20000, ITIL-F
>>>> 
>>>> <contactenos.html.gif>   902 900 231 / 620 267 520
>>>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
>>>> 
>>>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
>>>> 
>>>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
>>>> 
>>>> <gesconsultor_logo_blue_email.png>
>>>> 
>>>> 
>>>> 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.
>>> 
>>> 
>>> Óscar Bou Bou
>>> Responsable de Producto
>>> Auditor Jefe de Certificación ISO 27001 en BSI
>>> CISA, CRISC, APMG ISO 20000, ITIL-F
>>> 
>>> <contactenos.html.gif>   902 900 231 / 620 267 520
>>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
>>> 
>>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
>>> 
>>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
>>> 
>>> <gesconsultor_logo_blue_email.png>
>>> 
>>> 
>>> 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.
>> 
>> 
>> Óscar Bou Bou
>> Responsable de Producto
>> Auditor Jefe de Certificación ISO 27001 en BSI
>> CISA, CRISC, APMG ISO 20000, ITIL-F
>> 
>> <contactenos.html.gif>   902 900 231 / 620 267 520
>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
>> 
>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
>> 
>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
>> 
>> <gesconsultor_logo_blue_email.png>
>> 
>> 
>> 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.
> 
> 
> Óscar Bou Bou
> Responsable de Producto
> Auditor Jefe de Certificación ISO 27001 en BSI
> CISA, CRISC, APMG ISO 20000, ITIL-F
> 
> <contactenos.html.gif>   902 900 231 / 620 267 520
> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
> 
> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
> 
> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
> 
> <gesconsultor_logo_blue_email.png>
> 
> 
> 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.


Ó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://www.twitter.com/oscarbou>

   http://es.linkedin.com/in/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.






Re: Domain Objects Lifecycle and Events published on "removing"

Posted by Dan Haywood <da...@haywood-associates.co.uk>.
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


On 17 January 2015 at 16:17, GESCONSULTOR - Óscar Bou <
o.bou@gesconsultor.com> 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
>
> [2]
> 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
>
> [4] http://www.axonframework.org
>
> [5]
> 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
>
> [7]
> 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 <
> o.bou@gesconsultor.com> 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 <
> o.bou@gesconsultor.com> 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
>
>
> El 13/1/2015, a las 18:39, Dan Haywood <da...@haywood-associates.co.uk>
> escribió:
>
>
>
> On 13 January 2015 at 17:19, GESCONSULTOR - Óscar Bou <
> o.bou@gesconsultor.com> 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 <da...@haywood-associates.co.uk>
>> 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
>> [2] https://issues.apache.org/jira/browse/ISIS-550
>> [3] https://issues.apache.org/jira/browse/ISIS-1005
>>
>>
>> ~~~~~~~~~~~~~
>>
>>
>> On 13 January 2015 at 14:06, GESCONSULTOR - Óscar Bou <
>> o.bou@gesconsultor.com> 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 <je...@stromboli.it>
>>> 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
>>>
>>> HTH
>>>
>>> On 12 January 2015 at 19:38, Dan Haywood <da...@haywood-associates.co.uk>
>>> 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 <
>>> o.bou@gesconsultor.com> 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
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> Óscar Bou Bou
>>> Responsable de Producto
>>> Auditor Jefe de Certificación ISO 27001 en BSI
>>> CISA, CRISC, APMG ISO 20000, ITIL-F
>>>
>>> <contactenos.html.gif>   902 900 231 / 620 267 520
>>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou
>>>
>>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou
>>>
>>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/>
>>>
>>> <gesconsultor_logo_blue_email.png>
>>>
>>>
>>> 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.
>>>
>>
>>
>> *Óscar Bou Bou*
>> Responsable de Producto
>> Auditor Jefe de Certificación ISO 27001 en BSI
>> CISA, CRISC, APMG ISO 20000, ITIL-F
>>
>> <contactenos.html.gif>   902 900 231 / 620 267 520
>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou
>>
>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou
>>
>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/>
>>
>> <gesconsultor_logo_blue_email.png>
>>
>>
>> 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.
>>
>
>
> *Óscar Bou Bou*
> Responsable de Producto
> Auditor Jefe de Certificación ISO 27001 en BSI
> CISA, CRISC, APMG ISO 20000, ITIL-F
>
> <contactenos.html.gif>   902 900 231 / 620 267 520
> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou
>
> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou
>
> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/>
>
> <gesconsultor_logo_blue_email.png>
>
>
> 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.
>
>
>
> *Óscar Bou Bou*
> Responsable de Producto
> Auditor Jefe de Certificación ISO 27001 en BSI
> CISA, CRISC, APMG ISO 20000, ITIL-F
>
> <contactenos.html.gif>   902 900 231 / 620 267 520
> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou
>
> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou
>
> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/>
>
> <gesconsultor_logo_blue_email.png>
>
>
> 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.
>
>
>
> *Ó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.
>
>
>
>
>
>

Re: Domain Objects Lifecycle and Events published on "removing"

Posted by GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>.
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

[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

[5] 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

[7] 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 <o....@gesconsultor.com> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>> escribió:
>>> 
>>> 
>>> 
>>> On 13 January 2015 at 17:19, GESCONSULTOR - Óscar Bou <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <jeroen@stromboli.it <ma...@stromboli.it>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>>
>>>>> 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 <
>>>>>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>> 
>>>> 
>>>> 
>>>> Óscar Bou Bou
>>>> Responsable de Producto
>>>> Auditor Jefe de Certificación ISO 27001 en BSI
>>>> CISA, CRISC, APMG ISO 20000, ITIL-F
>>>> 
>>>> <contactenos.html.gif>   902 900 231 / 620 267 520
>>>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
>>>> 
>>>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
>>>> 
>>>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
>>>> 
>>>> <gesconsultor_logo_blue_email.png>
>>>> 
>>>> 
>>>> 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.
>>> 
>>> 
>>> Óscar Bou Bou
>>> Responsable de Producto
>>> Auditor Jefe de Certificación ISO 27001 en BSI
>>> CISA, CRISC, APMG ISO 20000, ITIL-F
>>> 
>>> <contactenos.html.gif>   902 900 231 / 620 267 520
>>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
>>> 
>>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
>>> 
>>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
>>> 
>>> <gesconsultor_logo_blue_email.png>
>>> 
>>> 
>>> 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.
>> 
>> 
>> Óscar Bou Bou
>> Responsable de Producto
>> Auditor Jefe de Certificación ISO 27001 en BSI
>> CISA, CRISC, APMG ISO 20000, ITIL-F
>> 
>> <contactenos.html.gif>   902 900 231 / 620 267 520
>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
>> 
>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
>> 
>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
>> 
>> <gesconsultor_logo_blue_email.png>
>> 
>> 
>> 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.
> 
> 
> Óscar Bou Bou
> Responsable de Producto
> Auditor Jefe de Certificación ISO 27001 en BSI
> CISA, CRISC, APMG ISO 20000, ITIL-F
> 
> <contactenos.html.gif>   902 900 231 / 620 267 520
> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
> 
> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
> 
> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
> 
> <gesconsultor_logo_blue_email.png>
> 
> 
> 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.


Ó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://www.twitter.com/oscarbou>

   http://es.linkedin.com/in/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.






Re: Domain Objects Lifecycle and Events published on "removing"

Posted by GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>.
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 <o....@gesconsultor.com> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>> escribió:
>> 
>> 
>> 
>> On 13 January 2015 at 17:19, GESCONSULTOR - Óscar Bou <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <jeroen@stromboli.it <ma...@stromboli.it>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>>
>>>> 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 <
>>>>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>> 
>>> 
>>> 
>>> Óscar Bou Bou
>>> Responsable de Producto
>>> Auditor Jefe de Certificación ISO 27001 en BSI
>>> CISA, CRISC, APMG ISO 20000, ITIL-F
>>> 
>>> <contactenos.html.gif>   902 900 231 / 620 267 520
>>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
>>> 
>>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
>>> 
>>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
>>> 
>>> <gesconsultor_logo_blue_email.png>
>>> 
>>> 
>>> 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.
>> 
>> 
>> Óscar Bou Bou
>> Responsable de Producto
>> Auditor Jefe de Certificación ISO 27001 en BSI
>> CISA, CRISC, APMG ISO 20000, ITIL-F
>> 
>> <contactenos.html.gif>   902 900 231 / 620 267 520
>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
>> 
>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
>> 
>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
>> 
>> <gesconsultor_logo_blue_email.png>
>> 
>> 
>> 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.
> 
> 
> Óscar Bou Bou
> Responsable de Producto
> Auditor Jefe de Certificación ISO 27001 en BSI
> CISA, CRISC, APMG ISO 20000, ITIL-F
> 
> <contactenos.html.gif>   902 900 231 / 620 267 520
> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
> 
> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
> 
> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
> 
> <gesconsultor_logo_blue_email.png>
> 
> 
> 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.


Ó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://www.twitter.com/oscarbou>

   http://es.linkedin.com/in/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.






Re: Domain Objects Lifecycle and Events published on "removing"

Posted by GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>.
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 <da...@haywood-associates.co.uk> escribió:
> 
> 
> 
> On 13 January 2015 at 17:19, GESCONSULTOR - Óscar Bou <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <jeroen@stromboli.it <ma...@stromboli.it>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>>
>>> 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 <
>>>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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
>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>> 
>> 
>> 
>> Óscar Bou Bou
>> Responsable de Producto
>> Auditor Jefe de Certificación ISO 27001 en BSI
>> CISA, CRISC, APMG ISO 20000, ITIL-F
>> 
>> <contactenos.html.gif>   902 900 231 / 620 267 520
>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
>> 
>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
>> 
>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
>> 
>> <gesconsultor_logo_blue_email.png>
>> 
>> 
>> 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.
> 
> 
> Óscar Bou Bou
> Responsable de Producto
> Auditor Jefe de Certificación ISO 27001 en BSI
> CISA, CRISC, APMG ISO 20000, ITIL-F
> 
> <contactenos.html.gif>   902 900 231 / 620 267 520
> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
> 
> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
> 
> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
> 
> <gesconsultor_logo_blue_email.png>
> 
> 
> 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.


Ó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://www.twitter.com/oscarbou>

   http://es.linkedin.com/in/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.






Re: Domain Objects Lifecycle and Events published on "removing"

Posted by Dan Haywood <da...@haywood-associates.co.uk>.
On 13 January 2015 at 17:19, GESCONSULTOR - Óscar Bou <
o.bou@gesconsultor.com> 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 <da...@haywood-associates.co.uk>
> 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
> [2] https://issues.apache.org/jira/browse/ISIS-550
> [3] https://issues.apache.org/jira/browse/ISIS-1005
>
>
> ~~~~~~~~~~~~~
>
>
> On 13 January 2015 at 14:06, GESCONSULTOR - Óscar Bou <
> o.bou@gesconsultor.com> 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 <je...@stromboli.it>
>> 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
>>
>> HTH
>>
>> On 12 January 2015 at 19:38, Dan Haywood <da...@haywood-associates.co.uk>
>> 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 <
>> o.bou@gesconsultor.com> 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
>>
>>
>>
>>
>>
>>
>>
>> Óscar Bou Bou
>> Responsable de Producto
>> Auditor Jefe de Certificación ISO 27001 en BSI
>> CISA, CRISC, APMG ISO 20000, ITIL-F
>>
>> <contactenos.html.gif>   902 900 231 / 620 267 520
>> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou
>>
>> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou
>>
>> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/>
>>
>> <gesconsultor_logo_blue_email.png>
>>
>>
>> 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.
>>
>
>
> *Ó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.
>
>
>
>
>
>

Re: Domain Objects Lifecycle and Events published on "removing"

Posted by GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>.
ok, Dan.

 But that would include something like @DomainObjectInteraction, in order to customize the event (and the event handler) ?


> El 13/1/2015, a las 15:21, Dan Haywood <da...@haywood-associates.co.uk> 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 <o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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 <jeroen@stromboli.it <ma...@stromboli.it>> 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 <dan@haywood-associates.co.uk <ma...@haywood-associates.co.uk>>
>> 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 <
>>> o.bou@gesconsultor.com <ma...@gesconsultor.com>> 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
>>>> 
>>>> 
>>>> 
>>>> 
>>> 
> 
> 
> Óscar Bou Bou
> Responsable de Producto
> Auditor Jefe de Certificación ISO 27001 en BSI
> CISA, CRISC, APMG ISO 20000, ITIL-F
> 
> <contactenos.html.gif>   902 900 231 / 620 267 520
> <Pasted Graphic 1.tiff>   http://www.twitter.com/oscarbou <http://www.twitter.com/oscarbou>
> 
> <gesdatos-software.gif>   http://es.linkedin.com/in/oscarbou <http://es.linkedin.com/in/oscarbou>
> 
> <blog.png>   http://www.GesConsultor.com <http://www.gesconsultor.com/> 
> 
> <gesconsultor_logo_blue_email.png>
> 
> 
> 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.


Ó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://www.twitter.com/oscarbou>

   http://es.linkedin.com/in/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.






Re: Domain Objects Lifecycle and Events published on "removing"

Posted by Dan Haywood <da...@haywood-associates.co.uk>.
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
[2] https://issues.apache.org/jira/browse/ISIS-550
[3] https://issues.apache.org/jira/browse/ISIS-1005


~~~~~~~~~~~~~


On 13 January 2015 at 14:06, GESCONSULTOR - Óscar Bou <
o.bou@gesconsultor.com> 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 <je...@stromboli.it>
> 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
>
> HTH
>
> On 12 January 2015 at 19:38, Dan Haywood <da...@haywood-associates.co.uk>
> 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 <
> o.bou@gesconsultor.com> 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
>
>
>
>
>
>
>
> Ó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.
>
>
>
>
>
>

Re: Domain Objects Lifecycle and Events published on "removing"

Posted by GESCONSULTOR - Óscar Bou <o....@gesconsultor.com>.
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 <je...@stromboli.it> 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
> 
> HTH
> 
> On 12 January 2015 at 19:38, Dan Haywood <da...@haywood-associates.co.uk>
> 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 <
>> o.bou@gesconsultor.com> 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
>>> 
>>> 
>>> 
>>> 
>> 


Ó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://www.twitter.com/oscarbou>

   http://es.linkedin.com/in/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.






Re: Domain Objects Lifecycle and Events published on "removing"

Posted by Jeroen van der Wal <je...@stromboli.it>.
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

HTH

On 12 January 2015 at 19:38, Dan Haywood <da...@haywood-associates.co.uk>
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 <
> o.bou@gesconsultor.com> 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
> >
> >
> >
> >
>

Re: Domain Objects Lifecycle and Events published on "removing"

Posted by Dan Haywood <da...@haywood-associates.co.uk>.
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 <
o.bou@gesconsultor.com> 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
>
>
>
>