micronaut-projects / micronaut-core

Micronaut Application Framework
http://micronaut.io
Apache License 2.0
6.07k stars 1.07k forks source link

Infinite loop when Exception is thrown while instanciating Singleton #1962

Closed avaldor-dw closed 5 years ago

avaldor-dw commented 5 years ago

Thanks for reporting an issue for Micronaut, please review the task list below before submitting the issue. Your issue report will be closed if the issue is incomplete and the below tasks not completed.

NOTE: If you are unsure about something and the issue is more of a question a better place to ask questions is on Stack Overflow (http://stackoverflow.com/tags/micronaut) or Gitter (https://gitter.im/micronautfw/). DO NOT use the issue tracker to ask questions.

Task List

Steps to Reproduce

  1. Create a simple web service app with micronaut
  2. Create a controler TestController including a singleton TestService 3 . Create resource /test calling singleton TestService
  3. Throw an exception when instanciating TestService(into it constructor)
  4. Deploy and run your micro service
  5. Call resource /test with your browser or postman

Expected Behaviour

We should get something like an HTTP code 500 or other response

Actual Behaviour

The request is hanged Looking at the log, micronaut is making an infinite loop to try to create the TestService instance

Environment Information

Example Application

jameskleeh commented 5 years ago

I can't reproduce this on Micronaut 1.1.4. Please upload an example application that reproduces the issue

avaldor-dw commented 5 years ago

Hello, I am going to try first with version 1.1.4 and let you know the result

avaldor-dw commented 5 years ago

Hello, I tried with version 1.1.4: I got the same issue. After investigating I found tha the issue came from a @Error(global=true) defined into my one of Controller. To got the Error I need to have the defect Service Singleton, decalred into 2 Controllers. Crazy... When I set global=false I don't have the issue. I noticed into the log that 'Path taken' was Path Taken: new $FileControllerDefinition$Intercepted([AssetService assetService],FileService fileService,MeterRegistry meterRegistry,FileImportPublisher fileImportPublisher,BeanContext beanContext,Interceptor[] interceptors) --> new AssetServiceImp([AssetDao assetDao]) --> new AssetDaoImpl([ArangoDB arangoDB],ArangoDBConfiguration arangoDBConfiguration)]: java.lang.Exception -> $FileControllerDefinition$Intercepted#HttpResponse basicError(HttpRequest request,Exception e) . basicError is the method @Error . I tried with another project, but the path is different so no problem. I am sorry I tried to make a little project for you to reproduce but I did not succeed. I hope I gave enough informations. Thanks to you.

jameskleeh commented 5 years ago

@avaldor-dw Unfortunately without an example I don't know where to look

avaldor-dw commented 5 years ago

Hello, please have a look there: https://github.com/avaldor-dw/micronaut_issue It is a project that reproduce the issue. You just need to run the Unit Test

jameskleeh commented 5 years ago

@avaldor-dw This is the expected behavior. The request comes in and fails to instantiate the controller because of the exception thrown in ArangoDBFactory. That exception is then handled by your global exception handler which is handling ALL exceptions. In order to execute that method, the class where it resides must be instantiated. That class also requires the ArangoDBFactory and thus the exception is thrown again and we're in the loop.

You can resolve this issue by moving the global error route to a class that does not have the dependency, or registering an ExceptionHandler bean.