Injecting beans in Aggregates

Hi all.

I’m writing a prototype to show the capabilities of Event Sourcing and Sagas with Axon, I’m quite new with it. I searched and found this thread [1] in this forum that practically explains my problem, however the solution with [2] is not working. The error I’m having is

UnsupportedHandlerException: On method public TestService(TestStartCommand,org.springframework.web.client.RestTemplate,org.axonframework.commandhandling.gateway.CommandGateway), parameter 2 is invalid. It is not of any format supported by a providedParameterValueResolver.

It’s coming from my JavaConfig class (shameless copy of the quick guide)

@Bean public EventSourcingRepository<TestService> eventRepository() { // we need to configure the repository EventSourcingRepository<AuditService> eventRepository = new EventSourcingRepository<TestService>(TestService.class, eventStore()); eventRepository.setEventBus(eventBus()); // Axon needs to know that our TestService Aggregate can handle commands AggregateAnnotationCommandHandler.subscribe(TestService.class, eventRepository, commandBus()); // <<====== ERROR // Let’s wire the Event Handler in our infrastructure. AnnotationEventListenerAdapter.subscribe(new TestService`Handler(), eventBus());

return eventRepository;
}

`

Following the explanation in [2],

Methods annotated with @CommandHandler and @EventHandler are now inspected by
the SpringBeanParameterResolverFactory, which injects Spring beans as method
parameters. It is automatically enabled when the axon:annotation-support/
element is used. Otherwise, configure the factory is a bean to enable support.

and since I don’t have any XML config, I just added this to my JavaConfig

`
@Bean
public SpringBeanParameterResolverFactory springBeanParameterResolverFactory(){
return new SpringBeanParameterResolverFactory();

}

`

and the constructor of the aggregate is (both restTemplate and commandGateway are defines as beans):

`
@CommandHandler
public TestService (TestStartCommand command, RestTemplate restTemplate, CommandGateway commandGateway) {
this.restTemplate = restTemplate;
this.commandGateway = commandGateway;
this.id = command.getId();
apply(new TestStartedEvent(command.getId(), command.getData()));
}

`

So, it seems that AggregateAnnotationCommandHandler never sees nor uses ``SpringBeanParameterResolverFactory.

Any ideas on what am I doing wrong?

Cheers.

[1] https://groups.google.com/d/msg/axonframework/d9OeCWU2FbQ/dUaHGy5pXj8J
[2] Issues · AxonFramework/AxonFramework · GitHub

Well, I solved this particular problem by instead of

// Axon needs to know that our TestService Aggregate can handle commands
AggregateAnnotationCommandHandler.subscribe(TestService.class, eventRepository, commandBus()); // <<====== ERROR

using this instead:

@Bean public AggregateAnnotationCommandHandler<TestService> commandHandler() { CommandTargetResolver commandTargetResolver = new AnnotationCommandTargetResolver(); AggregateAnnotationCommandHandler<TestService> commandHandler = new AggregateAnnotationCommandHandler<TestService>(TestService`.class, eventRepository(), commandTargetResolver, springBeanParameterResolverFactory());
for (String supportedCommand : commandHandler.supportedCommands()) {
commandBus().subscribe(supportedCommand, commandHandler);
}
return commandHandler;
}

`

Now it seems to be working OK, is this the correct way to do it or is there a cleaner way to do it?

Well, problem solved but I’m sure I will have more to ask… :slight_smile:

Cheers.

Hi Antonio,

you can also do
AggregateAnnotationCommandHandler.subscribe(TestService.class, eventRepository(), springBeanParameterResolverFactory(), commandTargetResolver);

In that case, you don’t need to do the for loop afterwards.
Cheers,

Allard

PS. Support for easier configuration in JavaConfig is coming up…

Hmmm, in Axon 2.2? I can’t see that, only 2 subscribe methods

`

subscribe(Class aggregateType, Repository repository, CommandBus commandBus)

subscribe(Class aggregateType, Repository repository, CommandBus commandBus, CommandTargetResolver commandTargetResolver)

`

none that accepts a ParameterResolverFactory…

Sorry, I misread my own interface ;-). Seems like your solution is the easiest one. This definitely needs some api improvement. Coming soon…

Cheers,

Allard

I just saw today that v2.3 was released and that

It’s now easier to configure Axon Annotation configuration. Simply put the @AnnotationDriven annotation on your @Configuration bean, and all you @CommandHandler and @EventHandler annotated beans are registered with their respective Bus

However, I tried using this and removing the loop from my code above, but it didn’t work, I had to put the loop back.

Did I misread something?

Cheers.

Hi,

the new annotation is about event handler beans, not aggregates. There is no annotation for this yet. That’s the next step.
Did you try using the AggregateAnnotationCommandHandlerFactoryBean? Or alternatively, use a small snippet of xml to define the aggregate-annotation-handler?

Cheers,

Allard

Well, I’m using the AggregateAnnotationCommandHandlerFactoryBean now because I no longer need to inject parameters, but to use the SpringBeanParameterResolverFactory that loop is necessary. It should be a question of a couple of lines to implement that inside the AggregateAnnotationCommandHandler itself.

Cheers.