Affects: 5.2.4 (Spring Boot 2.2.6)


I have a rest service that uses a @RequestScope bean to store some data.

Now I want to use the same classes that I use for my service in a background task. However, in this scenario there is of course no RequestScope.

My goal is the following:

If there is a RequestScope, inject the bean and use it. If there is no RequestScope, don't use the bean at all.

This is more or less my code:

 @Autowired
 private ObjectProvider<LogDetails> logDetailsProvider;

  public void doStuff() {
    // ... 
    logDetailsProvider.ifAvailable(logDetails -> logDetails.add("result", result));
    // ... 
  }

My expectation is that this code also works in a background thread and simply does not use the LogDetails class, but instead a BeanCreationException is thrown.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.logDetails': 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; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:368)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
...

Comment From: sbrannen

Thanks for raising the issue.

I can certainly understand your expectation and confusion with the status quo.

Speaking of the status quo, the meaning of "available" in the current implementation is related to the presence of a bean definition for the given type. The current implementation does not take into account that the actual bean may not be available if it's a scoped bean and the necessary scope is not active.

In light of that, we will expand the meaning of "available" in this context to cover the latter use case as well in Spring Framework 5.3.

Comment From: mnisius

Thank you! I think that is a very good decision. The current behavoir is rather confusing.

If anyone has the same issue here is a workaround:

 @Autowired
 private LogDetails logDetails;

  public void doStuff() {
     // ... 
      if (RequestContextHolder.getRequestAttributes() != null)  {
          logDetails.add("result", result);
      }
    // ... 
  }

Comment From: jhoeller

I've introduced a ScopeNotActiveException, thrown from the factory instead of a plain BeanCreationException now, and explicitly ignored in the ObjectProvider availability methods (including ifAvailable and ifUnique). To be available in the upcoming 5.3 snapshot.