Skip to content

Commit

Permalink
Implementing retry logic to restTemplate (#17375)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
3 people committed Dec 12, 2023
1 parent 809b333 commit a792a79
Show file tree
Hide file tree
Showing 11 changed files with 579 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -438,4 +438,8 @@ public static enum ENUM_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case,

public static final String GENERATE_MARSHAL_JSON = "generateMarshalJSON";
public static final String GENERATE_MARSHAL_JSON_DESC = "Generate MarshalJSON method";

public static final String MAX_ATTEMPTS_FOR_RETRY = "maxAttemptsForRetry";

public static final String WAIT_TIME_OF_THREAD = "waitTimeMillis";
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ public class JavaClientCodegen extends AbstractJavaCodegen
protected boolean generateClientAsBean = false;
protected boolean useEnumCaseInsensitive = false;

protected int maxAttemptsForRetry = 1;
protected long waitTimeMillis = 10l;

private static class MpRestClientVersion {
public final String rootPackage;
public final String pomTemplate;
Expand Down Expand Up @@ -465,6 +468,20 @@ public void processOpts() {
if (additionalProperties.containsKey(USE_ENUM_CASE_INSENSITIVE)) {
this.setUseEnumCaseInsensitive(Boolean.parseBoolean(additionalProperties.get(USE_ENUM_CASE_INSENSITIVE).toString()));
}

if (additionalProperties.containsKey(CodegenConstants.MAX_ATTEMPTS_FOR_RETRY)) {
this.setMaxAttemptsForRetry(Integer.parseInt(additionalProperties.get(CodegenConstants.MAX_ATTEMPTS_FOR_RETRY).toString()));
}
else {
additionalProperties.put(CodegenConstants.MAX_ATTEMPTS_FOR_RETRY, maxAttemptsForRetry);
}

if (additionalProperties.containsKey(CodegenConstants.WAIT_TIME_OF_THREAD)) {
this.setWaitTimeMillis(Long.parseLong((additionalProperties.get(CodegenConstants.WAIT_TIME_OF_THREAD).toString())));
}
else {
additionalProperties.put(CodegenConstants.WAIT_TIME_OF_THREAD, waitTimeMillis);
}
writePropertyBack(USE_ENUM_CASE_INSENSITIVE, useEnumCaseInsensitive);

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

public void setMaxAttemptsForRetry(int maxAttemptsForRetry) {
this.maxAttemptsForRetry= maxAttemptsForRetry;
}

public void setWaitTimeMillis(long waitTimeMillis) {
this.waitTimeMillis= waitTimeMillis;
}

/**
* Serialization library.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
Expand Down Expand Up @@ -105,6 +106,10 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
private HttpHeaders defaultHeaders = new HttpHeaders();
private MultiValueMap<String, String> defaultCookies = new LinkedMultiValueMap<String, String>();

private int maxAttemptsForRetry = {{maxAttemptsForRetry}};

private long waitTimeMillis = {{waitTimeMillis}};

private String basePath = "{{basePath}}";

private RestTemplate restTemplate;
Expand Down Expand Up @@ -167,6 +172,46 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
return this;
}

/**
* Get the max attempts for retry
*
* @return int the max attempts
*/
public int getMaxAttemptsForRetry() {
return maxAttemptsForRetry;
}

/**
* Set the max attempts for retry
*
* @param getMaxAttemptsForRetry the max attempts for retry
* @return ApiClient this client
*/
public ApiClient setMaxAttemptsForRetry(int maxAttemptsForRetry) {
this.maxAttemptsForRetry = maxAttemptsForRetry;
return this;
}

/**
* Get the wait time in milliseconds
*
* @return long wait time in milliseconds
*/
public long getWaitTimeMillis() {
return waitTimeMillis;
}

/**
* Set the wait time in milliseconds
*
* @param waitTimeMillis the wait time in milliseconds
* @return ApiClient this client
*/
public ApiClient setWaitTimeMillis(long waitTimeMillis) {
this.waitTimeMillis = waitTimeMillis;
return this;
}

/**
* Get authentications (key: authentication name, value: authentication).
*
Expand Down Expand Up @@ -721,7 +766,23 @@ public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} {
RequestEntity<Object> requestEntity = requestBuilder.body(selectBody(body, formParams, contentType));
ResponseEntity<T> responseEntity = restTemplate.exchange(requestEntity, returnType);
ResponseEntity<T> responseEntity = null;
int attempts = 0;
while (attempts < maxAttemptsForRetry) {
try {
responseEntity = restTemplate.exchange(requestEntity, returnType);
break;
} catch (HttpServerErrorException ex) {
attempts++;
if (attempts < maxAttemptsForRetry) {
try {
Thread.sleep(waitTimeMillis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
if (responseEntity.getStatusCode().is2xxSuccessful()) {
return responseEntity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
Expand Down Expand Up @@ -79,6 +80,10 @@ private String collectionToString(Collection<?> collection) {
private HttpHeaders defaultHeaders = new HttpHeaders();
private MultiValueMap<String, String> defaultCookies = new LinkedMultiValueMap<String, String>();

private int maxAttemptsForRetry = 1;

private long waitTimeMillis = 10;

private String basePath = "http://localhost:3000";

private RestTemplate restTemplate;
Expand Down Expand Up @@ -136,6 +141,46 @@ public ApiClient setBasePath(String basePath) {
return this;
}

/**
* Get the max attempts for retry
*
* @return int the max attempts
*/
public int getMaxAttemptsForRetry() {
return maxAttemptsForRetry;
}

/**
* Set the max attempts for retry
*
* @param getMaxAttemptsForRetry the max attempts for retry
* @return ApiClient this client
*/
public ApiClient setMaxAttemptsForRetry(int maxAttemptsForRetry) {
this.maxAttemptsForRetry = maxAttemptsForRetry;
return this;
}

/**
* Get the wait time in milliseconds
*
* @return long wait time in milliseconds
*/
public long getWaitTimeMillis() {
return waitTimeMillis;
}

/**
* Set the wait time in milliseconds
*
* @param waitTimeMillis the wait time in milliseconds
* @return ApiClient this client
*/
public ApiClient setWaitTimeMillis(long waitTimeMillis) {
this.waitTimeMillis = waitTimeMillis;
return this;
}

/**
* Get authentications (key: authentication name, value: authentication).
*
Expand Down Expand Up @@ -637,7 +682,23 @@ public <T> ResponseEntity<T> invokeAPI(String path, HttpMethod method, Map<Strin

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

ResponseEntity<T> responseEntity = restTemplate.exchange(requestEntity, returnType);
ResponseEntity<T> responseEntity = null;
int attempts = 0;
while (attempts < maxAttemptsForRetry) {
try {
responseEntity = restTemplate.exchange(requestEntity, returnType);
break;
} catch (HttpServerErrorException ex) {
attempts++;
if (attempts < maxAttemptsForRetry) {
try {
Thread.sleep(waitTimeMillis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}

if (responseEntity.getStatusCode().is2xxSuccessful()) {
return responseEntity;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Echo Server API
* Echo Server API
*
* The version of the OpenAPI document: 0.1.0
* Contact: [email protected]
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/


package org.openapitools.client;

import org.junit.Assert;
import org.openapitools.client.api.*;
import org.openapitools.client.model.*;
import org.junit.Test;
import org.junit.Ignore;

import java.io.IOException;
import java.util.*;


/**
* API tests
*/
public class CustomTest {

private final QueryApi api = new QueryApi();
private final BodyApi bodyApi = new BodyApi();

/**
* Test body parameter(s)
* <p>
* Test body parameter(s)
*
*/
@Test
public void testEchoBodyPet() {
Pet pet = new Pet().id(12345L).name("Hello World").
photoUrls(Arrays.asList(new String[]{"http://a.com", "http://b.com"})).category(new Category().id(987L).name("new category"));

Pet p = bodyApi.testEchoBodyPet(pet);
Assert.assertNotNull(p);
Assert.assertEquals("Hello World", p.getName());
Assert.assertEquals(Long.valueOf(12345L), p.getId());

// response is empty body
Pet p2 = bodyApi.testEchoBodyPet(null);
Assert.assertNull(p2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
Expand Down Expand Up @@ -77,6 +78,10 @@ private String collectionToString(Collection<?> collection) {
private HttpHeaders defaultHeaders = new HttpHeaders();
private MultiValueMap<String, String> defaultCookies = new LinkedMultiValueMap<String, String>();

private int maxAttemptsForRetry = 1;

private long waitTimeMillis = 10;

private String basePath = "http://localhost";

private RestTemplate restTemplate;
Expand Down Expand Up @@ -132,6 +137,46 @@ public ApiClient setBasePath(String basePath) {
return this;
}

/**
* Get the max attempts for retry
*
* @return int the max attempts
*/
public int getMaxAttemptsForRetry() {
return maxAttemptsForRetry;
}

/**
* Set the max attempts for retry
*
* @param getMaxAttemptsForRetry the max attempts for retry
* @return ApiClient this client
*/
public ApiClient setMaxAttemptsForRetry(int maxAttemptsForRetry) {
this.maxAttemptsForRetry = maxAttemptsForRetry;
return this;
}

/**
* Get the wait time in milliseconds
*
* @return long wait time in milliseconds
*/
public long getWaitTimeMillis() {
return waitTimeMillis;
}

/**
* Set the wait time in milliseconds
*
* @param waitTimeMillis the wait time in milliseconds
* @return ApiClient this client
*/
public ApiClient setWaitTimeMillis(long waitTimeMillis) {
this.waitTimeMillis = waitTimeMillis;
return this;
}

/**
* Get authentications (key: authentication name, value: authentication).
*
Expand Down Expand Up @@ -580,7 +625,23 @@ public <T> ResponseEntity<T> invokeAPI(String path, HttpMethod method, Map<Strin

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

ResponseEntity<T> responseEntity = restTemplate.exchange(requestEntity, returnType);
ResponseEntity<T> responseEntity = null;
int attempts = 0;
while (attempts < maxAttemptsForRetry) {
try {
responseEntity = restTemplate.exchange(requestEntity, returnType);
break;
} catch (HttpServerErrorException ex) {
attempts++;
if (attempts < maxAttemptsForRetry) {
try {
Thread.sleep(waitTimeMillis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}

if (responseEntity.getStatusCode().is2xxSuccessful()) {
return responseEntity;
Expand Down
Loading

0 comments on commit a792a79

Please sign in to comment.