0

I have a service-client project which is in normal spring application , not spring boot .its used for mainly logging related things.which contains Interceptor , loggingservice impl class and some model classes for logging. I have added this module as a dependency to main application in pom.xml.and i was able to inject and use the loggingService beans within the service layers of the main application.

Am getting NullPointerException while auto-wiring loggingService within the interceptor .The bean is not available within the interceptor.but like i said it can be injected and used within the main application.
Also am not able to read properties using @Value within the interceptor.

This is my Interceptor class .

@Component
public class LoggingInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    LoggingService loggingService;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        loggingService.info("Am in prehandle");
        return true;
    }
}

This is my configuration class where i register the interceptor with the main application

@Component
public class LoggingConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getLoginInterceptor());
    }

    @Bean
    public LoggingInterceptor getLoginInterceptor() {
        return new LoggingInterceptor();
    }

}

My question is almost similar to this post Cannot Autowire Service in HandlerInterceptorAdapter , but its different like am referring the interceptor from another module , and like they suggested i tried to create the bean from the application. But the issues am facing right now is

  1. getting NullPointerException while injecting loggingService within interceptor, but its working in main application
  2. @Value annotation also return null, not able to read from properties
M. Deinum
  • 115,695
  • 22
  • 220
  • 224
Ansar Samad
  • 572
  • 2
  • 11
  • 34

1 Answers1

1

You have 2 possible solutions.

  1. Mark your LoggingConfig as @Configuration instead of @Copmponent
  2. Inject the LoggingInterceptor instead of referencing the @Bean method

Option 1: LoggingConfig as @Configuration

Your LoggingConfig is marked as an @Component whereas it should be marked as an @Configuration. The difference is that whilst it is allowed to have an @Bean method on an @Component it operates in a so-called lite mode. Meaning you cannot use method references to get the instance of a bean (this is due to no special proxy being created). This will lead to just a new instance of the LoggingInterceptor being created but it isn't a bean.

So in short what you are doing is equivalent to registry.addInterceptor(new LoggingInterceptor()); which just creates an instance without Spring knowing about it.

When marking the LoggingConfig as an @Configuration a special proxy will be created which will make the LoggingInterceptor a proper singleton bean, due to the method call being intercepted. This will register the bean in Spring and you will be able call the method.

NOTE: You actually endup with 2 instances of the LoggingInterceptor one due to the @Component on it the other through the @Bean. Remove the @Component.

Option 2: Inject the LoggingInterceptor.

As your LoggingInterceptor is marked as an @Component Spring will already create an instance (you actually have 2 instances of it created in your current setup). This instance you can inject into your LoggingConfig.

@Component
public class LoggingConfig implements WebMvcConfigurer {

    private LoggingInterceptor loggingInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loggingInterceptor);
    }
}

With this you can remove the @Bean method as you will get the proper one injected into your LoggingConfig class. The class can also remain an @Component in this case. Although I would recommend using @Configuration as to also properly stereotype it.

NOTE: If you are on a recent Spring version you can use @Configuration(proxyBeanMethods=false). This will make a lite-configuration (just like an @Component) but it is still marked properly as a configuration class.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224