Robert van der Spek
Robert van der Spek

Reputation: 1207

@Value does not inject property, stays null

I have a servlet running and I am trying to inject a property-value into a Filter.

I am confident that the appConfig file is being loaded (when I change the file name, I get a FileNotFound exception). Same count for the properties-file.

It seems the class where I try to inject the property is somehow ignored by Spring. It is a filter (see below). I have experimented with this by adding the property value in the annotation itself. (@Value("${filter.weburl:'some'}"). However, the String webURL remains NULL.

Can anyone help me figure out what is going on here?

package example.servlet.filters;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@Component
public class AuthenticationFilter implements Filter{

    private ServletContext context;
    private final Logger LOGGER = LoggerFactory.getLogger(AuthenticationFilter.class);
    @Value("${filter.weburl:'some'}")
    private String webURL;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.context = filterConfig.getServletContext();
        this.context.log("AuthenticationFilter initialized");

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        Cookie[] cookies = request.getCookies();
        if(cookies != null) {
            for (Cookie cookie : cookies) {
                System.out.println(cookie.getName() + " " + cookie.getValue() + "\n");
            }
        } else {
            ((HttpServletResponse)servletResponse).sendRedirect(webURL + "/inloggen");
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

My AppConfig file:

package example;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

@Configuration
@ComponentScan("example")
@PropertySource("WEB-INF/service.properties")
public class AppConfig {
    @Bean
    public static PropertySourcesPlaceholderConfigurer getPropertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Bean
    public FilterRegistrationBean authenticationFilterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(getAuthenticationFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setName("authenticationFilter");
        filterRegistrationBean.setOrder(1);
        return null;
    }

    @Bean(name="authenticationFilter")
    public AuthenticationFilter getAuthenticationFilter() {
        return new AuthenticationFilter();
    }
}

Upvotes: 4

Views: 1976

Answers (3)

memo
memo

Reputation: 1938

Had the same issue and none of the answers on SE worked for me. The only thing that worked was to replace field injection with method argument injection, i.e. instead of

@Configuration
public class MyConfig  {

    @Value("${jdbc.hibernate.dialect}") 
    private String dialect;
    @Value("${jdbc.hibernate.show_sql}") 
    private String showSql;

    @Bean
    public SessionFactory sessionFactory(DataSource dataSource) {
       ...
    }
}

used this

@Configuration
public class MyConfig  {

    @Bean
    public SessionFactory sessionFactory(DataSource dataSource,
            @Value("${jdbc.hibernate.dialect}") String dialect,
            @Value("${jdbc.hibernate.show_sql}") String showSql) {
        ...
    }
}

Note that the first argument (dataSource) was correctly injected in both cases, only the properties were not.

Upvotes: 0

Strelok
Strelok

Reputation: 51441

If you register a filter in the Application Context it will be registered for all requests, if you use a FilterRegistrationBean, you can customize the URL paths that the filter applies to. You seem to have both and it's probably causing all sorts of problems. Also your filter is annotate with @Component AND you're creating the filter as a bean in your configuration class.

This is how you should structure your code to make it work:

// No @Component annotation keeps this class pure as you're using your configuration class to create beans
public class AuthenticationFilter implements Filter{

    private ServletContext context;
    private final Logger LOGGER = LoggerFactory.getLogger(AuthenticationFilter.class);
    private String webURL;

    public AuthenticationFilter(String webURL) {
      this.webURL = webURL;
    }

    // rest of filter
}

Configuration class:

@Configuration
@ComponentScan("example") //if you have other components to scan, otherwise not required
@PropertySource("WEB-INF/service.properties")
public class AppConfig {

    @Value("${filter.weburl:some}")
    String webURL;

    @Bean
    public static PropertySourcesPlaceholderConfigurer getPropertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Bean
    public FilterRegistrationBean authenticationFilterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new AuthenticationFilter(this.webURL));
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.setName("authenticationFilter");
        filterRegistrationBean.setOrder(1);
        return filterRegistrationBean;
    }
}

Upvotes: 1

Monzurul Shimul
Monzurul Shimul

Reputation: 8386

You need to have following in your configuration class.

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

To configure filter using web.xml do this

<filter>
    <filter-name>authenticationFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>authenticationFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Upvotes: 1

Related Questions