Hi Oscar, Thanks for these references. The key thing you said that's helped me was:
> All our Event Handlers are located on previously subscribed Services, so they will be in memory. If they need any Domain Object, they query the repositories on the event handler. Obviously, multiple Event Handlers can be registered for one kind of Event. That to me seems like the correct solution... don't have individual entities subscribing to events, instead have the domain service(s) act as the subscriber. As you say, when an event is received, have the service identify the impacted domain entities and then call them. That's such an obvious approach I feel a bit embarrassed for going down the wrong path. Anyway... I'm going to refactor the EventBusService and take out that subscriber loading/hint stuff. And, then I'll implement a simplified version of the @PostsEvent annotation, also without the hint/loading stuff. ~~~ With respect to Axon, I know you mentioned it before, and I took a look through its getting started guide. There's rather a lot of boilerplate in there, which - I've always argued - is liable to slow down / inhibit the development of a ubiquitous language. Since you use Axon, you can tell me if I'm mistaken in this or not. I don't know that the CommandHandler stuff in Axon makes much sense from an Isis standpoint; our RO viewer gives us something like that for free, I would've though. Neither am I certain that an EventStore is the best persistence mechanism for the majority of enterprise apps that get built. But being able to raise events *does* make sense to me as a way of decoupling chunks of business logic; hence the EventBusService. Cheers Dan ~~~~ On 30 June 2013 11:38, GESCONSULTOR - Óscar Bou <[email protected]>wrote: > Opss!!! Let me resend it. The previous one did not contained the proper > links. > > Just to clarify, when a Command has the @TargetAggregateIdentifier > annotation on one of its fields, the Command Bus will previously load that > Entity from the Repository and, after that, will invoke the command on that > Entity. More details on [2]. > > On the default implementation, the Domain Entity "identifier" field (which > must be compared against the @TargetAggregateIdentifier) is also annotated > with @AggregateIdentifier. The used Repository only needs a "findById" > method for locating it and dispatch the command (it's also possible to > query specifying also the expected "version", but this is out of scope). > > > Hope this helps again, > > Oscar > > > > ---- > > Hi, Dan. > > I'm going to adopt your style of not mixing links with the post. > > We are currently using as our Domain Event Bus one of the implementations > available on the Axon Framework [1]. > > As it's a CQRS framework, there is a difference between Command Handlers > and Event Handlers. > > All our Event Handlers are located on previously subscribed Services, so > they will be in memory. If they need any Domain Object, they query the > repositories on the event handler. Obviously, multiple Event Handlers can > be registered for one kind of Event. > > For Command Handlers, it's possible to pass a field which contains the > Aggregate Identifier (annotated with @TargetAggregateIdentifier), and also > to annotate as a @CommandHandler a constructor method (if the command's > responsibility is to create a Domain Entity). Note that only one Command > Handler can be registered for each kind of command. If more than one is > present, only the last one found will be notified by the Command Bus about > the Command dispatched (detailed info on [2]). > > There is detailed documentation about Command Handlers [2] (including the > interface for sending Commands) and Event Handlers [3] (they cannot be > sent, just received) available. > > There's a new quickstart tutorial on Axon with a small example based also > on a ToDo domain entity [4]. > > Hope this helps, > > Oscar > > > > [1] http://www.axonframework.org/ > [2] http://www.axonframework.org/docs/2.0/command-handling.html > [3] http://www.axonframework.org/docs/2.0/event-processing.html > [4] http://www.axonframework.org/axon-2-quickstart-guide/ > > > > El 30/06/2013, a las 10:38, Dan Haywood <[email protected]> > escribió: > > > Folks, > > Looking for opinions here. > > > > I recently committed an EventBusService, so that one can programmatically > > post an event via Guava's EventBus: > > > > public void setStartDate(LocalDate dt) { > > this.setStartDate = dt; > > eventBusService.post(new StartDateChangedEvent(this, oldValue, > > newValue), getFoos(), getBars(), ...) > > } > > > > Guava then invokes any object that has a method annotated @Subscribe > > accepting the event type: > > > > @Subscribe > > public void handle(StartDateChangedEvent ev) { ... } > > > > It's trivially easy for domain objects to register themselves with the > > event bus. In their injectXxx method, just do the register: > > > > public void injectEventBusService(EventBusService ebs) { > > this.eventBusService = ebs; > > ebs.register(this); > > } > > > > > > I'm reasonably happy with all of this, I think, though the downside is > that > > the publisher needs to ensure that any potential subscribers are > in-memory > > so that they get notified. This is the purpose of the getFoos() and > > getBars() calls passed in to post(...); it's a hint for Isis to bring the > > objects in these collections into memory. > > > > Also, strictly speaking, the publication of the event should be in > > modifyStartDate(...) rather than setStartDate(...) to avoid unintended > > side-effects with JDO when it calls setStartDate to recreate or delete > the > > object. In fact, the JDO objectstore does protect against this, but it's > > all somewhat hacky. > > > > > > ~~~ > > > > I'm now thinking about introducing an annotation to publish the event, > eg: > > > > @PostsEvent(type=StartDateChangedEvent.class, subscribers={"foos", > "bars"}) > > public LocalDate getStartDate() { ... } > > public void setStartDate(LocalDate dt) { ... } > > > > > > where the "foos" and "bars" are - again - the collections of the > publishing > > object to be loaded into memory first. > > > > Or, as a refinement: > > > > @PostsEvent(type=StartDateChangedEvent.class, > > subscribersPolicy=StartDateSubscribersPolicy.class) > > public LocalDate getStartDate() { ... } > > public void setStartDate(LocalDate dt) { ... } > > > > would allow a strategy object to be specified to allow arbitrary > subscriber > > objects to be loaded. > > > > ~~~ > > > > I don't think any of this is too difficult to implement, but is it worth > > it? Or is this subscriber loading hint basically telling me that the > > approach is fundamentally flawed? > > > > Opinions welcome > > > > Thx > > Dan > >
