Event handler not work

I’m using Axon Server 2025.4.1 as an event store with Axon Framework 4.7.0.
I’ve noticed that an @EventHandler is only invoked when I explicitly annotate its class with @ProcessingGroup ; without that annotation, the handler is never triggered.
In the aggregate I can see the command-handling log and the event-sourcing logs, but nothing is logged inside the @EventHandler .
Could anyone explain why the handler is ignored when no @ProcessingGroup is provided?

this is my code

 CreateReconciliationDraftCommand command =
                    new CreateReconciliationDraftCommand(
                            newReconciliationNo,
                            newReconciliationName,
                            originalReconciliation.getStartDate(),
                            originalReconciliation.getEndDate(),
                            originalReconciliation.getReconciliationDate(),
                            transportType,
                            originalReconciliation.getConsignorCorpCode(),
                            originalReconciliation.getConsignorCorpName(),
                            originalReconciliation.getCarrierCorpCode(),
                            originalReconciliation.getCarrierCorpName(),
                            reconciliationItems,
                            originalReconciliation.getCumulativeAmount(),
                            originalReconciliationNo);
            // @formatter:on
            commandGateway.send(command);

this is my aggregate

@Slf4j
@Getter
@Aggregate
public class ReconciliationAggregate {

    // 对账单编号
    @AggregateIdentifier
    private String reconciliationNo;



    protected ReconciliationAggregate() {
    }

    // =============================================
    // 命令处理器 - 创建对账单草稿
    // =============================================
    @CommandHandler
    public ReconciliationAggregate(CreateReconciliationDraftCommand command) {
        // 基础验证
        Assert.notEmpty(command.getItems(), () -> "运单列表不能为空");

        log.info("create draft command handler->{}",command);
        // 发布事件
        // @formatter:off
        apply(
                new ReconciliationDraftCreatedEvent(
                        command.getReconciliationNo(),
                        command.getName(),
                        command.getStartDate(),
                        command.getEndDate(),
                        command.getReconciliationDate(),
                        command.getTransportType(),
                        command.getConsignorCorpCode(),
                        command.getConsignorCorpName(),
                        command.getCarrierCorpCode(),
                        command.getCarrierCorpName(),
                        command.getItems(),
                        calculateTotalAmount(command.getItems()),
                        calculateTotalWeight(command.getItems()),
                        command.getCumulativeAmount(),
                        command.getItems().size(),
                        ReconciliationStatus.DRAFT,
                        command.getHistoryReconciliationNo()));
        // @formatter:on
    } 
 @EventSourcingHandler
    public void on(ReconciliationDraftCreatedEvent event) {
        log.info("ReconciliationDraftCreatedEvent: {}", event);
        this.reconciliationNo = event.getReconciliationNo();
}

this is my projection

package com.smartchain.tms.reconciliation.query.projections;

@Slf4j
@Component
//@ProcessingGroup("reconciliation")
@RequiredArgsConstructor
public class ReconciliationProjection {

    private final ReconciliationItemService reconciliationItemService;

    private final ReconciliationService reconciliationService;

    @EventHandler
    @Transactional
    public void on(ReconciliationDraftCreatedEvent event) {
        log.info("处理对账单草稿创建事件: {}", event.getReconciliationNo());
}

but i get this log

In all honesty, @justrught, I cannot!
Axon Framework in a Spring Boot scenario will look for all beans in Spring’s Application Context for method annotated with:

  • @CommandHandler
  • @EventHandler
  • QueryHandler

Hence, as your ReconciliationProjection is annotated with @Component, it is a part of the Application Context.
The only thing I can think of, is a wiring ordering issue, although that’s farfetched.

To investigate further, I would suggest you toggle on debug logging for the TrackingEventProcessor. Without the @ProcessingGroup annotation, the name of your event processors == the package name.
Hence, in your example, that’s com.smartchain.tms.reconciliation.query.projections. You should see logs of the TrackingEventProcessor starting with that processor name.
If that’s not the case, we can dive deeper.

Ow, and by the way, please update to Axon Framework 4.12. AF4.7 is a very old version of Axon Framework. Perhaps that may already resolve the issue you are facing.

Sorry to bother you again — I gave it another try but still couldn’t find any relevant logs. Also, just a quick question: can I upgrade directly from version 4.7 to 4.12? I didn’t see any specific notes about this on the official website. I’m currently using JDK 8 — could that cause any issues?

As shown in the image above, “运单查询” is another query that follows this interface, but no log information is found. This is my local environment, so there are no other requests. The query below is the callback after the execution of this command interface is completed.

No need to say sorry! Helping one another out is what this forum is for. :slight_smile:

You can indeed just update to 4.12, @justrught! No worries there.

And JDK8 is completely fine as well! Axon Framework 4 is based on JDK8 and will be. Note that Axon Framework 5, which we are working on right now, will be JDK21, though! Last point on the JDK: I don’t think the JDK version is the culprit for the problem you’re seeing.

Hmm, that’s a nuisance. Instead of logging, you can also place some debug statements and run your application in debug mode, if you like.
Specifically the start operation of the TrackingEventProcessor would be worthwhile. If that’s not hit, there’s definitely some wiring ordering going amiss.


Besides all of the above, I do wnat to point out that use of the @ProcessingGroup is recommended for your Event Handling Components. Without that annotation, your event handling components will be placed in Event Processors named after your package name. Although a fair default, as handlers that belong to one another are typically placed in the same package, it is not overly clear to developers working on the application.

If, instead, you mark every Event Handling Component with the @ProcessingGroup annotation, with a specific and descriptive name, all members of the team are clear on the fact that “Ah, this Event Handling Component belongs to an Event Processor with this name!”

After upgrading to version 4.12.1, the application fails to start, and I received the following error message.


***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method axonServerCommandBus in org.axonframework.springboot.autoconfig.AxonServerBusAutoConfiguration required a bean of type 'org.axonframework.axonserver.connector.AxonServerConnectionManager' that could not be found.


Action:

Consider defining a bean of type 'org.axonframework.axonserver.connector.AxonServerConnectionManager' in your configuration.
~~~text

I found that the last working version is 4.8.3. Starting from 4.9.0, this error occurs. My Spring Boot version is 2.3.10.RELEASE. I suspect that Axon might be using an auto-configuration approach that has been deprecated in Spring Boot 2.3.

Curious, as Axon Framework has support for Spring Boot 2 and Spring Boot 3, with dedicated autowiring tests. Including the AxonServerConnectionManager. Are you not, perchance, excluding Axon Server somewhere? Like a dependency or an autoconfiguration class specifically?

Somewhere within the AF4 lifecycle we did split the creation of Axon Server base components from the Axon Server buses with the Spring Boot autoconfiguration. More concretely, there’s a AxonServerAutoConfiguration for the former and a AxonServerBusAutoConfiguration for the latter. Both react with the axon.axonserver.enabled property set to false, by the way, so if you are using an autoconfiguration exclusion approach, I would recommend to switch that to a property-based shutdown approach.

I didn’t exclude any dependencies.
I started from a clean project with only Spring Boot’s base starter and Axon.
I tested version by version until I finally pinned down the result.