Affects: 5.1.4


ObjectProvider.ifAvailable and ObjectProvider.getIfAvailable should take scope availability into consideration.

Example: Invoking ObjectProvider.ifAvailable for a request scoped bean when the request scope isn't actually available will trigger an error: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.tenant': 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:365) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:672) at Tenant$$EnhancerBySpringCGLIB$$4e4ce2a6.getName(<generated>) at EntityManagerAspect.lambda$0(EntityManagerAspect.java:34) at org.springframework.beans.factory.ObjectProvider.ifAvailable(ObjectProvider.java:93) at EntityManagerAspect.enableMultiTenantsFilter(EntityManagerAspect.java:33) at org.hibernate.internal.SessionFactoryImpl.createEntityManager(SessionFactoryImpl.java:614) at org.hibernate.internal.SessionFactoryImpl.createEntityManager(SessionFactoryImpl.java:154) at org.apache.logging.log4j.core.appender.db.jpa.JpaDatabaseManager.connectAndStart(JpaDatabaseManager.java:77) ... 18 more Caused by: 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.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:42) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:353) And the only workaround I see is to manually check if the scope is available, which IMHO defeats the purpose of such a method (and a generic way to check if a scope is available doesn't seem to exist).

Comment From: jhoeller

The case you're showing here seems to involve a scoped proxy which is rather tricky: It can be obtained fine but then fails when any method on it gets invoked if the target scope is not available. From a technical perspective, ObjectProvider is right in passing that instance to you: The proxy object is available, after all, and you might just store it or pass it on without invoking a method on it quite yet.

We could consider checking scope availability for a raw scoped bean but you'd have to change your scoped bean definition to non-proxied then. I'm not sure that's a common enough case in general.

Comment From: andrei-ivanov

Yes, I think the Tenant instance gets automatically created as a (request) scoped proxy and it gets injected into a singleton scoped EntityManagerAspect or obtained through ObjectProvider. But I wanted to make sure the object that I receive is actually usable, otherwise getIfAvailable isn't that interesting. Maybe a new getIfUsable should be added? 🙂

Comment From: jhoeller

Duplicate of #24822. Sorry for missing this original ticket for the revision in 5.3 M1.