I have a Spring-Boot application which uses Spring-Security. I have a request scoped bean that I want to autowire into one of my custom Filters in the security filter chain, but at the moment it is not working.
I understand that some config is needed to use request scoped beans outside of the DispatcherServlet, and have read this http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/beans.html#beans-factory-scopes-other But have not had any success yet:
For Servlet 3.0+, this can done programmatically via the WebApplicationInitializer interface.
(I am using latest Tomcat so is servlet 3+)
I have tried using both the RequestContextListener and the RequestContextFilter (docs say that they, and the DispatcherServlet, do the exact same thing), but in both cases I still get errors because my autowired object is null:
My attempt to register the Filter
@Configuration @ComponentScan @EnableAutoConfiguration class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure( SpringApplicationBuilder application ) { application.sources( Application ) } @Override public void onStartup( ServletContext servletContext ) throws ServletException { super.onStartup( servletContext ) servletContext.addFilter("requestContextFilter", new RequestContextFilter() ).addMappingForUrlPatterns(null, false, "/*") }
My attempt to register the Listener
@Configuration @ComponentScan @EnableAutoConfiguration class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure( SpringApplicationBuilder application ) { application.sources( Application ) } @Override public void onStartup( ServletContext servletContext ) throws ServletException { super.onStartup( servletContext ) servletContext.addListener( new RequestContextListener() ) }
Am I missing something obvious? I have had a look at the auto config source code for Spring Boot and haven't come across anything yet.
UPDATE
I was being an idiot, I had added my Filter in my SpringSecurity configuration, inside the configure()
method:
http.addFilterBefore( new PreAuthFilter(), BasicAuthenticationFilter )
but hadn't registered the new Filter as a Bean. As per M. Denium's comment below, I didn't need all that additional config explicitly adding the listener/filter, just registering the bean was enough.
Class RequestContextListener Servlet listener that exposes the request to the current thread, through both LocaleContextHolder and RequestContextHolder . To be registered as listener in web.
It's used to wire the configurations from Spring beans together and use them for the application. Use ApplicationContext if you want to retrieve the information of Spring beans. Use ServletContext if you want to get/set attribute those shared to all Servlet.
Spring Boot Servlet Initializer class file allows you to configure the application when it is launched by using Servlet Container. The code for Spring Boot Application class file for JAR file deployment is given below − package com. tutorialspoint. demo; import org.
Spring Boot automatically configures your application based on the dependencies you have added to the project by using @EnableAutoConfiguration annotation. For example, if MySQL database is on your classpath, but you have not configured any database connection, then Spring Boot auto-configures an in-memory database.
As detailed in the update/comments, this was caused by my own stupidity.
Spring-Boot is able to autowire Request/Session scoped beans into filter's that are outside of the DispatcherServlet
As per Spring's documentation, we need to add the RequestContextListener
or RequestContextFilter
to enable this functionality:
To support the scoping of beans at the request, session, and global session levels (web-scoped beans), some minor initial configuration is required before you define your beans. (This initial setup is not required for the standard scopes, singleton and prototype.) ...
If you access scoped beans within Spring Web MVC, in effect, 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.
To handle this, I needed to register a RequestContextListener bean:
@Bean public RequestContextListener requestContextListener(){ return new RequestContextListener(); }
If you don't register that bean, you will get an error stating that you are trying to access the Request scope outside of DispatcherServlet.
The problem I experienced(autowired objects just not being injected) was caused by the fact that I was just registering my custom filter as a standard class instance, not a Spring managed bean:
http.addFilterBefore( new PreAuthFilter(), BasicAuthenticationFilter )
To solve this, I just moved the creation of the PreAuthFilter
to a sepearte @Bean
method, the @Autowired
functionality then worked fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With