Reputation: 124
I have two Java Spring Boot web service apps on the same server calling each other via REST. Service A calls Service B and the latter successfully acts upon the notfication. THE PROBLEM is that Service A never receives the acknowlegement from Service B, so it thinks it has failed, and in accordance with its looping recovery logic, it tries again…and again…and again. Service B ends up doing 3 times the work for no added benefit.
The relevant code (stripped down and falsified to protect the guilty) is as follows:
Service A:
public void giveOrderToServiceB(@RequestBody CustomClass message) {
...
org.springframework.web.client.RestTemplate template = new RestTemplate(clientHttpRequestFactory());
com.mycompany.CustomReply reply = template.postForObject(serviceBUrl, message, CustomReply.class);
Service B REST Controller:
@PostMapping(value="ExecuteTheWork", produces=org.springframework.http.MediaType.APPLICATION_JSON_VALUE, consumes=MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody CustomReply executeTheWork(@RequestBody CustomClass thing) {
// do something with the thing...
CustomReply reply = new CustomReply();
reply.setReply("Successfully executed the work.");
return reply;
}
The actual exception caught by Service A after calling RestTemplate.postForObject() is
java.net.SocketTimeoutException: Read timed out
Please advise.
Upvotes: 0
Views: 2921
Reputation: 2325
When you are registering the bean of rest template in your application it must then configure it with a timeout. Following is the Spring application config file
package com.temp.project.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class TempProjectConfig {
/**
* Set Timeout for HTTP requests
* @return
*/
@Bean
public ClientHttpRequestFactory getClientHttpRequestFactory() {
int timeout = 1200000; // here is the timeout property set for rest template
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory
= new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setConnectTimeout(timeout);
return clientHttpRequestFactory;
}
/**
* RestTemplate to call REST endpoints
* @param clientHttpRequestFactory
* @return
*/
@Bean
public RestTemplate getRestTemplate(ClientHttpRequestFactory clientHttpRequestFactory) {
return new RestTemplate(clientHttpRequestFactory);
}
}
Upvotes: 0
Reputation: 124
OK, I think I got it. I don't send the response back from Service B until after the method has completed all of its work, which can take several seconds to several minutes. If I immediately answer (and skip the processing), it works consistently. Need to spin off the actual work to a separate thread. Cheeers
Upvotes: 0