Skip to content

Commit 31d0395

Browse files
committed
Add constructor to RetryableException for cases without retryAfter
Added 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. Added a unit test to verify the new constructors. - canCreateRetryableExceptionWithoutRetryAfter - canCreateRetryableExceptionWithoutRetryAfterAndWithCause Fixes #2458
1 parent 2c2db1c commit 31d0395

File tree

2 files changed

+172
-33
lines changed

2 files changed

+172
-33
lines changed

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

+147-33
Original file line numberDiff line numberDiff line change
@@ -32,78 +32,192 @@ 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+
* <p>
37+
* Use this constructor when the server response does not include a Retry-After header
38+
* or when 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
3744
*/
3845
public RetryableException(
39-
int status,
40-
String message,
41-
HttpMethod httpMethod,
42-
Throwable cause,
43-
Long retryAfter,
44-
Request request) {
46+
int status,
47+
String message,
48+
HttpMethod httpMethod,
49+
Request request) {
50+
super(status, message, request);
51+
this.httpMethod = httpMethod;
52+
this.retryAfter = null;
53+
}
54+
55+
/**
56+
* Represents a non-retryable exception when Retry-After information is explicitly not provided.
57+
* <p>
58+
* Use this constructor when the server response does not include a Retry-After header
59+
* or when retries are not expected.
60+
*
61+
* @param status the HTTP status code
62+
* @param message the exception message
63+
* @param httpMethod the HTTP method (GET, POST, etc.)
64+
* @param cause the underlying cause of the exception
65+
* @param request the original HTTP request
66+
*/
67+
public RetryableException(
68+
int status,
69+
String message,
70+
HttpMethod httpMethod,
71+
Throwable cause,
72+
Request request) {
73+
super(status, message, request, cause);
74+
this.httpMethod = httpMethod;
75+
this.retryAfter = null;
76+
}
77+
78+
/**
79+
* Represents a retryable exception when Retry-After information is available.
80+
* <p>
81+
* Use this constructor when the server response includes a Retry-After header
82+
* specifying the delay in milliseconds before retrying.
83+
* <p>
84+
* If {@code retryAfter} is {@code null}, prefer using
85+
* {@link #RetryableException(int, String, HttpMethod, Throwable, Request)} instead.
86+
*
87+
* @param status the HTTP status code
88+
* @param message the exception message
89+
* @param httpMethod the HTTP method (GET, POST, etc.)
90+
* @param cause the underlying cause of the exception
91+
* @param retryAfter the retry delay in milliseconds
92+
* @param request the original HTTP request
93+
*/
94+
public RetryableException(
95+
int status,
96+
String message,
97+
HttpMethod httpMethod,
98+
Throwable cause,
99+
Long retryAfter,
100+
Request request) {
45101
super(status, message, request, cause);
46102
this.httpMethod = httpMethod;
47103
this.retryAfter = retryAfter;
48104
}
49105

106+
/**
107+
* @deprecated Use {@link #RetryableException(int, String, HttpMethod, Throwable, Long, Request)}
108+
* instead. This constructor uses {@link Date} for retryAfter, which has been replaced by {@link Long}.
109+
*
110+
* @param status the HTTP status code
111+
* @param message the exception message
112+
* @param httpMethod the HTTP method (GET, POST, etc.)
113+
* @param cause the underlying cause of the exception
114+
* @param retryAfter the retry-after time as a {@link Date}
115+
* @param request the original HTTP request
116+
*/
50117
@Deprecated
51118
public RetryableException(
52-
int status,
53-
String message,
54-
HttpMethod httpMethod,
55-
Throwable cause,
56-
Date retryAfter,
57-
Request request) {
119+
int status,
120+
String message,
121+
HttpMethod httpMethod,
122+
Throwable cause,
123+
Date retryAfter,
124+
Request request) {
58125
super(status, message, request, cause);
59126
this.httpMethod = httpMethod;
60127
this.retryAfter = retryAfter != null ? retryAfter.getTime() : null;
61128
}
62129

63130
/**
64-
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header. If you
65-
* don't want to retry, set null.
131+
* Represents a retryable exception when Retry-After information is available.
132+
* <p>
133+
* Use this constructor when the server response includes a Retry-After header.
134+
*
135+
* @param status the HTTP status code
136+
* @param message the exception message
137+
* @param httpMethod the HTTP method (GET, POST, etc.)
138+
* @param retryAfter the retry delay in milliseconds
139+
* @param request the original HTTP request
66140
*/
67141
public RetryableException(
68-
int status, String message, HttpMethod httpMethod, Long retryAfter, Request request) {
142+
int status,
143+
String message,
144+
HttpMethod httpMethod,
145+
Long retryAfter,
146+
Request request) {
69147
super(status, message, request);
70148
this.httpMethod = httpMethod;
71149
this.retryAfter = retryAfter;
72150
}
73151

152+
/**
153+
* @deprecated Use {@link #RetryableException(int, String, HttpMethod, Long, Request)}
154+
* instead. This constructor uses {@link Date} for retryAfter, which has been replaced by {@link Long}.
155+
*
156+
* @param status the HTTP status code
157+
* @param message the exception message
158+
* @param httpMethod the HTTP method (GET, POST, etc.)
159+
* @param retryAfter the retry-after time as a {@link Date}
160+
* @param request the original HTTP request
161+
*/
74162
@Deprecated
75163
public RetryableException(
76-
int status, String message, HttpMethod httpMethod, Date retryAfter, Request request) {
164+
int status,
165+
String message,
166+
HttpMethod httpMethod,
167+
Date retryAfter,
168+
Request request) {
77169
super(status, message, request);
78170
this.httpMethod = httpMethod;
79171
this.retryAfter = retryAfter != null ? retryAfter.getTime() : null;
80172
}
81173

82174
/**
83-
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header.
175+
* Represents a retryable exception with response body and headers.
176+
* <p>
177+
* Use this constructor when handling HTTP responses that include Retry-After information.
178+
*
179+
* @param status the HTTP status code
180+
* @param message the exception message
181+
* @param httpMethod the HTTP method (GET, POST, etc.)
182+
* @param retryAfter the retry delay in milliseconds
183+
* @param request the original HTTP request
184+
* @param responseBody the HTTP response body
185+
* @param responseHeaders the HTTP response headers
84186
*/
85187
public RetryableException(
86-
int status,
87-
String message,
88-
HttpMethod httpMethod,
89-
Long retryAfter,
90-
Request request,
91-
byte[] responseBody,
92-
Map<String, Collection<String>> responseHeaders) {
188+
int status,
189+
String message,
190+
HttpMethod httpMethod,
191+
Long retryAfter,
192+
Request request,
193+
byte[] responseBody,
194+
Map<String, Collection<String>> responseHeaders) {
93195
super(status, message, request, responseBody, responseHeaders);
94196
this.httpMethod = httpMethod;
95197
this.retryAfter = retryAfter;
96198
}
97199

200+
/**
201+
* @deprecated Use {@link #RetryableException(int, String, HttpMethod, Long, Request, byte[], Map)}
202+
* instead. This constructor uses {@link Date} for retryAfter, which has been replaced by {@link Long}.
203+
*
204+
* @param status the HTTP status code
205+
* @param message the exception message
206+
* @param httpMethod the HTTP method (GET, POST, etc.)
207+
* @param retryAfter the retry-after time as a {@link Date}
208+
* @param request the original HTTP request
209+
* @param responseBody the HTTP response body
210+
* @param responseHeaders the HTTP response headers
211+
*/
98212
@Deprecated
99213
public RetryableException(
100-
int status,
101-
String message,
102-
HttpMethod httpMethod,
103-
Date retryAfter,
104-
Request request,
105-
byte[] responseBody,
106-
Map<String, Collection<String>> responseHeaders) {
214+
int status,
215+
String message,
216+
HttpMethod httpMethod,
217+
Date retryAfter,
218+
Request request,
219+
byte[] responseBody,
220+
Map<String, Collection<String>> responseHeaders) {
107221
super(status, message, request, responseBody, responseHeaders);
108222
this.httpMethod = httpMethod;
109223
this.retryAfter = retryAfter != null ? retryAfter.getTime() : null;

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

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

0 commit comments

Comments
 (0)