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 < [email protected]> wrote: > Hi, Dan and Jeroen for your pointing me towards those examples. > > As I'm seeing on Estatio, event publishing is made through an > @ActionInteraction annotation, which requires to always delete entities by > means of that action. > > I attached the event post to the "removing" framework method for > publishing the event every time an object is going to be delete, > independently it's made through a custom action or through > "container().remove()". > That way, I can be sure the business logic is going to be executed ALWAYS > despite how the other developers implement this. > > We can re-implement all this event logic for assuring that we always > delete this kind of domain objects through that action, but I thought > previous solution would work better, as it's directly attached to the > object's lifecycle. > > In previous threads we talked about the option of being notified of > framework's events. > > Perhaps implementing a @DomainObjectInteraction annotation in a similar > way to @ActionInteraction could have sense. > > What do you think? > > Thanks, > > Oscar > > > > > > > > > El 12/1/2015, a las 20:38, Jeroen van der Wal <[email protected]> > 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 <[email protected]> > wrote: > > Hi Oscar, > > I think we can support this use case, but admittedly it isn't - yet - well > documented. > > First thing to say is that the "removing" lifecycle code hook method that > you quote isn't actually part of your stacktrace. As it happens, that's > probably a good thing... support for them is a little bit patchy (there > might be bugs). > > So, when I look at your stack trace, what's actually happening is that: > * BusinessEntity.deleteFromAssignedToBusinessProcesses(...) is performing a > "removeElement" on a wrapped collection, which fires an event via: > * CollectionRemoveFromFacetForInteractionAbstract, which is handled by > * RelationshipsBCMInformationEventHandler.on > > So, what you should do in the handler is to look at the event's "phase". > In fact, you really must pay attention to the phase because it is called > multiple times: > > switch(ev,getPhase()) { > case HIDE: > ... > case DISABLE: > ... > case VALIDATE: > ... > case EXECUTING: > ... > case EXECUTED: > ... > } > > As you have probably guessed, your code wants to go into the "EXECUTING" > bit, which is the pre-execute callback. I imagine at the moment it is > firing for all the cases, including the EXECUTED bit, and that's most > likely why JDO then complains at you when you try to access that deleted > object. > > Hope that makes sense / works... if not, then we can go round the loop. > > Cheers > Dan > > > > > > > > Two things about > Rather than do this on the removing() callback, I suggest you emit an event > on the action that The event that > > On 12 January 2015 at 18:24, GESCONSULTOR - Óscar Bou < > [email protected]> 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. > > > > > >
