If you are accessing scoped beans within Spring Web MVC, i.e. within a request that is processed by the Spring DispatcherServlet, or DispatcherPortlet, then no special setup is necessary: DispatcherServlet and DispatcherPortlet already expose all relevant state.
If you are runnning outside of Spring MVC ( Not processed by DispatchServlet) you have to use the RequestContextListener
Not just ContextLoaderListener
.
Add the following in your web.xml
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
That will provide session to Spring in order to maintain the beans in that scope
Update :
As per other answers , the @Controller
only sensible when you are with in Spring MVC Context, So the @Controller is not serving actual purpose in your code. Still you can inject your beans into any where with session scope / request scope ( you don't need Spring MVC / Controller to just inject beans in particular scope) .
Update :
RequestContextListener exposes the request to the current Thread only.
You have autowired ReportBuilder in two places
1. ReportPage
- You can see Spring injected the Report builder properly here, because we are still in Same web Thread. i did changed the order of your code to make sure the ReportBuilder injected in ReportPage like this.
log.info("ReportBuilder name: {}", reportBuilder.getName());
reportController.getReportData();
i knew the log should go after as per your logic , just for debug purpose i added .
2. UselessTasklet
- We got exception , here because this is different thread created by Spring Batch , where the Request is not exposed by RequestContextListener
.
You should have different logic to create and inject ReportBuilder
instance to Spring Batch ( May Spring Batch Parameters and using Future<ReportBuilder>
you can return for future reference)