Skip to content

Commit 752db82

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 752db82

File tree

2 files changed

+141
-5
lines changed

2 files changed

+141
-5
lines changed

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

+116-5
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,66 @@ 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
44+
*/
45+
public RetryableException(
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+
* retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header. If you
93+
* don't want to retry, use {@link #RetryableException(int, String, HttpMethod, Throwable, Request)}.
94+
* @param request the original HTTP request
3795
*/
3896
public RetryableException(
3997
int status,
@@ -47,6 +105,17 @@ public RetryableException(
47105
this.retryAfter = retryAfter;
48106
}
49107

108+
/**
109+
* @deprecated Use {@link #RetryableException(int, String, HttpMethod, Throwable, Long, Request)}
110+
* instead. This constructor uses {@link Date} for retryAfter, which has been replaced by {@link Long}.
111+
*
112+
* @param status the HTTP status code
113+
* @param message the exception message
114+
* @param httpMethod the HTTP method (GET, POST, etc.)
115+
* @param cause the underlying cause of the exception
116+
* @param retryAfter the retry-after time as a {@link Date}
117+
* @param request the original HTTP request
118+
*/
50119
@Deprecated
51120
public RetryableException(
52121
int status,
@@ -61,8 +130,17 @@ public RetryableException(
61130
}
62131

63132
/**
64-
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header. If you
65-
* don't want to retry, set null.
133+
* Represents a retryable exception when Retry-After information is available.
134+
* <p>
135+
* Use this constructor when the server response includes a Retry-After header.
136+
*
137+
* @param status the HTTP status code
138+
* @param message the exception message
139+
* @param httpMethod the HTTP method (GET, POST, etc.)
140+
* @param retryAfter the retry delay in milliseconds
141+
* retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header. If you
142+
* don't want to retry, use {@link #RetryableException(int, String, HttpMethod, Request)}
143+
* @param request the original HTTP request
66144
*/
67145
public RetryableException(
68146
int status, String message, HttpMethod httpMethod, Long retryAfter, Request request) {
@@ -71,6 +149,16 @@ public RetryableException(
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(
76164
int status, String message, HttpMethod httpMethod, Date retryAfter, Request request) {
@@ -80,7 +168,18 @@ public RetryableException(
80168
}
81169

82170
/**
83-
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header.
171+
* Represents a retryable exception with response body and headers.
172+
* <p>
173+
* Use this constructor when handling HTTP responses that include Retry-After information.
174+
*
175+
* @param status the HTTP status code
176+
* @param message the exception message
177+
* @param httpMethod the HTTP method (GET, POST, etc.)
178+
* @param retryAfter the retry delay in milliseconds
179+
* retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header.
180+
* @param request the original HTTP request
181+
* @param responseBody the HTTP response body
182+
* @param responseHeaders the HTTP response headers
84183
*/
85184
public RetryableException(
86185
int status,
@@ -95,6 +194,18 @@ public RetryableException(
95194
this.retryAfter = retryAfter;
96195
}
97196

197+
/**
198+
* @deprecated Use {@link #RetryableException(int, String, HttpMethod, Long, Request, byte[], Map)}
199+
* instead. This constructor uses {@link Date} for retryAfter, which has been replaced by {@link Long}.
200+
*
201+
* @param status the HTTP status code
202+
* @param message the exception message
203+
* @param httpMethod the HTTP method (GET, POST, etc.)
204+
* @param retryAfter the retry-after time as a {@link Date}
205+
* @param request the original HTTP request
206+
* @param responseBody the HTTP response body
207+
* @param responseHeaders the HTTP response headers
208+
*/
98209
@Deprecated
99210
public RetryableException(
100211
int status,

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)