Added ToDoCommandHandler to Axon tutorial, but doesn't work

Hi,

I’ve tried to extend the Axon tutorial with an explicit CommandHandler class, ToDoCommandHandler, and I’ve moved the @CommandHandler annotated method markCompleted to this new class. I’ve also registered the new ToDoCommandHandler class in the application context, but when I run the ToDoItemTest I get the exception:

Tests in error:
testMarkToDoItemAsCompleted(com.foo.axongettingstarted.ToDoItemTest): No handler was subscribed to command [com.foo.axongettingstarted.MarkCompletedCommand]

I’ve added all the classes to this pastie: http://pastie.org/private/fj2jxcyozkj2zl3irobsg
and here is the changed test: http://pastie.org/private/bcwti6vzuevobtws2wirsq

Do you understand why the ToDoCommandHandler isn’t found by Axon?

And also, when I run the ToDoItemRunner then the ToDoItemCompletedEvent doesn’t seem to be fired, probably due to the same issue as the test, that the CommandHandler isn’t invoked.

Hi Viggo,

which version of Axon do you use? A related bug was solved in version 2.0.3 (see http://issues.axonframework.org/youtrack/issue/AXON-144).

Cheers,

Allard

Hi,

I’m using 2.0.3. I was able to get the unit test working by adding the commandhandler to the fixture, but the ToDoItemRunner still got an issue.

Hi Allard,

I’ve debugged a bit further, and it seems that the MarkCompletedEvent isn’t fired because the code never reaches that far! In the ToDoCommandHandler the repository isn’t injected, so when trying to lookup the ToDoItem to mark as completed, it isn’t found!
Is it something about the wiring of the application context that’s not correct?

<axon:command-bus id=“commandBus”/>
<axon:event-bus id=“eventBus”/>

<axon:event-sourcing-repository id=“toDoRepository”
aggregate-type=“org.axonframework.test.sample.ToDoItem”/>

<axon:aggregate-command-handler id=“toDoItemHandler”
aggregate-type=“org.axonframework.test.sample.ToDoItem”
repository=“toDoRepository”
command-bus=“commandBus”/>

<axon:filesystem-event-store id=“eventStore” base-dir=“events”/>

Best regards,
Viggo

Hi Viggo,

looks like you didn’t include your command handler bean in the spring context. You should either declare it as or using component scanning.

Cheers,

Allard

If you look at the spring config, the ToDoCommandHandler is defined as a bean. Anything else I can look into?

You’re saying that the Repository isn’t injected. Do you use Spring’s injection mechanism, or Axon’s (as method parameter)?

Cheers,

Allard

Hi,

if you look at the pastie here, you see that I’ve configured the Spring wiring (and I think it’s correct…), and also added a setter method for the repository injection.

http://pastie.org/private/fj2jxcyozkj2zl3irobsg

Cheers,
Viggo

You may need to tell Spring to deal with the annotations. Try adding a context:annotation-config/ to your spring context.

Cheers,

Allard

Hi Allard, big news:)

I know Spring pretty well, but was maybe a bit lazy and thought that Axon did more “Spring magic” than what could be expected:) After wiring up the repository by setting the property repository which points to the axon:event-sourcing-repository it all started to work pretty well:)

BUT, one thing puzzling me is: Why didn’t I see any evidence of the NullPointerException happening in the ToDoCommandHandler because of the missed injection of the repository? Who swallowed it? Axon?

I would consider this thread as closed as soon as you can explain to me how I can get information about NPEs and such happening :slight_smile:

Regards,
Viggo

Hi Viggo,

that’s what was bothering me as well. I’ve checked the code and found a little issue there with fire-and-forget methods on the Gateway. I have documented the issue in http://issues.axonframework.org/youtrack/issue/AXON-170. Meanwhile, it’s also solved.

Cheers,

Allard

Nice:) thanks for really quick analysis and fix:) It means I have to build Axon myself to get hold of the latest fix, or do you have a 2.0-4-SNAPSHOT version I can depend on?

Regards,
Viggo

You can depend on the snapshot, but might have to configure a snapshot repository. Check out the downloads page on axonframework.org.

Cheers,

Allard

Hi Allard:)

I’ve tested with the latest 2.0.4-SNAPSHOT, removing the injection of the repository from the Spring config to make the NPE happen again, and my assumption then was that some output should be given that it happened, and that I was NOT going to get a Build Successful when executing the ToDoItemRunner…but the build was still successful, and no output given about the NPE. Do you want me to wrap up the project and send it to you to make it easier to reproduce?

Hi Viggo,

that the tests don’t fail doesn’t surprise me. The method you’re using is a fire-and-forget method. This means exceptions are not propagated.
Did you configure logging properly? The SimpleCommandBus logs failures on the error level.

Cheers,

Allard

You’re correct, I will look at my logging configuration!:slight_smile:

Another question related to the Axon Tutorial: I’ve added System.out.println in the @EventHandler annotated method on the ToDoItem class, and it is called both when the CreateToDoItemCommand is called, BUT also when the MarkCompletedCommand is called, isn’t it strange? This line will trigget the ToDoItemCreatedEvent to be fired:
ToDoItem todo = repository.load(command.getTodoId());

any clue? Is it a bug or a feature?

That’s because of the event sourcing. To get current state of the aggregate, axon replays all past events on the aggregate.

Hi Allard, not sure if I understand/agree:)

Let me give an example. Let’s say we extend the ToDo tutorial even more, adding the possibility to perform three different steps on the ToDo before it’s completed, and that each event corresponding to the different command prints out a message that the even has happened, like this:

private void run() {
final String itemId = UUID.randomUUID().toString();
commandGateway.send(new CreateToDoItemCommand(itemId, “Need to do this”));
commandGateway.send(new PerformToDoStep1Command(itemId, “Step 1 of ToDo”));
commandGateway.send(new PerformToDoStep2Command(itemId, “Step 2 of ToDo”));
commandGateway.send(new PerformToDoStep3Command(itemId, “Step 3 of ToDo”));
commandGateway.send(new MarkCompletedCommand(itemId));
}

The output I get is this (from the event handlers):

We’ve got something to do: Need to do this (19d7cf6a-d252-4e7d-9d85-51f7249fd13e)
We’ve got something to do: Need to do this (19d7cf6a-d252-4e7d-9d85-51f7249fd13e)
We’ve completed step 1: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e
We’ve got something to do: Need to do this (19d7cf6a-d252-4e7d-9d85-51f7249fd13e)
We’ve completed step 2: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e
We’ve got something to do: Need to do this (19d7cf6a-d252-4e7d-9d85-51f7249fd13e)
We’ve completed step 3: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e
We’ve got something to do: Need to do this (19d7cf6a-d252-4e7d-9d85-51f7249fd13e)
We’ve completed a task: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e

BUT, my assumption is that I should get output like this:

We’ve got something to do: Need to do this (19d7cf6a-d252-4e7d-9d85-51f7249fd13e)
We’ve completed step 1: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e
We’ve completed step 2: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e
We’ve completed step 3: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e
We’ve completed a task: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e

Why is always the create event message shown between each new event arriving, and if you’re statement is correct (that for each new event arriving it should replay everything from the past), then the output should look like this:
We’ve got something to do: Need to do this (19d7cf6a-d252-4e7d-9d85-51f7249fd13e)

We’ve got something to do: Need to do this (19d7cf6a-d252-4e7d-9d85-51f7249fd13e)
We’ve completed step 1: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e

We’ve got something to do: Need to do this (19d7cf6a-d252-4e7d-9d85-51f7249fd13e)
We’ve completed step 1: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e
We’ve completed step 2: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e

We’ve got something to do: Need to do this (19d7cf6a-d252-4e7d-9d85-51f7249fd13e)
We’ve completed step 1: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e
We’ve completed step 2: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e
We’ve completed step 3: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e

We’ve got something to do: Need to do this (19d7cf6a-d252-4e7d-9d85-51f7249fd13e)
We’ve completed step 1: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e
We’ve completed step 2: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e
We’ve completed step 3: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e
We’ve completed a task: 19d7cf6a-d252-4e7d-9d85-51f7249fd13e

So, am I missing some “basic event sourcing knowledge”, or have I implemented something wrong, is it a bug somewhere, or? :slight_smile:

Best regards,
Viggo

H Viggo,

the last output you mention is the one I would expect. Whether it’s a bug or not really depends in the implementation and configuration.
Which event store do you use? What does you ToDoItem code look like?

I you can share some code & config, I can have a look at it.

Cheers,

Allard

Hi:)

I find it strange that you expect the last output. Wouldn’t the “event history” of a ToDo item contain too many events then, making it hard to figure out what happened? I would assume that only the “pure business related events” were recorded to the event store. Or, maybe they are, but Axon has to reply them? hmm…please ellaborate:) Well, I have a zip’d version of my project, how do you want it? Email? drop box URL?