1

I have following class in my code, you can say it is just a wrapper over standard RestTemplate. So whenever we have to make an external request instead of using RestTemplate we autowire custom MyRestTemplate.

@Service
@Scope(scopeName = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyRestTemplateImpl implements MyRestTemplate {

private final RestTemplate restTemplate;
private Logger logger = LogManager.getLogger(MyRestTemplateImpl.class);

@Autowired
public MyRestTemplateImpl(RestTemplate restTemplate) {
    this.restTemplate = restTemplate;
}


@Override
public <T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity, Class<T> responseType, Object... uriVariables) throws RestClientException {

    ResponseEntity responseEntity = restTemplate.exchange(url, method, requestEntity, responseType, uriVariables);
          return responseEntity;
    }
}

Now the issue is I am making some Async rest calls, which in turn calls MyRestTemplate to make external REST requests. But it fails giving following error:

Error creating bean with name 'scopedTarget.myRestTemplateImpl': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton

I understand that it is because a new thread is spawned for Async operation and scope request is invalid for that child thread. And it can be solved by using very nice solutions from How to enable request scope in async task executor but, I don't want to go for it at this moment as this Async operation is not so common and also I have some time constraints.

So, My main question is, if I make MyRestTemplateImpl as singleton everything works fine, I did not come across any such issue. But there are many methods using MyRestTemplateImpl for external requests and traffic on the application is also heavy.

Will changing it to Singleton from Request cause any adverse effects like slowness, race condition or any such harmful effect that I am unaware of or not come across as of now ?

If yes, if you can please give proper explanation apart from basic difference between scopes for it would be great as it will give me better reasoning while scoping the beans while I code now onwards. If no, why ?

I know for each request a new bean will be created but please explain what are the actual use cases for request scope with small examples ?

rdj7
  • 1,905
  • 4
  • 18
  • 33
  • 2
    As long as you don't keep state there is nothing to worry. The `RestTEmplate` after construction is thread-safe. It might even improve performance and memory usage. – M. Deinum May 12 '20 at 07:56

1 Answers1

2

If your custom RestTemplate looks exactly like what you put in your sample code, it is of zero utility - you can just use the standard RestTemplate. Also, since you pass in a (presumably) non-request scoped RestTemplate to the constructor, it is not even doing what you think it is doing I suspect. If you really wanted it to be request-scoped and auto-proxied, you can get the same effect without subclassing it. For example:

@Configuration
class RestTemplateConfig {

  @Bean
  @Scope(scopeName = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
  RestTemplate restTemplate() {
    return new RestTemplate();
  }
}

Also note that the @Service stereotype is debatably inaccurate as I don't consider RestTemplate a service. It doesn't matter much, but it would probably be more accurate to stereotype it as @Component.

If your RestTemplate actually adds additional functionality and you omitted it for brevity, then the answer is "it depends". In general, singleton scope is always the right answer.

Request scope is for cases where you need a Spring bean to have data that is only relevant for the current request. I suggest this kind of code should be avoided, but sometimes it is useful. For example, maybe you have an object for collecting statistics for a single request - how many methods were called, how long each takes to complete, etc. You wouldn't want to reuse this across all requests, so you can make it request scoped and it will be recreated for each request.

If your RestTemplate does not have any state that is request specific, there is no point in making a new one each time with request scope. exchange() for example can be called over and over with different parameters each time - there is no need to create a new RestTemplate when calling exchange().

As a rule of thumb, you generally want to avoid anything but singleton scope. You may have some odd cases where other scopes are useful, but they should be scrutinized as it's rare to need other scopes.

SingleShot
  • 18,821
  • 13
  • 71
  • 101
  • thanks for the answer. I currently don't have any other functionality in `MyRestTemplate`, I will remove this `request` scope. Do you think it will have any adverse effects as there are thousands of requests going out from application through `MyRestTemplate` and i am removing it because as per me `request` doesn't do anything special but since I am changing somebody else's code, I am worried about its consequences. – rdj7 May 19 '20 at 10:24
  • If there is nothing "odd" in the implementation, it should work just fine. But as with any change - test! – SingleShot May 20 '20 at 03:04
  • There is nothing odd in the implementation. Yes, will test it properly. Thanks! – rdj7 May 20 '20 at 08:00