0

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.

6
  • Have you checked that Service B actually finishes it's method? I guess the culprit lies somewhere in // do something with the thing... Commented Nov 21, 2018 at 18:59
  • Thanks. Yes, it executes, parses an XML file, makes calls to a database (I can query to see the results) and the logging statement before the final return statement succeeds. Commented Nov 21, 2018 at 19:21
  • I'm wondering if there is something about the JSON marshalling and un-marshalling. Since these services are in separate JVMs they aren't actually referencing the same instances of the return object. Commented Nov 21, 2018 at 19:21
  • 1
    Try to add time to your reste template by doing like this : @Bean public RestTemplate restTemplate( RestTemplateBuilder restTemplateBuilder) { return restTemplateBuilder .setConnectTimeout(500) .setReadTimeout(500) .build(); } Else try to tell us what's is the url of every service ? Commented Nov 21, 2018 at 19:38
  • Inexplicably, it seems to be working now; the return message is getting back to the caller. The only change I made related to this was to put the declaration of the return class variable towards the top of the method body. Go figure. Commented Nov 21, 2018 at 20:05

2 Answers 2

0

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

Sign up to request clarification or add additional context in comments.

Comments

0

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);
    }

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.