I have a code base with several nearly-identical usages of @Retryable
, all driven by the same configuration values. So I created a new annotation that's annotated with ("inherits") @Retryable
, like this:
@Documented
@Retention(RUNTIME)
@Target({ TYPE, METHOD })
@Retryable(
include = RestClientException.class,
maxAttempts = 5,
backoff = @Backoff(delay = 1000, multiplier = 3)
)
public @interface RESTClientRetry {
@AliasFor(annotation = Retryable.class, attribute = "listeners")
String[] listeners() default {};
@AliasFor(annotation = Retryable.class, attribute = "include")
Class<? extends Throwable>[] include() default {};
@AliasFor(annotation = Retryable.class, attribute = "maxAttemptsExpression")
String maxAttemptsExpression() default "";
@AliasFor(annotation = Retryable.class, attribute = "backoff")
Backoff backoff() default @Backoff();
}
This works as expected, except for when I want usages of this annotation to use their own listeners. Usage is like this:
@RESTClientRetry(listeners = "retryLoggerBean1")
In an application where there are several RetryListener
beans (named retryLoggerBean1
, retryLoggerBean2
, etc), they are all getting called for every method that's annotated with RESTClientRetry
, even though each annotation specifies its own listeners
.
Using the debugger, I see that when AnnotationAwareRetryOperationsInterceptor
is invoked, the Retryable
object has an empty value for listeners
. So it seems like that interceptor is not supporting annotation "inheritance" (composition). Without any annotation-specific listeners, it's falling back to the global set of listeners, which explains why I'm seeing them all invoked for every method.
Is this a known limitation or bug with the interceptor, or is there another way to wrap @Retryable
with my own annotation and still le individual usage define which listener to use?