0

I'm trying to autowire a service to my request filter. It gives me a null pointer exception and I'm not quite sure why. I've used the exact same autowire class in my controller and it works as expected!

@Component(value="jwtFilter")
public class JwtFilter extends GenericFilterBean {
    RedisClient redisClient = new RedisClient();

    @Autowired
    JwtTokenService jwtServ; // Is null for some reason??!!

    @Override
    public void doFilter(final ServletRequest req,
                         final ServletResponse res,
                         final FilterChain chain) throws IOException, ServletException {
//        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); // Doesnt fix issue
        System.out.println("\nMaking request...");
        final HttpServletRequest request = (HttpServletRequest) req;


        final String authHeader = request.getHeader("Authorization");
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            throw new ServletException("Missing or invalid Authorization header.");
        }

        final String token = authHeader.substring(7); // The part after "Bearer "

        try {
            final Claims claims = Jwts.parser().setSigningKey("${userapi.secret}")
                    .parseClaimsJws(token).getBody();
            request.setAttribute("claims", claims);
            request.setAttribute("token", token);
            System.out.println(claims.getSubject() + " <~~ Subject from jwt");
            JwtToken foundT = jwtServ.findByUser(claims.getSubject()); // Fails here because of jwtServ being null
            System.out.println (foundT + " <~~ Found JWT from redis");

        }
        catch (final SignatureException e) {
            throw new ServletException("Invalid token.");
        }


        chain.doFilter(req, res);
    }

Is there something that I've missed out on? I'm not sure why it'd work in my spring controller and not the filter?

Here is my main class with all the @Beans:

@SpringBootApplication
public class UserServiceApplication {
@Bean
    public FilterRegistrationBean jwtFilter() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new JwtFilter());
        registrationBean.addUrlPatterns("/api/v1/*");
        registrationBean.addUrlPatterns("/user/api/v1/*");
        return registrationBean;
    }

    private @Value("${redis.host}") String redisHost;
    private @Value("${redis.port}") int redisPort;

    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }

    @Bean
    public HibernateJpaSessionFactoryBean sessionFactory() {
        return new HibernateJpaSessionFactoryBean();
    }


    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        JedisConnectionFactory jedisConFactory = new JedisConnectionFactory();
        jedisConFactory.setHostName("localhost");
        jedisConFactory.setPort(6379);
        return jedisConFactory;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(jedisConnectionFactory());
        return template;
    }



    @Bean
    ChannelTopic topic() {
        return new ChannelTopic("pubsub:queue");
    }
James111
  • 15,378
  • 15
  • 78
  • 121
  • 3
    Ofcourse it will be `null`... You are doing `new JwtFilter` yourself, no spring, no nothing, no dependency injection. Define a `@Bean` method instead. – M. Deinum Jun 29 '16 at 11:30
  • @M.Deinum - Yep! That did it. Is the better alternative to create a `@bean` (which simply returns a new JwtFilter) or do what the accepted answer suggests (which also works)? – James111 Jun 29 '16 at 11:41
  • You can do both as you have added `@Component` it will be detected. However imho it is better to inject it into the method `jwtFilter(JwtFilter jwtFilter)`. You better rename your `FilterRegistrationBean` as that now will override the actual filter. Which will lead to strange to debug issues. – M. Deinum Jun 29 '16 at 11:44
  • 1
    @M.Deinum - Alright great & Yeah I noticed! – James111 Jun 29 '16 at 11:48

1 Answers1

6

Since you manually instantiate JwtFilter

registrationBean.setFilter(new JwtFilter());

Spring doesn't manage it therefore doesn't inject jwtServ.

To fix it inject jwtFilter into UserServiceApplication and set injected jwtFilter into registrationBean.

@SpringBootApplication
public class UserServiceApplication {

    @Autowired
    private JwtFilter jwtFilter;

    @Bean
    public FilterRegistrationBean jwtFilter() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(jwtFilter);
        ...
    }
    ...
Evgeny
  • 2,483
  • 1
  • 17
  • 24
  • Yep! I just achieved this by creating a `@bean JwtFilter` method and then adding that as the `filter`...This solution seems like the better alternative! – James111 Jun 29 '16 at 11:40