Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configuring RequestContextListener in SpringBoot

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.

like image 747
rhinds Avatar asked May 15 '15 07:05

rhinds


People also ask

What is the use of RequestContextListener?

Class RequestContextListener Servlet listener that exposes the request to the current thread, through both LocaleContextHolder and RequestContextHolder . To be registered as listener in web.

What is Servlet context in spring boot?

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.

What is spring boot Servletinitializer?

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.

How do spring boot applications work internally?

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.


1 Answers

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.

like image 108
rhinds Avatar answered Sep 20 '22 11:09

rhinds