I'm trying instantiate a component object for which I declared the <bean>
entry in applicationContext.xml. The flow to instantiate my target component class is as follows
CalculateController -> CalculateService -> CalculateComponent
Where
CalculatorController - scope = request, annotated with @Controller and included in component scan in webapplicationContext.xml
CalculatorService - Scope = singleton, annotated with @service and included in component scan in applicationContext.xml
CalculateComponent - scope = request, no annotation, excluded from component scan in both webapplicationConext.xml and applicationContext.xml. Defined bean entry in webApplicationContext.xml with scope = request. Also include
<aop:scoped-proxy/>
in the <bean>
definition.
I have included the following entry in web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring/applicationContext.xml
/WEB-INF/mvc-dispatcher-servlet.xml
....Other resource xmls
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- To retrieve session related information -->
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
note that, the CalculateComponent has a 3 parameter ref object constructor and all three of them has <bean>
entry in webApplicationContext.xml with singleton scope and they are not annotated.
When the request send to create the CalculateComponent object, spring container throwing the following error.
"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/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request."
Please advise.
Update:
When I removed /WEB-INF/mvc-dispatcher-servlet.xml from contextConfigLocation and started the server, I got the Autowired failed error - "No qualifying bean of type CalculateComponent found for dependency:", even after I changed the scope from request to singleton.
Then I commented out the Autowiring of CalculateComponent in CalculateService and I can now see the CalculateComponent initiated twice (as mentioned my @Serge Ballesta). So I concluded that the CalculateService is initiated via ContextLoaderListener (bean entry in applicationContext.xml), before the DispatcherServlet is loaded(i.e no bean mentioned in mvc-dispatcher-servlet is loaded).
I added the /WEB-INF/mvc-dispatcher-servlet.xml back again in contextConfigLocation, but this time as the first entry (i.e on top of applicationContext.xml). Now the CalculateComponent loaded twice again and the Autowiring was done with singleton scope. With this setup I changed the CalculateComponent scope back to request, but again "I got the No thread-bound request found" error.
So the issue is,
ContextLoaderListener trying to initiaze the resources of DispatcherServlet(CalculateComponent) before its loaded / available.
Answering my own question. As I mentioned in my question this is my flow to get the request scoped component bean.
CalculateController -> CalculateService -> CalculateComponent.
But the CalculateController was invoked through an async request. We cannot access the web scoped beans from the async request thread.
Reference: How to enable request scope in async task executor