Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpringBoot with @Value property in Filter is null

I'm using SpringBoot's @Value annotation to populate an object property from the default application.properties file, but seeing some strange behaviour in a Filter override.

There are two breakpoints in my debugger:

@Component
  public class BasicFilter implements Filter {

  @Value("${aad.client_id}")
  private String clientId;

  @Bean
  public FilterRegistrationBean registerFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new BasicFilter()); // <-- 1.
    registration.addUrlPatterns("/secure/*");
    return registration;
  }

  public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain chain) throws IOException, ServletException {
    if (request instanceof HttpServletRequest) { // <- 2.
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        ...

At 1.: this.client_id is set to 'foo' (from application.properties A2 2.: this.client_id is null

Any explanation for the different/missing values?

like image 255
Black Avatar asked Dec 11 '17 09:12

Black


1 Answers

You're injecting a new BasicFilter() into the FilterRegistrationBean. In this case, you're creating a new object, but it won't be a Spring managed bean, so its clientId will be empty. So basically you have 2 instances now:

  1. One created by Spring due to the @Component annotation
  2. One injected into the FilterRegistrationBean using the new keyword (not managed by Spring)

You should likely move the registerFilter() method to a separate configuration class (annotated with @Configuration) and autowire/inject the BasicFilter bean into that method, eg:

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean registerFilter(BasicFilter filter) { // Inject it
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(filter); // Use it
        registration.addUrlPatterns("/secure/*");
        return registration;
   }
}

Altenatively, if you want to keep the @Bean method in the filter itself, you should replace it by this, since the current object is managed by Spring, while the new instance won't be:

@Bean
public FilterRegistrationBean registerFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(this);
    registration.addUrlPatterns("/secure/*");
    return registration;
}

Related: Spring @Value annotation always evaluating as null?

like image 188
g00glen00b Avatar answered Oct 23 '22 10:10

g00glen00b