I want to keep my EventHandler retrying when an exception is thrown in the (tracking) EventHandler. The default behaviour is to continue processing the next event in the EventHandler. I do not want that, so I have created the following ErrorHandler:
`
@Component
public class RetryErrorHandler implements ListenerInvocationErrorHandler {
private final Logger log;
public RetryErrorHandler() {
this(LoggerFactory.getLogger(RetryErrorHandler.class));
}
public RetryErrorHandler(Logger log) {
this.log = log;
}
@Override
public void onError(Exception exception, EventMessage<?> eventMessage, EventMessageHandler eventMessageHandler) throws Exception {
log.warn("EventListener [{}] failed to handle event [{}] ({}). " +
“Starting retry mode”,
eventMessageHandler.getClass().getSimpleName(),
eventMessage.getIdentifier(),
eventMessage.getPayloadType().getName(),
exception);
throw exception;
}
}
`
With Axon 4.1.1, the RetryErrorHandler is being picked up by Spring Boot, and Axon. Axon gets an exception in the error handler, causing it NOT to update the token. As a result, the event is being redelivered to my EventHandler until the EventHandler no longer throws an exception. This is exactly the behaviour I want.
With Axon 4.2 (I changed axon version as ONLY change), the behaviour is different. The RetryErrorHandler is still picked up by Axon (Good) and executed when my EventHandler throws an Exception (Good) but now, the tracking token of the event processor IS updated. This result in the event no longer being offered for retry. NOT what I want.
What is the explanation about this changed behavior? Is this by design? Is this an AxonFramework bug? How can I make axon framework 4.2 eventhandlers to retry forever until they no longer throw an exception?
This is my Event handler:
`
@Component
@ProcessingGroup(“retry-event-listener”)
public class RetryEventListener {
public RetryEventListener(@Autowired SampleService sampleService) {
this.sampleService = sampleService;
}
private final SampleService sampleService;
@EventHandler
public void on(SampleRetryAggregateCreated event) throws Exception {
sampleService.eventListenerMethod();
}
}
`
And this is the test of my RetryErrorHandler:
`
public class RetryErrorHandlerTest extends AxonIntegrationTest {
@Autowired
private SampleService sampleService;
@Test
public void testEventProcessor() throws Exception {
when(sampleService.mock().eventListenerMethod())
.thenThrow(new Exception())
.thenThrow(new IllegalStateException())
.thenReturn(“Ok”);
commandGateway.sendAndWait(new CreateSampleRetryAggregate(UUID.randomUUID()));
verify(sampleService.mock(), timeout(10000).times(3)).eventListenerMethod();
}
}
`
The test succeeds in axon framework 4.1.1 and 4.1.2, but fails in 4.2 (because in 4.2, the eventListenerMethod() is invoked only once)
`
@Component
public class SampleService {
private SampleService mockDelegate;
public SampleService() {
mockDelegate = Mockito.mock(SampleService.class);
}
public String eventListenerMethod() throws Exception {
return mockDelegate.eventListenerMethod();
}
public SampleService mock() {
return mockDelegate;
}
}
`