These are my first steps at using Axon. Intriguing. I get it. Now let’s make it work. So I created a spring based skeleton project using Initializr, and similar to the “getting started” I created two commands, two events, an aggregate, a projection, a rest controller, and unit tests. All good. However:
The unit test run but fail to actually instantiate the aggregate
The rest controller starts but a GET request does not trigger it
So I’ve writting a Spring @Component, but it is created before the handlers in the aggregate are registered.
Nice that you started using AxonFramework. From the post here I cannot judge what is wrong with the implementation, maybe you can share the repository? Other than that we do have some code samples that may be of help. Or our hotel demo application. I hope to be able to get you up to speed soon!
As Yvonne said, it’s pretty hard to come up with responses without looking into the code!
Other than what she already shared, let me try to dive into some of the problems you mentioned with lots of assumptions from my side =)
Unit Tests
Axon Framework provides something called AggregateTestFixture. This is what you should use for testing it!
You can’t write ‘normal’ unit tests for it because your Aggregate has to be build from commands and events, that’s why this Fixture is there, to help! (There are other similar Fixtures to help with different components as well)
Not sure what you meant by Rest Controller starts but a GET does not trigger it
Here it is also not clear what is this @Component used for and where do you want to use it! Do you want to use a Component inside the Aggregate perhaps? If that is the case, you should inject the Component on the @CommandHandler annotated method! If that is not the case, I would need more context to help.
I moved my experiment code into a public bitbucket repo. It would be great if you to get me through these first hurdles As said, it is nothing more then the getting started except using some other domain concepts.
The GET endpoint is commented out but looks good you just need to change it to the correct Query and expected payload:
@GetMapping("/open")
public CompletableFuture<List<RosterBlock>> findOpenRosterBlocks() {
return queryGateway.query(new FindAllOrderedProductsQuery(), ResponseTypes.multipleInstancesOf(Order.class));
}
This expects a QueryHandler in the projection class which looks like this:
@QueryHandler
public List<Order> getClosedRosterBlockIds(FindAllOrderedProductsQuery query) {
//TODO: implement
}
probably it did not work because the ActiveRosterBlocksProjection is not a Component and it could not find a QueryHandler annotated method for that query with the expected return type.
Of course! The givens need to be events and not commands. See, that is where the logic needs to sink in. Fixed. And thank you!
The projection in the getting started is also not a component, but that REST thing seems to be a tomcat problem.
Is there any way to prevent a Spring component to start before the Axon framework is initialized? @DependsOn or something? Because first the component is up.
What is the function of the AutoStart class? You can rely on the AutoConfiguration of Axon. I deleted the AutoStart class and it works.
I added a query:
public class GetOpenRosterBlockIds {
}
Changed the GET mapping:
@GetMapping("/")
public CompletableFuture<List<String>> findOpenRosterBlocks() {
return queryGateway.query(new GetOpenRosterBlockIds(), ResponseTypes.multipleInstancesOf(String.class));
}
And updated the queryHandler:
@QueryHandler
public List<String> getOpenRosterBlockIds(GetOpenRosterBlockIds query) {
return openRosterBlockIds;
}
The Autostart class is indeed a way around the fact that my REST service wasn’t accessible, so I wanted to bypass that. But the REST issue was caused by a missing trailing /. So I’m up and running! Great! Thanks for the help!
One more question: how is the support in Axon for Java record classes? Seems like the perfect candidate for commands and events. (Again; I get exceptions after converting them, so is that supported?)