Replay events from a FileSystemEventStore without Clusters

Hi all.

I need to demonstrate the event sourcing capabilities of Axon in my POC prototype, and that includes replaying events in case of a failure. Since this is only a prototype I am using the most simple infrastructure possible, i.e. no database, no queues, only a simple war deployed on a tomcat.

So my question is, how can I replay events from a FileSystemEventStore, and without using the ReplayingCluster?

Or is there a way to wrap a ReplayingCluster around a FileSystemEventStore?

Thanks in advance.

Cheers.

Somehow related to this, While I was searching this group I read somewhere that “returning values from commands in aggregates is a bad practice”. Why is that? My prototype relies on this, my usecase is somehow like this:

  • User (U) invokes a URL to a Webbapp (W)
  • W invokes a Command © that is handled by a Aggregate (A)
  • A raises a Event (E) that is stored in the EventStore
  • A invokes a Handler (H) that executes the intention of C
  • H responds with result ® to A
  • A sets R as response in C
  • C responds to W
  • W responds to U

lets say that the first request from U (UR) returns 10 lines (L1-10). UR1 was stored as E1.

  • U marks a L1 as “OK” —> invokes UR2, stores as E2
  • U marks a L2 as “OK” —> invokes UR3, stores as E3
  • U marks a L3 as “NOK” —> invokes UR4, stores as E4

SYSTEM CRASHES —> U still as to mark L4-L10

SYSTEM RECOVERS —> replay E1-E4

  • U resumes its work where it was before the crash

So to this I will rely on the C on the A to return a R to the U.

Is that feasible?

Thanks.

Hi Antonio,

the FilesystemEventStore doesn’t support replaying. You can only store and load events for a single aggregate. I believe it also supports snapshots, but that’s really it.
You’re probably better off using the JpaEventStore with an hsql database. At least, you’ll have all the options.

Hope this helps.
Cheers,

Allard

Hi,

it’s not really clear to me how ‘H’ executes the intent of C. That’s really the job of A. Or is the handler a command handler inside the aggregate?
It is seen by some to be good practice not to rely on return values from commands. Especially in distributed systems, it’s unreliable and slow to have to wait for the reply of a command. However, in Axon, sending a return value is really easy. In your command handler, simply define a return type and return the value you want. The callback will receive this value as the parameter of the onSuccess() method.
However, if the system crashes (assuming the transaction has just been committed, but return value was not yet sent), the return value will never reach the sender. When using the distributed command bus, the sender will receive an exception, telling it that the host executing the command was lost. If your commands are idempotent (or if you have some other means of detecting duplicate commands), you can simply send the command again to some other node.

Cheers,

Allard

Hi again…

Actually what I really wanted is load events for a single aggregate, so I just did it with the FS Store. We are not planning (at least not for now) to have a full-fledged EP system, but instead using EP for recovery on “short” term tasks (like I described in “SYSTEM RECOVERS —> replay E1-E4”) so when such task finishes the Events associated wit it are discarded.

Cheers.

Hi,

it’s not really clear to me how ‘H’ executes the intent of C. That’s really the job of A. Or is the handler a command handler inside the aggregate?

Actually I’m banging my head against several walls with this. Basically the question is, where should I put the “real” work inside the architecture? Aggregates, EventHandlers, CommandHandlers, Sagas? I actually already did it in several ways but none feel “natural” to me and they feel too complex… Let me try one example with my “audit” prototype: after the Aggregate is created with a CreateAudit (that only sets it’s Id) the user invokes a StartAudit

`

@CommandHandler
public Object startAudit(AuditStartCommand command) throws Exception {
Object audit = getAuditObject(command.getId());
apply(new AuditStartedEvent(command.getId(), audit));
return audit ;
}

@EventSourcingHandler
public void on(AuditStartedEvent event) throws Exception {
this.state = “STARTED”;
this.audit = event.getData();
}

`

So the question is, where that getAuditObject(Id)`` gets it’s data from:

A injected service bean?

`
private Object getAuditObject(String id) {
return service.get(id);
}

`

Dispatch it as a command?

`
private Object getAuditObject(String id) {
return commandGateway.sendAndWait(new RetrieveAuditObject(id));
}

`

Dispatch it as a event?

private Object getAuditObject(String id) { eventTemplate.publishEvent(new RetrieveAuditObject(id));return something…`
``}

`

This last one doesn’t look too useful, but what if I actually need to model this action as a Saga?

Actually, Sagas is what I’m struggling now, but I’ll write another post about it.

Once again, thanks for your great support.

Cheers.

Hi Antonio,

When a command handler requires certain information, it is almost always best to provide it as part of the command itself. If the information is too large to pass in its entirety, you can consider giving the aggregate access to a service (in ddd terms a repository) that can provide access to the required instances.
The service can be injected by adding it as parameter to the @CommandHandler annotation. If it’s a Spring bean, Axon will inject it (if there is exactly one instance in the application context).

Aggregates themselves will never send out commands directly.

Cheers,

Allard

PS. In my training, I extensively cover the modeling aspects of cqrs. I would definitely recommend attending it. See http://www.trifork.nl/en/home/training/axon-immersion.html

OK, got it as well. However… why to inject the service as a parameter in the method and not in the Aggregate itself as “usual”? (the way I posted in another threas)

Cheers.

BTW, funny enough I had sent that link to my boss a couple of hours before you posted it :slight_smile: Let’s see what direction we are going to take after the “prototype” phase, I may try to push for it…

Regular dependency injection is fine. Especially if you use a prototype bean.

Cheers,

Allard