0

I'm encountering a issue, where autowiring doesn't work when I add Hystrix(EnableHystrix) in my microservice.

Controller class:

@RestController
@RequestMapping("/login")
@Slf4j
public class LoginController {

    @Autowired
    ILoginService loginService;


    @ApiOperation(value = "Validate user credentials", response = LoginUser.class)
    @PostMapping(value = "/validateCredentials")
    private ResponseEntity<LoginUser> validateUserCredentials(@RequestBody LoginUser logginUser) {
        LoginUser user=loginService.validateUser(logginUser);
         ......
         .....
   }
}

Autowiring of ILoginService works perfectively without Hystrix.

But when I add the dependency( Version 2.2.6 Release)

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
 </dependency>

And enable Hystrix as:

@EnableFeignClients("com.abcd")
@SpringBootApplication
@EnableHystrix
public class MyApplication{

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

}

The Autowire of ILoginService fails and NullPointerException is thrown when trying to access the autowired property.

I have this configuration working fine in other microservices, But fails in this particular microservice. What is going wrong here?

EDIT: StackTrace is:

java.lang.NullPointerException
at com.demo.login.controller.LoginController.validateUserCredentials(LoginController.java:46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)2021-01-28 17:09:12.999 DEBUG 1800 --- [nio-9200-exec-8] com.demo.login.ExceptionsHelper      : Exception: 

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
Harihara_K
  • 174
  • 16

1 Answers1

1

In the current form, its kind of hard to tell what exactly happens. So I'll provide some thoughts that can lead to the solution:

  1. You say,

The Autowire of ILoginService fails and NullPointerException is thrown when trying to access the autowired property.

Usually when its possible to autowire a bean because it doesn't exist or something, spring should throw an exception during the startup and it will be impossible to "access" the autowired property during the statrup because the system won't start, so this is confusing. Maybe if you could provide a stacktrace and the place where you're trying to access the property it could become more clear...

  1. Its possible in theory (again the stacktrace could show that) that someone tries to access the property before the autowiring actually executes. Technically its implemented in spring via BeanPostProcessor with certain priority that might compete with other bean post processors.

Try to rewrite the controller to use constructor injection (so that spring would inject the ILoginService during the construction of the controller:

@RestController
public class LoginController {
    // Note, no autowiring here
    private final ILoginService loginService;

    // If you are on old spring you need to mark this constructor with @Autowired,
    // in the recent spring versions its not required anymore as long as this is the only 
    // constructor of your class
    public LoginController(ILoginService loginService) {
       this.loginService = loginService;
    }
  1. After you're doing this, try to place a breakpoint in the constructor and see what exactly gets injected (this is an advantage of constructor injection in this case)
Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
  • Hi, thanks for answering.I have edited my question to show the autowired property is being used and added stack trace – Harihara_K Jan 28 '21 at 11:42
  • I rewrote it to constructor injection and added a breakpoint. LoginService in injected properly. But `NullPointerException` is still thrown – Harihara_K Jan 28 '21 at 11:48
  • Ok, so with constructor injection it works? – Mark Bramnik Jan 28 '21 at 11:50
  • No, same Null Pointer Exception is thrown when validateUserCredentils method runs – Harihara_K Jan 28 '21 at 11:51
  • 1
    I assume, line 46 is ` LoginUser user=loginService.validateUser(logginUser);` In this case this doesn't make sense - once the controller gets created and the data field is injected who can set "null" to it? Maybe something in the code does it? Make the data field final so that Java won't let changing the field after setting the value in constructor... What happens now? – Mark Bramnik Jan 28 '21 at 11:53
  • Yeah, even I'm wondering the same. I have marked the field as final, and added a log in contructor. It displayes `Injection worked:com.demo.login.service.impl.LoginServiceImpl@3344a978` So Injection is proper right? – Harihara_K Jan 28 '21 at 12:04
  • Exactly, once the service gets injected, I don't see who can "reset" it to null... – Mark Bramnik Jan 28 '21 at 12:09