From b949944a1baa241995e6c5af5af762526dab68bd Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Mon, 9 Mar 2020 14:22:42 -0400 Subject: [PATCH] Support positional RetryListeners - useful when framework code needs to add a listener before user listeners. --- .../retry/support/RetryTemplate.java | 31 +++++++++++++++++-- .../RetryOperationsInterceptorTests.java | 27 +++++++++++++++- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/springframework/retry/support/RetryTemplate.java b/src/main/java/org/springframework/retry/support/RetryTemplate.java index cdf6908..8bf4bf4 100644 --- a/src/main/java/org/springframework/retry/support/RetryTemplate.java +++ b/src/main/java/org/springframework/retry/support/RetryTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2019 the original author or authors. + * Copyright 2006-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -143,16 +143,41 @@ public class RetryTemplate implements RetryOperations { } /** - * Register an additional listener. + * Register an additional listener at the end of the list. * @param listener the {@link RetryListener} * @see #setListeners(RetryListener[]) */ public void registerListener(RetryListener listener) { + registerListener(listener, this.listeners.length); + } + + /** + * Register an additional listener at the specified index. + * @param listener the {@link RetryListener} + * @param index the position in the list. + * @since 1.3 + * @see #setListeners(RetryListener[]) + */ + public void registerListener(RetryListener listener, int index) { List list = new ArrayList(Arrays.asList(this.listeners)); - list.add(listener); + if (index >= list.size()) { + list.add(listener); + } + else { + list.add(index, listener); + } this.listeners = list.toArray(new RetryListener[list.size()]); } + /** + * Return true if at least one listener is registered. + * @return true if listeners present. + * @since 1.3 + */ + public boolean hasListeners() { + return this.listeners.length > 0; + } + /** * Setter for {@link BackOffPolicy}. * @param backOffPolicy the {@link BackOffPolicy} diff --git a/src/test/java/org/springframework/retry/interceptor/RetryOperationsInterceptorTests.java b/src/test/java/org/springframework/retry/interceptor/RetryOperationsInterceptorTests.java index a91cd55..8cf0711 100644 --- a/src/test/java/org/springframework/retry/interceptor/RetryOperationsInterceptorTests.java +++ b/src/test/java/org/springframework/retry/interceptor/RetryOperationsInterceptorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2019 the original author or authors. + * Copyright 2006-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,10 +22,13 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.junit.Before; import org.junit.Test; + import org.springframework.aop.framework.Advised; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.target.SingletonTargetSource; @@ -43,6 +46,7 @@ import org.springframework.util.ClassUtils; import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -66,13 +70,34 @@ public class RetryOperationsInterceptorTests { public void setUp() throws Exception { this.interceptor = new RetryOperationsInterceptor(); RetryTemplate retryTemplate = new RetryTemplate(); + final AtomicBoolean calledFirst = new AtomicBoolean(); retryTemplate.registerListener(new RetryListenerSupport() { + + @Override + public boolean open(RetryContext context, RetryCallback callback) { + + calledFirst.set(true); + return true; + + } + @Override public void close(RetryContext context, RetryCallback callback, Throwable throwable) { RetryOperationsInterceptorTests.this.context = context; } + }); + retryTemplate.registerListener(new RetryListenerSupport() { + + @Override + public boolean open(RetryContext context, RetryCallback callback) { + + assertFalse(calledFirst.get()); + return true; + } + + }, 0); this.interceptor.setRetryOperations(retryTemplate); this.target = new ServiceImpl(); this.service = ProxyFactory.getProxy(Service.class, new SingletonTargetSource(this.target));