I have a singleton service class with an autowired field like:
#Service
public class MyService{
#Autowired
private List<POJO> listWithObjectsForRequest;
}
the listWithObjectsForRequest is used im multiple services and components of my Spring Boot Application and a lot of calculations are required to create this list. It also depends on the current request that is running. So I thought I could write a request scoped bean, that will be injected by Spring every time a request enters my application:
#Configuration
public class MyServiceConfiguration{
#Bean
#RequestScope
public List<POJO> listWithObjectsForRequest(){
return heavyCalculations() // signature: public List<POJO> heavyCalculations()...
}
}
But I get the following error on application startup:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myService': Unsatisfied dependency expressed through field 'listWithObjectsForRequest'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.listWithObjectsForRequest': 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.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1247)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
... 31 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.listWithObjectsForRequest': 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.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:193)
at com.sun.proxy.$Proxy84.equals(Unknown Source)
at java.util.concurrent.ConcurrentHashMap.containsValue(ConcurrentHashMap.java:985)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.determineAutowireCandidate(DefaultListableBeanFactory.java:1501)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1222)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
... 44 common frames omitted
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)
... 53 common frames omitted
I thought I found the answer here: Inject request scoped bean into another bean but my application still fails with this error message.
I know that the listWithObjectsForRequest can only be calculated in request scope, but how to tell spring that the field of MyService should only be initialized (once) in request?
You will get this exception because you are trying to inject request scope into singleton. Singleton will be created once and dependency will be injected once. You might be using some functionality which is depended on request, and during bean initialization of singleton, spring is unable to find it.
If you want to inject request scope bean into singleton you can do this by either
Inject ApplicationContext into MyService like -
#Autowired
private ApplicationContext context;
Then instead of autowiring listWithObjectsForRequest, get bean reference from the application context every time. Though this approach will solve the issue, but will bound your code with the Spring. If you are OK with it you can use it.
Or
You can use method injection as mentioned here - https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-method-injection
As already mentioned in other answers, you are getting this error because of injecting request scoped bean into a singleton scoped bean aka narrower bean DI problem
You just need to use
#Autowired
// provider from javax.inject.Provider;
private Provider<List<POJO>> listWithObjectsForRequest;
References
When to use javax.inject.Provider in Spring?
in Class POJO
try
#Scope("prototype")
before class declaration
Related
Using #Async annotation I want to call a method in a different thread that has access to Session and Request scoped classes.
However when the ApplicationContext tries to get the bean the following exception is generated:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.sessionInfoClass': Scope 'session' is not active for the current thread;
I had tried extending ApplicationContextAware class to hold the main thread context.
Also I had tried the suggested solution from this question How to enable request scope in async task executor
Source coude is in Github
https://github.com/saavedrah/spring-threadSample
I have created a pull request for your repo that solves the issue.
Basically, I extended this solution also for Runnable case.
To verify it, run the ThreadSampleApplication class then hit http://localhost:8080/testAsync
I saw 'application' scope in the following blog. Is it true?
http://www.concretepage.com/spring/spring-bean-scope-example-using-scope-annotation-and-xml-for-singleton-prototype-request-session-global-session-and-application-scope-with-scoped-proxy
Because, as per my surfing, I got to know spring has only the below 5 scopes. Please correct me if I'm wrong.
Singleton
Prototype
Request
Session
Global Session
There is a section on the official doc which is related to the bean scopes:
7.5 Bean scopes
Basically, they define the next:
singleton (Default) Scopes a single bean definition to a single object instance per Spring IoC container.
prototype
Scopes a single bean definition to any number of object instances.
request
Scopes a single bean definition to the lifecycle of a single HTTP request; that is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
session
Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
globalSession
Scopes a single bean definition to the lifecycle of a global HTTP Session. Typically only valid when used in a Portlet context. Only valid in the context of a web-aware Spring ApplicationContext.
application
Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
websocket
Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.
Furthermore, as Spring 3.0 exists other scope thread scope but is not registered by default, moreover you could even create your own scope:
As of Spring 3.0, a thread scope is available, but is not registered
by default. For more information, see the documentation for
SimpleThreadScope. For instructions on how to register this or any
another custom scope, see the section called “Using a custom scope”.
There is a section which explains how to define your custom scope:
7.5.5 Custom scopes
Respect to Application scope, they define it as next:
The Spring container creates a new instance of the AppPreferences bean
by using the appPreferences bean definition once for the entire web
application. That is, the appPreferences bean is scoped at the
ServletContext level, stored as a regular ServletContext attribute.
It also explains the difference between a Spring singleton bean:
This is somewhat similar to a Spring singleton bean but differs in two
important ways: It is a singleton per ServletContext, not per Spring
'ApplicationContext' (for which there may be several in any given web
application), and it is actually exposed and therefore visible as a
ServletContext attribute
So in case you are looking to use with XML:
<bean id="apps" class="com.App" scope="application"/>
Or annotation:
#ApplicationScope
#Component
public class App {
// ...
}
application
Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
Follow the link for more details:
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes
For my Spring Application I've used an Aspect solely for the purpose of logging (for logback). Now my next step to achieve web request logging is to invoke this aspect (using pointcut definitions) inside Spring's layer that accepts web requests and sends out web responses a.k.a the ServletDispatcher.
Now, intense Googling has revealed a 100+ voted answer of plugging a custom Servelet Dispatcher here: Spring Boot - How to log all requests and responses with exceptions in single place?
However, when I initialise the following inside my '#Configuration' class:
#Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet() {
return new LoggableDispatcherServlet();
}
#Bean
public ServletRegistrationBean dispatcherRegistration() {
return new ServletRegistrationBean(dispatcherServlet());
}
I get the following error:
2017-03-20 19:25:08 ERROR o.s.boot.SpringApplication - Application startup failed
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:137)
at ....
Caused by:
org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:117)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:84)
at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:537)
at ...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dispatcherRegistration' defined in class path resource [com/glass/round/activitystream/core/config/AppConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.servlet.ServletRegistrationBean]: Factory method 'dispatcherRegistration' threw exception; nested exception is java.lang.IllegalStateException: #Bean method AppConfig.dispatcherServlet called as a bean reference for type [org.springframework.web.servlet.DispatcherServlet] but overridden by non-compatible bean instance of type [com.sun.proxy.$Proxy76]. Overriding bean of same name declared in: class path resource [com/glass/round/activitystream/core/config/AppConfig.class]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173) ...
Caused by: java.lang.IllegalStateException: #Bean method AppConfig.dispatcherServlet called as a bean reference for type [org.springframework.web.servlet.DispatcherServlet] but overridden by non-compatible bean instance of type [com.sun.proxy.$Proxy76]. Overriding bean of same name declared in: class path resource [com/glass/round/activitystream/core/config/AppConfig.class]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:394)
at com.glass.round.activitystream.core.config.AppConfig$$EnhancerBySpringCGLIB$$ebcc6548.dispatcherServlet(<generated>)
at com.glass.round.activitystream.core.config.AppConfig.dispatcherRegistration(AppConfig.java:22)
at com.glass.round.activitystream.core.config.AppConfig$$EnhancerBySpringCGLIB$$ebcc6548.CGLIB$dispatcherRegistration$1(<generated>)
at com.glass.round.activitystream.core.config.AppConfig$$EnhancerBySpringCGLIB$$ebcc6548$$FastClassBySpringCGLIB$$5f3414d3.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356)
at com.glass.round.activitystream.core.config.AppConfig$$EnhancerBySpringCGLIB$$ebcc6548.dispatcherRegistration(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 26 common frames omitted
so the two obvious doubts are:
1.) why is Spring's default DispatcherServlet overriding my explicit Bean definition ?
2.) How to over come the above and will it help me in my goal ? Am I thinking right ?
I have a request-scoped bean which are used in app. Now I need to implement some predefined configuration beans. I tried both ways:
as a InitializingBean implementation
as a spring's ApplicationListener<ApplicationReadyEvent> listener
but the problem is that code within this config beans uses erquest-scoped bean and everytime I get a:
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?
is there any way of simulating request?
In my application, I have the following startup bean:
#Startup
#Singleton
#DependsOn("RecordAcumulator")
public class StartupBean {
private static final Logger logger = Logger.getLogger(StartupBean.class);
#Inject
RecordAcumulator recordAcumulator;
/**
* Initializes the EJB system on the post construct event
*/
#PostConstruct
public void init() {
The record accumulator is an EJB that accesses the database. The startup is intended to preload database tables into the cache.
#Stateless
public class RecordAcumulator {
When this launches, I get
Caused by: com.ibm.ws.exception.RuntimeWarning: CNTR0200E: The StartupBean singleton session bean in the EJB.jar module depends on the RecordAcumulator enterprise bean in the EJB.jar, but the target is not a singleton session bean.
I have tried many variations of this and I can't seem to get the thing to inject. My log file indicates that the RecordAcumulator EJB was bound prior to the startup bean being loaded, so I can't figure out why I can't inject the EJB into my startup.
If I remove the #DependsOn I get this:
Caused by: javax.ejb.NoSuchEJBException: An error occurred during initialization of singleton session bean bla#EJB.jar#StartupBean, resulting in the discarding of the singleton instance.; nested exception is: javax.ejb.EJBException: The #Inject java.lang.reflect.Field.recordAcumulator reference of type com.foo.bar.accum.RecordAcumulator for the StartupBean component in the EJB.jar module of the bla application cannot be resolved.
Any ideas how to pull this off?
EDIT----------
I found this link:
Controlling CDI Startup inside EJB 3.1
But the issue with that is i'm using WAS 8.5.5.0, That issue was supposed to be resolved in 8.5.0.2
From what I can see:
Remove the #DependsOn
Make your EJB #Singleton
There can be complexities with singleton EJBs, as all the traffic going through your application will go through that one instance. In your case that may not be an issue.