Hi Oscar,
I think we can support this use case, but admittedly it isn't - yet - well
documented.
First thing to say is that the "removing" lifecycle code hook method that
you quote isn't actually part of your stacktrace. As it happens, that's
probably a good thing... support for them is a little bit patchy (there
might be bugs).
So, when I look at your stack trace, what's actually happening is that:
* BusinessEntity.deleteFromAssignedToBusinessProcesses(...) is performing a
"removeElement" on a wrapped collection, which fires an event via:
* CollectionRemoveFromFacetForInteractionAbstract, which is handled by
* RelationshipsBCMInformationEventHandler.on
So, what you should do in the handler is to look at the event's "phase".
In fact, you really must pay attention to the phase because it is called
multiple times:
switch(ev,getPhase()) {
case HIDE:
...
case DISABLE:
...
case VALIDATE:
...
case EXECUTING:
...
case EXECUTED:
...
}
As you have probably guessed, your code wants to go into the "EXECUTING"
bit, which is the pre-execute callback. I imagine at the moment it is
firing for all the cases, including the EXECUTED bit, and that's most
likely why JDO then complains at you when you try to access that deleted
object.
Hope that makes sense / works... if not, then we can go round the loop.
Cheers
Dan
Two things about
Rather than do this on the removing() callback, I suggest you emit an event
on the action that The event that
On 12 January 2015 at 18:24, GESCONSULTOR - Óscar Bou <
[email protected]> 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
>
>
>
>