Skip to content

Commit 9c3bedf

Browse files
committed
Add. two new constructors to RetryableException:
- A constructor without retryAfter and without cause - A constructor without retryAfter but with cause Standardized JavaDoc across all RetryableException constructors These new constructors remove overload ambiguity when retryAfter is not needed. Add. a unit test to verify the new constructors. - canCreateRetryableExceptionWithoutRetryAfter - canCreateRetryableExceptionWithoutRetryAfterAndWithCause Fixes #2458
1 parent 2c2db1c commit 9c3bedf

File tree

2 files changed

+134
-5
lines changed

2 files changed

+134
-5
lines changed

core/src/main/java/feign/RetryableException.java

Lines changed: 107 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,58 @@ public class RetryableException extends FeignException {
3232
private final HttpMethod httpMethod;
3333

3434
/**
35-
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header. If you
36-
* don't want to retry, set null.
35+
* Represents a non-retryable exception when Retry-After information is explicitly not provided.
36+
*
37+
* <p>Use this constructor when the server response does not include a Retry-After header or when
38+
* retries are not expected.
39+
*
40+
* @param status the HTTP status code
41+
* @param message the exception message
42+
* @param httpMethod the HTTP method (GET, POST, etc.)
43+
* @param request the original HTTP request
44+
*/
45+
public RetryableException(int status, String message, HttpMethod httpMethod, Request request) {
46+
super(status, message, request);
47+
this.httpMethod = httpMethod;
48+
this.retryAfter = null;
49+
}
50+
51+
/**
52+
* Represents a non-retryable exception when Retry-After information is explicitly not provided.
53+
*
54+
* <p>Use this constructor when the server response does not include a Retry-After header or when
55+
* retries are not expected.
56+
*
57+
* @param status the HTTP status code
58+
* @param message the exception message
59+
* @param httpMethod the HTTP method (GET, POST, etc.)
60+
* @param cause the underlying cause of the exception
61+
* @param request the original HTTP request
62+
*/
63+
public RetryableException(
64+
int status, String message, HttpMethod httpMethod, Throwable cause, Request request) {
65+
super(status, message, request, cause);
66+
this.httpMethod = httpMethod;
67+
this.retryAfter = null;
68+
}
69+
70+
/**
71+
* Represents a retryable exception when Retry-After information is available.
72+
*
73+
* <p>Use this constructor when the server response includes a Retry-After header specifying the
74+
* delay in milliseconds before retrying.
75+
*
76+
* <p>If {@code retryAfter} is {@code null}, prefer using {@link #RetryableException(int, String,
77+
* HttpMethod, Throwable, Request)} instead.
78+
*
79+
* @param status the HTTP status code
80+
* @param message the exception message
81+
* @param httpMethod the HTTP method (GET, POST, etc.)
82+
* @param cause the underlying cause of the exception
83+
* @param retryAfter the retry delay in milliseconds retryAfter usually corresponds to the {@link
84+
* feign.Util#RETRY_AFTER} header. If you don't want to retry, use {@link
85+
* #RetryableException(int, String, HttpMethod, Throwable, Request)}.
86+
* @param request the original HTTP request
3787
*/
3888
public RetryableException(
3989
int status,
@@ -47,6 +97,17 @@ public RetryableException(
4797
this.retryAfter = retryAfter;
4898
}
4999

100+
/**
101+
* @deprecated Use {@link #RetryableException(int, String, HttpMethod, Throwable, Long, Request)}
102+
* instead. This constructor uses {@link Date} for retryAfter, which has been replaced by
103+
* {@link Long}.
104+
* @param status the HTTP status code
105+
* @param message the exception message
106+
* @param httpMethod the HTTP method (GET, POST, etc.)
107+
* @param cause the underlying cause of the exception
108+
* @param retryAfter the retry-after time as a {@link Date}
109+
* @param request the original HTTP request
110+
*/
50111
@Deprecated
51112
public RetryableException(
52113
int status,
@@ -61,8 +122,17 @@ public RetryableException(
61122
}
62123

63124
/**
64-
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header. If you
65-
* don't want to retry, set null.
125+
* Represents a retryable exception when Retry-After information is available.
126+
*
127+
* <p>Use this constructor when the server response includes a Retry-After header.
128+
*
129+
* @param status the HTTP status code
130+
* @param message the exception message
131+
* @param httpMethod the HTTP method (GET, POST, etc.)
132+
* @param retryAfter the retry delay in milliseconds retryAfter usually corresponds to the {@link
133+
* feign.Util#RETRY_AFTER} header. If you don't want to retry, use {@link
134+
* #RetryableException(int, String, HttpMethod, Request)}
135+
* @param request the original HTTP request
66136
*/
67137
public RetryableException(
68138
int status, String message, HttpMethod httpMethod, Long retryAfter, Request request) {
@@ -71,6 +141,15 @@ public RetryableException(
71141
this.retryAfter = retryAfter;
72142
}
73143

144+
/**
145+
* @deprecated Use {@link #RetryableException(int, String, HttpMethod, Long, Request)} instead.
146+
* This constructor uses {@link Date} for retryAfter, which has been replaced by {@link Long}.
147+
* @param status the HTTP status code
148+
* @param message the exception message
149+
* @param httpMethod the HTTP method (GET, POST, etc.)
150+
* @param retryAfter the retry-after time as a {@link Date}
151+
* @param request the original HTTP request
152+
*/
74153
@Deprecated
75154
public RetryableException(
76155
int status, String message, HttpMethod httpMethod, Date retryAfter, Request request) {
@@ -80,7 +159,18 @@ public RetryableException(
80159
}
81160

82161
/**
83-
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header.
162+
* Represents a retryable exception with response body and headers.
163+
*
164+
* <p>Use this constructor when handling HTTP responses that include Retry-After information.
165+
*
166+
* @param status the HTTP status code
167+
* @param message the exception message
168+
* @param httpMethod the HTTP method (GET, POST, etc.)
169+
* @param retryAfter the retry delay in milliseconds retryAfter usually corresponds to the {@link
170+
* feign.Util#RETRY_AFTER} header.
171+
* @param request the original HTTP request
172+
* @param responseBody the HTTP response body
173+
* @param responseHeaders the HTTP response headers
84174
*/
85175
public RetryableException(
86176
int status,
@@ -95,6 +185,18 @@ public RetryableException(
95185
this.retryAfter = retryAfter;
96186
}
97187

188+
/**
189+
* @deprecated Use {@link #RetryableException(int, String, HttpMethod, Long, Request, byte[],
190+
* Map)} instead. This constructor uses {@link Date} for retryAfter, which has been replaced
191+
* by {@link Long}.
192+
* @param status the HTTP status code
193+
* @param message the exception message
194+
* @param httpMethod the HTTP method (GET, POST, etc.)
195+
* @param retryAfter the retry-after time as a {@link Date}
196+
* @param request the original HTTP request
197+
* @param responseBody the HTTP response body
198+
* @param responseHeaders the HTTP response headers
199+
*/
98200
@Deprecated
99201
public RetryableException(
100202
int status,

core/src/test/java/feign/RetryerTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,31 @@ void defaultRetryerFailsOnInterruptedException() {
9696
assertThat(e).as("Unexpected exception found").isEqualTo(expected);
9797
}
9898
}
99+
100+
@Test
101+
void canCreateRetryableExceptionWithoutRetryAfter() {
102+
RetryableException exception =
103+
new RetryableException(500, "Internal Server Error", Request.HttpMethod.GET, REQUEST);
104+
105+
assertThat(exception.status()).isEqualTo(500);
106+
assertThat(exception.getMessage()).contains("Internal Server Error");
107+
assertThat(exception.method()).isEqualTo(Request.HttpMethod.GET);
108+
assertThat(exception.retryAfter()).isNull();
109+
}
110+
111+
@Test
112+
void canCreateRetryableExceptionWithoutRetryAfterAndWithCause() {
113+
Throwable cause = new IllegalArgumentException("Illegal argument exception");
114+
115+
try {
116+
throw new RetryableException(
117+
500, "Internal Server Error", Request.HttpMethod.GET, cause, REQUEST);
118+
} catch (RetryableException exception) {
119+
assertThat(exception.status()).isEqualTo(500);
120+
assertThat(exception.getMessage()).contains("Internal Server Error");
121+
assertThat(exception.method()).isEqualTo(Request.HttpMethod.GET);
122+
assertThat(exception.retryAfter()).isNull();
123+
assertThat(exception.getCause()).isEqualTo(cause);
124+
}
125+
}
99126
}

0 commit comments

Comments
 (0)