I'm using RestClient for upstream communication and would like to add some enhancements to make it more robust. Here's my current setup:
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(300);
factory.setReadTimeout(300);
RestClient restClient = RestClient.builder()
.requestFactory(factory)
.baseUrl("http://...:8080/..")
.build();
Map<String, Object> response = restClient.get()
.uri(backend)
.retrieve()
.body(Map.class);
Regarding Environment:
I'd appreciate suggestions on:
Has anyone done this before or can point me to relevant resources?
Here are the working solution I have.
/**
* A service class responsible for processing backend requests with
* retry and circuit breaker mechanisms.
*/
@Service
public class Processor {
private final RestClient restClient;
private final ExecutorService executor;
private final RetryTemplate retryTemplate;
private static final String RESULT = "result";
private static CircuitConfig circuit;
/**
* Constructor for the Processor class.
*
* @param circuit The circuit breaker configuration.
*/
@Autowired
public Processor(CircuitConfig circuit) {
this.circuit = circuit;
// Setting up client request factory with timeouts
SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
simpleClientHttpRequestFactory.setConnectTimeout(300);
simpleClientHttpRequestFactory.setReadTimeout(300);
this.restClient = RestClient.builder()
.requestFactory(simpleClientHttpRequestFactory)
.baseUrl("http://...:8080/../")
.build();
this.executor = Executors.newVirtualThreadPerTaskExecutor();
this.retryTemplate = createRetryTemplate();
System.out.println("CompletableFuture...");
}
/**
* Creates a retry template with exponential back-off policy.
*
* @return A configured RetryTemplate instance.
*/
private RetryTemplate createRetryTemplate() {
RetryTemplate retryTemplate = new RetryTemplate();
// Setting exponential back-off policy
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(100);
backOffPolicy.setMultiplier(2.0);
backOffPolicy.setMaxInterval(1000);
retryTemplate.setBackOffPolicy(backOffPolicy);
// Setting simple retry policy with max attempts
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(3);
retryTemplate.setRetryPolicy(retryPolicy);
return retryTemplate;
}
/**
* Retrieves backend response with retry mechanism.
*
* @param backend The backend URI.
* @return A map representing the backend response.
*/
public Map getBackendResp(String backend) {
return retryTemplate.execute(retryContext ->
restClient
.get()
.uri(backend)
.retrieve()
.body(Map.class));
}
/**
* Wraps the backend request within a CompletableFuture for asynchronous processing.
*
* @param backend The backend URI.
* @return A CompletableFuture containing a map representing the backend response.
*/
private CompletableFuture<Map> getFuture(String backend) {
return CompletableFuture.supplyAsync(() -> circuit.circuitBreaker.executeSupplier(() -> getBackendResp(backend)));
}
}
I wanted to understand if everything operates under the virtual thread paradigm, but this aspect remains ambiguous to me.