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.