Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,6 @@ If there has been an error, it is the last one thrown by the `RetryCallback`.
Note that when there is more than one listener, they are in a list, so there is an order.
In this case, `open` is called in the same order, while `onSuccess`, `onError`, and `close` are called in reverse order.

`RetryListenerSupport` is provided, with no-op implementations; you can extend this class if you don't need to implement all of the `RetryListener` methods.

### Listeners for Reflective Method Invocations

When dealing with methods that are annotated with `@Retryable` or with Spring AOP intercepted methods, Spring Retry allows a detailed inspection of the method invocation within the `RetryListener` implementation.
Expand Down
13 changes: 10 additions & 3 deletions src/main/java/org/springframework/retry/RetryListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*
* @author Dave Syer
* @author Gary Russell
* @author Henning Pöttker
*
*/
public interface RetryListener {
Expand All @@ -38,7 +39,9 @@ public interface RetryListener {
* @param callback the current {@link RetryCallback}.
* @return true if the retry should proceed.
*/
<T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback);
default <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
return true;
}

/**
* Called after the final attempt (successful or not). Allow the listener to clean up
Expand All @@ -49,7 +52,9 @@ public interface RetryListener {
* @param <E> the exception type
* @param <T> the return value
*/
<T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback, Throwable throwable);
default <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,
Throwable throwable) {
}

/**
* Called after a successful attempt; allow the listener to throw a new exception to
Expand All @@ -72,6 +77,8 @@ default <T, E extends Throwable> void onSuccess(RetryContext context, RetryCallb
* @param <T> the return value
* @param <E> the exception to throw
*/
<T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback, Throwable throwable);
default <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,
Throwable throwable) {
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2006-2007 the original author or authors.
* Copyright 2006-2022 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.
Expand All @@ -24,8 +24,10 @@
* Empty method implementation of {@link RetryListener}.
*
* @author Dave Syer
*
* @author Henning Pöttker
* @deprecated in favor of the default implementations in {@link RetryListener}
*/
@Deprecated(since = "2.0.1", forRemoval = true)
public class RetryListenerSupport implements RetryListener {

public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2022 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.
Expand All @@ -19,15 +19,16 @@
import org.springframework.core.AttributeAccessor;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryListener;
import org.springframework.retry.RetryStatistics;
import org.springframework.retry.listener.RetryListenerSupport;
import org.springframework.retry.policy.CircuitBreakerRetryPolicy;

/**
* @author Dave Syer
* @author Henning Pöttker
*
*/
public class StatisticsListener extends RetryListenerSupport {
public class StatisticsListener implements RetryListener {

private final StatisticsRepository repository;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.backoff.Sleeper;
import org.springframework.retry.interceptor.RetryInterceptorBuilder;
import org.springframework.retry.listener.RetryListenerSupport;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;

Expand All @@ -57,6 +56,7 @@
* @author Artem Bilan
* @author Gary Russell
* @author Aldo Sinanaj
* @author Henning Pöttker
* @since 1.1
*/
public class EnableRetryTests {
Expand Down Expand Up @@ -910,7 +910,7 @@ public int getCount() {

}

public abstract static class OrderedListener extends RetryListenerSupport implements Ordered {
public abstract static class OrderedListener implements RetryListener, Ordered {

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryListener;
import org.springframework.retry.listener.RetryListenerSupport;

import static org.assertj.core.api.Assertions.assertThat;

/**
* @author Dave Syer
* @author Gary Russell
* @author Henning Pöttker
*
*/
public class EnableRetryWithListenersTests {
Expand Down Expand Up @@ -68,7 +68,7 @@ public Service service() {

@Bean
public RetryListener listener() {
return new RetryListenerSupport() {
return new RetryListener() {
@Override
public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,
Throwable throwable) {
Expand All @@ -94,7 +94,7 @@ public ServiceWithOverriddenListener service() {

@Bean
public RetryListener listener1() {
return new RetryListenerSupport() {
return new RetryListener() {
@Override
public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,
Throwable throwable) {
Expand All @@ -105,7 +105,7 @@ public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T

@Bean
public RetryListener listener2() {
return new RetryListenerSupport() {
return new RetryListener() {
@Override
public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,
Throwable throwable) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryListener;
import org.springframework.retry.listener.MethodInvocationRetryListenerSupport;
import org.springframework.retry.listener.RetryListenerSupport;
import org.springframework.retry.policy.NeverRetryPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
import org.springframework.retry.support.RetryTemplate;
Expand All @@ -47,6 +47,13 @@
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;

/**
* @author Dave Syer
* @author Marius Grama
* @author Gary Russell
* @author Stéphane Nicoll
* @author Henning Pöttker
*/
public class RetryOperationsInterceptorTests {

private static int count;
Expand All @@ -66,7 +73,7 @@ public void setUp() {
this.interceptor = new RetryOperationsInterceptor();
RetryTemplate retryTemplate = new RetryTemplate();
final AtomicBoolean calledFirst = new AtomicBoolean();
retryTemplate.registerListener(new RetryListenerSupport() {
retryTemplate.registerListener(new RetryListener() {

@Override
public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
Expand All @@ -83,7 +90,7 @@ public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T
}

});
retryTemplate.registerListener(new RetryListenerSupport() {
retryTemplate.registerListener(new RetryListener() {

@Override
public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
import org.springframework.retry.ExhaustedRetryException;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryListener;
import org.springframework.retry.RetryOperations;
import org.springframework.retry.listener.RetryListenerSupport;
import org.springframework.retry.policy.AlwaysRetryPolicy;
import org.springframework.retry.policy.NeverRetryPolicy;
import org.springframework.retry.policy.SimpleRetryPolicy;
Expand All @@ -51,6 +51,7 @@
/**
* @author Dave Syer
* @author Gary Russell
* @author Henning Pöttker
*
*/
public class StatefulRetryOperationsInterceptorTests {
Expand All @@ -70,7 +71,7 @@ public class StatefulRetryOperationsInterceptorTests {
@BeforeEach
public void setUp() {
interceptor = new StatefulRetryOperationsInterceptor();
retryTemplate.registerListener(new RetryListenerSupport() {
retryTemplate.registerListener(new RetryListener() {
@Override
public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,
Throwable throwable) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;

/**
* @author Dave Syer
* @author Gary Russell
* @author Henning Pöttker
*/
@SuppressWarnings("deprecation")
public class RetryListenerSupportTests {

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.Assertions.assertThatNoException;

/**
* @author Dave Syer
* @author Stéphane Nicoll
* @author Gary Russell
* @author Henning Pöttker
*/
public class RetryListenerTests {

RetryTemplate template = new RetryTemplate();
Expand All @@ -40,15 +47,43 @@ public class RetryListenerTests {

List<String> list = new ArrayList<>();

@Test
public void testOpenDefaultImplementation() {
var retryListener = new RetryListener() {
};
assertThat(retryListener.open(null, null)).isTrue();
}

@Test
public void testCloseDefaultImplementation() {
var retryListener = new RetryListener() {
};
assertThatNoException().isThrownBy(() -> retryListener.close(null, null, null));
}

@Test
public void testOnSuccessDefaultImplementation() {
var retryListener = new RetryListener() {
};
assertThatNoException().isThrownBy(() -> retryListener.onError(null, null, null));
}

@Test
public void testOnErrorDefaultImplementation() {
var retryListener = new RetryListener() {
};
assertThatNoException().isThrownBy(() -> retryListener.onError(null, null, null));
}

@Test
public void testOpenInterceptors() {
template.setListeners(new RetryListener[] { new RetryListenerSupport() {
template.setListeners(new RetryListener[] { new RetryListener() {
public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
count++;
list.add("1:" + count);
return true;
}
}, new RetryListenerSupport() {
}, new RetryListener() {
public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
count++;
list.add("2:" + count);
Expand All @@ -63,7 +98,7 @@ public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback

@Test
public void testOpenCanVetoRetry() {
template.registerListener(new RetryListenerSupport() {
template.registerListener(new RetryListener() {
public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback<T, E> callback) {
list.add("1");
return false;
Expand All @@ -80,13 +115,13 @@ public <T, E extends Throwable> boolean open(RetryContext context, RetryCallback

@Test
public void testCloseInterceptors() {
template.setListeners(new RetryListener[] { new RetryListenerSupport() {
template.setListeners(new RetryListener[] { new RetryListener() {
public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,
Throwable t) {
count++;
list.add("1:" + count);
}
}, new RetryListenerSupport() {
}, new RetryListener() {
public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,
Throwable t) {
count++;
Expand All @@ -103,12 +138,12 @@ public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T
@Test
public void testOnError() {
template.setRetryPolicy(new NeverRetryPolicy());
template.setListeners(new RetryListener[] { new RetryListenerSupport() {
template.setListeners(new RetryListener[] { new RetryListener() {
public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,
Throwable throwable) {
list.add("1");
}
}, new RetryListenerSupport() {
}, new RetryListener() {
public <T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,
Throwable throwable) {
list.add("2");
Expand All @@ -128,7 +163,7 @@ public <T, E extends Throwable> void onError(RetryContext context, RetryCallback

@Test
public void testCloseInterceptorsAfterRetry() {
template.registerListener(new RetryListenerSupport() {
template.registerListener(new RetryListener() {
public <T, E extends Throwable> void close(RetryContext context, RetryCallback<T, E> callback,
Throwable t) {
list.add("" + count);
Expand Down
Loading