Starting in 2.8.4 you can configure the framework to use both blocking and non-blocking retries in conjunction. For example, you can have a set of exceptions that would likely trigger errors on the next records as well, such as DatabaseAccessException, so you can retry the same record a few times before sending it to the retry topic, or straight to the DLT.spring-doc.cn

To configure blocking retries, override the configureBlockingRetries method in a @Configuration class that extends RetryTopicConfigurationSupport and add the exceptions you want to retry, along with the BackOff to be used. The default BackOff is a FixedBackOff with no delay and 9 attempts. See Configuring Global Settings and Features for more information.spring-doc.cn

@Override
protected void configureBlockingRetries(BlockingRetriesConfigurer blockingRetries) {
    blockingRetries
            .retryOn(MyBlockingRetryException.class, MyOtherBlockingRetryException.class)
            .backOff(new FixedBackOff(3_000, 5));
}
In combination with the global retryable topic’s fatal exceptions classification, you can configure the framework for any behavior you’d like, such as having some exceptions trigger both blocking and non-blocking retries, trigger only one kind or the other, or go straight to the DLT without retries of any kind.
In combination with the global retryable topic’s fatal exceptions classification, you can configure the framework for any behavior you’d like, such as having some exceptions trigger both blocking and non-blocking retries, trigger only one kind or the other, or go straight to the DLT without retries of any kind.

Here’s an example with both configurations working together:spring-doc.cn

@Override
protected void configureBlockingRetries(BlockingRetriesConfigurer blockingRetries) {
    blockingRetries
            .retryOn(ShouldRetryOnlyBlockingException.class, ShouldRetryViaBothException.class)
            .backOff(new FixedBackOff(50, 3));
}

@Override
protected void manageNonBlockingFatalExceptions(List<Class<? extends Throwable>> nonBlockingFatalExceptions) {
    nonBlockingFatalExceptions.add(ShouldSkipBothRetriesException.class);
}

In this example:spring-doc.cn

  • ShouldRetryOnlyBlockingException.class would retry only via blocking and, if all retries fail, would go straight to the DLT.spring-doc.cn

  • ShouldRetryViaBothException.class would retry via blocking, and if all blocking retries fail would be forwarded to the next retry topic for another set of attempts.spring-doc.cn

  • ShouldSkipBothRetriesException.class would never be retried in any way and would go straight to the DLT if the first processing attempt failed.spring-doc.cn

Note that the blocking retries behavior is allowlist - you add the exceptions you do want to retry that way; while the non-blocking retries classification is geared towards FATAL exceptions and as such is denylist - you add the exceptions you don’t want to do non-blocking retries, but to send directly to the DLT instead.
Note that the blocking retries behavior is allowlist - you add the exceptions you do want to retry that way; while the non-blocking retries classification is geared towards FATAL exceptions and as such is denylist - you add the exceptions you don’t want to do non-blocking retries, but to send directly to the DLT instead.
The non-blocking exception classification behavior also depends on the specific topic’s configuration.
The non-blocking exception classification behavior also depends on the specific topic’s configuration.