Skip to content

Commit a792a79

Browse files
rubiniselvarajRubiniwing328
authored
Implementing retry logic to restTemplate (#17375)
* Implementing retry logic to restTemplate * Fixing the issue * Adding import * Fix * Fix * minor update, add tests * fix * Adding the maxRetryAttempt, threadWaitTime as additionalProperty * Updating the apiClient * Removing reduntant variable * Generating samples * Fixing format --------- Co-authored-by: Rubini <[email protected]> Co-authored-by: William Cheng <[email protected]>
1 parent 809b333 commit a792a79

File tree

11 files changed

+579
-8
lines changed

11 files changed

+579
-8
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,4 +438,8 @@ public static enum ENUM_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case,
438438

439439
public static final String GENERATE_MARSHAL_JSON = "generateMarshalJSON";
440440
public static final String GENERATE_MARSHAL_JSON_DESC = "Generate MarshalJSON method";
441+
442+
public static final String MAX_ATTEMPTS_FOR_RETRY = "maxAttemptsForRetry";
443+
444+
public static final String WAIT_TIME_OF_THREAD = "waitTimeMillis";
441445
}

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ public class JavaClientCodegen extends AbstractJavaCodegen
139139
protected boolean generateClientAsBean = false;
140140
protected boolean useEnumCaseInsensitive = false;
141141

142+
protected int maxAttemptsForRetry = 1;
143+
protected long waitTimeMillis = 10l;
144+
142145
private static class MpRestClientVersion {
143146
public final String rootPackage;
144147
public final String pomTemplate;
@@ -465,6 +468,20 @@ public void processOpts() {
465468
if (additionalProperties.containsKey(USE_ENUM_CASE_INSENSITIVE)) {
466469
this.setUseEnumCaseInsensitive(Boolean.parseBoolean(additionalProperties.get(USE_ENUM_CASE_INSENSITIVE).toString()));
467470
}
471+
472+
if (additionalProperties.containsKey(CodegenConstants.MAX_ATTEMPTS_FOR_RETRY)) {
473+
this.setMaxAttemptsForRetry(Integer.parseInt(additionalProperties.get(CodegenConstants.MAX_ATTEMPTS_FOR_RETRY).toString()));
474+
}
475+
else {
476+
additionalProperties.put(CodegenConstants.MAX_ATTEMPTS_FOR_RETRY, maxAttemptsForRetry);
477+
}
478+
479+
if (additionalProperties.containsKey(CodegenConstants.WAIT_TIME_OF_THREAD)) {
480+
this.setWaitTimeMillis(Long.parseLong((additionalProperties.get(CodegenConstants.WAIT_TIME_OF_THREAD).toString())));
481+
}
482+
else {
483+
additionalProperties.put(CodegenConstants.WAIT_TIME_OF_THREAD, waitTimeMillis);
484+
}
468485
writePropertyBack(USE_ENUM_CASE_INSENSITIVE, useEnumCaseInsensitive);
469486

470487
final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/");
@@ -1240,6 +1257,14 @@ public void setUseEnumCaseInsensitive(boolean useEnumCaseInsensitive) {
12401257
this.useEnumCaseInsensitive = useEnumCaseInsensitive;
12411258
}
12421259

1260+
public void setMaxAttemptsForRetry(int maxAttemptsForRetry) {
1261+
this.maxAttemptsForRetry= maxAttemptsForRetry;
1262+
}
1263+
1264+
public void setWaitTimeMillis(long waitTimeMillis) {
1265+
this.waitTimeMillis= waitTimeMillis;
1266+
}
1267+
12431268
/**
12441269
* Serialization library.
12451270
*

modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/ApiClient.mustache

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import org.springframework.util.CollectionUtils;
3131
import org.springframework.util.LinkedMultiValueMap;
3232
import org.springframework.util.MultiValueMap;
3333
import org.springframework.util.StringUtils;
34+
import org.springframework.web.client.HttpServerErrorException;
3435
import org.springframework.web.client.RestClientException;
3536
import org.springframework.web.client.RestTemplate;
3637
import org.springframework.web.util.UriComponentsBuilder;
@@ -105,6 +106,10 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
105106
private HttpHeaders defaultHeaders = new HttpHeaders();
106107
private MultiValueMap<String, String> defaultCookies = new LinkedMultiValueMap<String, String>();
107108

109+
private int maxAttemptsForRetry = {{maxAttemptsForRetry}};
110+
111+
private long waitTimeMillis = {{waitTimeMillis}};
112+
108113
private String basePath = "{{basePath}}";
109114

110115
private RestTemplate restTemplate;
@@ -167,6 +172,46 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
167172
return this;
168173
}
169174

175+
/**
176+
* Get the max attempts for retry
177+
*
178+
* @return int the max attempts
179+
*/
180+
public int getMaxAttemptsForRetry() {
181+
return maxAttemptsForRetry;
182+
}
183+
184+
/**
185+
* Set the max attempts for retry
186+
*
187+
* @param getMaxAttemptsForRetry the max attempts for retry
188+
* @return ApiClient this client
189+
*/
190+
public ApiClient setMaxAttemptsForRetry(int maxAttemptsForRetry) {
191+
this.maxAttemptsForRetry = maxAttemptsForRetry;
192+
return this;
193+
}
194+
195+
/**
196+
* Get the wait time in milliseconds
197+
*
198+
* @return long wait time in milliseconds
199+
*/
200+
public long getWaitTimeMillis() {
201+
return waitTimeMillis;
202+
}
203+
204+
/**
205+
* Set the wait time in milliseconds
206+
*
207+
* @param waitTimeMillis the wait time in milliseconds
208+
* @return ApiClient this client
209+
*/
210+
public ApiClient setWaitTimeMillis(long waitTimeMillis) {
211+
this.waitTimeMillis = waitTimeMillis;
212+
return this;
213+
}
214+
170215
/**
171216
* Get authentications (key: authentication name, value: authentication).
172217
*
@@ -721,7 +766,23 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
721766
722767
RequestEntity<Object> requestEntity = requestBuilder.body(selectBody(body, formParams, contentType));
723768
724-
ResponseEntity<T> responseEntity = restTemplate.exchange(requestEntity, returnType);
769+
ResponseEntity<T> responseEntity = null;
770+
int attempts = 0;
771+
while (attempts < maxAttemptsForRetry) {
772+
try {
773+
responseEntity = restTemplate.exchange(requestEntity, returnType);
774+
break;
775+
} catch (HttpServerErrorException ex) {
776+
attempts++;
777+
if (attempts < maxAttemptsForRetry) {
778+
try {
779+
Thread.sleep(waitTimeMillis);
780+
} catch (InterruptedException e) {
781+
Thread.currentThread().interrupt();
782+
}
783+
}
784+
}
785+
}
725786
726787
if (responseEntity.getStatusCode().is2xxSuccessful()) {
727788
return responseEntity;

samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/ApiClient.java

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.springframework.util.LinkedMultiValueMap;
2323
import org.springframework.util.MultiValueMap;
2424
import org.springframework.util.StringUtils;
25+
import org.springframework.web.client.HttpServerErrorException;
2526
import org.springframework.web.client.RestClientException;
2627
import org.springframework.web.client.RestTemplate;
2728
import org.springframework.web.util.UriComponentsBuilder;
@@ -79,6 +80,10 @@ private String collectionToString(Collection<?> collection) {
7980
private HttpHeaders defaultHeaders = new HttpHeaders();
8081
private MultiValueMap<String, String> defaultCookies = new LinkedMultiValueMap<String, String>();
8182

83+
private int maxAttemptsForRetry = 1;
84+
85+
private long waitTimeMillis = 10;
86+
8287
private String basePath = "http://localhost:3000";
8388

8489
private RestTemplate restTemplate;
@@ -136,6 +141,46 @@ public ApiClient setBasePath(String basePath) {
136141
return this;
137142
}
138143

144+
/**
145+
* Get the max attempts for retry
146+
*
147+
* @return int the max attempts
148+
*/
149+
public int getMaxAttemptsForRetry() {
150+
return maxAttemptsForRetry;
151+
}
152+
153+
/**
154+
* Set the max attempts for retry
155+
*
156+
* @param getMaxAttemptsForRetry the max attempts for retry
157+
* @return ApiClient this client
158+
*/
159+
public ApiClient setMaxAttemptsForRetry(int maxAttemptsForRetry) {
160+
this.maxAttemptsForRetry = maxAttemptsForRetry;
161+
return this;
162+
}
163+
164+
/**
165+
* Get the wait time in milliseconds
166+
*
167+
* @return long wait time in milliseconds
168+
*/
169+
public long getWaitTimeMillis() {
170+
return waitTimeMillis;
171+
}
172+
173+
/**
174+
* Set the wait time in milliseconds
175+
*
176+
* @param waitTimeMillis the wait time in milliseconds
177+
* @return ApiClient this client
178+
*/
179+
public ApiClient setWaitTimeMillis(long waitTimeMillis) {
180+
this.waitTimeMillis = waitTimeMillis;
181+
return this;
182+
}
183+
139184
/**
140185
* Get authentications (key: authentication name, value: authentication).
141186
*
@@ -637,7 +682,23 @@ public <T> ResponseEntity<T> invokeAPI(String path, HttpMethod method, Map<Strin
637682

638683
RequestEntity<Object> requestEntity = requestBuilder.body(selectBody(body, formParams, contentType));
639684

640-
ResponseEntity<T> responseEntity = restTemplate.exchange(requestEntity, returnType);
685+
ResponseEntity<T> responseEntity = null;
686+
int attempts = 0;
687+
while (attempts < maxAttemptsForRetry) {
688+
try {
689+
responseEntity = restTemplate.exchange(requestEntity, returnType);
690+
break;
691+
} catch (HttpServerErrorException ex) {
692+
attempts++;
693+
if (attempts < maxAttemptsForRetry) {
694+
try {
695+
Thread.sleep(waitTimeMillis);
696+
} catch (InterruptedException e) {
697+
Thread.currentThread().interrupt();
698+
}
699+
}
700+
}
701+
}
641702

642703
if (responseEntity.getStatusCode().is2xxSuccessful()) {
643704
return responseEntity;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Echo Server API
3+
* Echo Server API
4+
*
5+
* The version of the OpenAPI document: 0.1.0
6+
* Contact: [email protected]
7+
*
8+
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
9+
* https://openapi-generator.tech
10+
* Do not edit the class manually.
11+
*/
12+
13+
14+
package org.openapitools.client;
15+
16+
import org.junit.Assert;
17+
import org.openapitools.client.api.*;
18+
import org.openapitools.client.model.*;
19+
import org.junit.Test;
20+
import org.junit.Ignore;
21+
22+
import java.io.IOException;
23+
import java.util.*;
24+
25+
26+
/**
27+
* API tests
28+
*/
29+
public class CustomTest {
30+
31+
private final QueryApi api = new QueryApi();
32+
private final BodyApi bodyApi = new BodyApi();
33+
34+
/**
35+
* Test body parameter(s)
36+
* <p>
37+
* Test body parameter(s)
38+
*
39+
*/
40+
@Test
41+
public void testEchoBodyPet() {
42+
Pet pet = new Pet().id(12345L).name("Hello World").
43+
photoUrls(Arrays.asList(new String[]{"http://a.com", "http://b.com"})).category(new Category().id(987L).name("new category"));
44+
45+
Pet p = bodyApi.testEchoBodyPet(pet);
46+
Assert.assertNotNull(p);
47+
Assert.assertEquals("Hello World", p.getName());
48+
Assert.assertEquals(Long.valueOf(12345L), p.getId());
49+
50+
// response is empty body
51+
Pet p2 = bodyApi.testEchoBodyPet(null);
52+
Assert.assertNull(p2);
53+
}
54+
}

samples/client/others/java/resttemplate-useAbstractionForFiles/src/main/java/org/openapitools/client/ApiClient.java

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.springframework.util.LinkedMultiValueMap;
2323
import org.springframework.util.MultiValueMap;
2424
import org.springframework.util.StringUtils;
25+
import org.springframework.web.client.HttpServerErrorException;
2526
import org.springframework.web.client.RestClientException;
2627
import org.springframework.web.client.RestTemplate;
2728
import org.springframework.web.util.UriComponentsBuilder;
@@ -77,6 +78,10 @@ private String collectionToString(Collection<?> collection) {
7778
private HttpHeaders defaultHeaders = new HttpHeaders();
7879
private MultiValueMap<String, String> defaultCookies = new LinkedMultiValueMap<String, String>();
7980

81+
private int maxAttemptsForRetry = 1;
82+
83+
private long waitTimeMillis = 10;
84+
8085
private String basePath = "http://localhost";
8186

8287
private RestTemplate restTemplate;
@@ -132,6 +137,46 @@ public ApiClient setBasePath(String basePath) {
132137
return this;
133138
}
134139

140+
/**
141+
* Get the max attempts for retry
142+
*
143+
* @return int the max attempts
144+
*/
145+
public int getMaxAttemptsForRetry() {
146+
return maxAttemptsForRetry;
147+
}
148+
149+
/**
150+
* Set the max attempts for retry
151+
*
152+
* @param getMaxAttemptsForRetry the max attempts for retry
153+
* @return ApiClient this client
154+
*/
155+
public ApiClient setMaxAttemptsForRetry(int maxAttemptsForRetry) {
156+
this.maxAttemptsForRetry = maxAttemptsForRetry;
157+
return this;
158+
}
159+
160+
/**
161+
* Get the wait time in milliseconds
162+
*
163+
* @return long wait time in milliseconds
164+
*/
165+
public long getWaitTimeMillis() {
166+
return waitTimeMillis;
167+
}
168+
169+
/**
170+
* Set the wait time in milliseconds
171+
*
172+
* @param waitTimeMillis the wait time in milliseconds
173+
* @return ApiClient this client
174+
*/
175+
public ApiClient setWaitTimeMillis(long waitTimeMillis) {
176+
this.waitTimeMillis = waitTimeMillis;
177+
return this;
178+
}
179+
135180
/**
136181
* Get authentications (key: authentication name, value: authentication).
137182
*
@@ -580,7 +625,23 @@ public <T> ResponseEntity<T> invokeAPI(String path, HttpMethod method, Map<Strin
580625

581626
RequestEntity<Object> requestEntity = requestBuilder.body(selectBody(body, formParams, contentType));
582627

583-
ResponseEntity<T> responseEntity = restTemplate.exchange(requestEntity, returnType);
628+
ResponseEntity<T> responseEntity = null;
629+
int attempts = 0;
630+
while (attempts < maxAttemptsForRetry) {
631+
try {
632+
responseEntity = restTemplate.exchange(requestEntity, returnType);
633+
break;
634+
} catch (HttpServerErrorException ex) {
635+
attempts++;
636+
if (attempts < maxAttemptsForRetry) {
637+
try {
638+
Thread.sleep(waitTimeMillis);
639+
} catch (InterruptedException e) {
640+
Thread.currentThread().interrupt();
641+
}
642+
}
643+
}
644+
}
584645

585646
if (responseEntity.getStatusCode().is2xxSuccessful()) {
586647
return responseEntity;

0 commit comments

Comments
 (0)