loopbackio / loopback-next

LoopBack makes it easy to build modern API applications that require complex integrations.
https://loopback.io
Other
4.93k stars 1.06k forks source link

[BUG]: @inject() + asProxyWithInterceptors make repository function not work! #8475

Open Embraceeeee opened 2 years ago

Embraceeeee commented 2 years ago

Describe the bug

What is the problem

When I use the global interceptor: @inject('repositorys.xxxRepository', {asProxyWithInterceptors: true}) will be successfully intercepted. But many functions of repository variable not work!

export class TodoController {
  constructor(
    @inject('repositorys.TodoRepository', {asProxyWithInterceptors: true})
    public todoRepository: TodoRepository,
  ) { }
  @get('/todos')
    @response(200, {
      description: 'Array of Todo model instances',
      content: {
        'application/json': {
          schema: {
            type: 'array',
            items: getModelSchemaRef(Todo, {includeRelations: true}),
          },
        },
      },
    })
    async find(
      @param.filter(Todo) filter?: Filter<Todo>,
    ): Promise<Todo[]> {
      return this.todoRepository.find(filter);
    }
}

HTTP Status Code 500 Error:

Server is running at http://[::1]:3000
Try http://[::1]:3000/ping
TodoRepository#find() interceptor success!
Request GET /todos?filter=%7B%0A%20%0A%7D failed with status code 500. ResolutionError: The argument 'TodoRepository.prototype.find[1]' is not decorated 
for dependency injection but no value was supplied by the caller. Did you forget to apply @inject() to the argument? (context: InterceptedInvocationContext-n626DiRrTbSKOXsrJCAr-w-38)
    at D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\resolver.ts:233:15
    at resolveList (D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\value-promise.ts:169:28)
    at resolveInjectedArguments (D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\resolver.ts:220:21)
    at invokeTargetMethodWithInjection (D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\invocation.ts:223:49)
    at InterceptedInvocationContext.invokeTargetMethod (D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\invocation.ts:119:14)
    at targetMethodInvoker (D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\interceptor.ts:349:23)
    at D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\interceptor-chain.ts:219:14
    at transformValueOrPromise (D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\value-promise.ts:298:12)
    at GenericInterceptorChain.invokeNextInterceptor (D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\interceptor-chain.ts:214:35)
    at GenericInterceptorChain.next (D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\interceptor-chain.ts:202:17)      
    at D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\interceptor-chain.ts:219:42
    at TestInterceptor.intercept (D:\githubFile\loopback4-repository-proxy-issue\src\interceptors\test.interceptor.ts:55:28)
    at D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\interceptor-chain.ts:219:14
    at transformValueOrPromise (D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\value-promise.ts:298:12)
    at GenericInterceptorChain.invokeNextInterceptor (D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\interceptor-chain.ts:214:35)
    at GenericInterceptorChain.next (D:\githubFile\loopback4-repository-proxy-issue\node_modules\@loopback\context\src\interceptor-chain.ts:202:17)   

Expected behavior

The interceptor takes effect and the repository variable function work.

Actual behavior

It throws the above exception.

How to reproduce the problem

  1. git clone https://github.com/Embraceeeee/loopback4-repository-proxy-issue
  2. npm install
  3. npm start
  4. visit url http://[::1]:3000/explorer/#/TodoController
  5. view output

Logs

No response

Additional information

No response

Reproduction

https://github.com/Embraceeeee/loopback4-repository-proxy-issue

achrinza commented 2 years ago

Duplicate of https://github.com/loopbackio/loopback-next/discussions/8363

Embraceeeee commented 2 years ago

@achrinza Thank you for your reply. I could be wrong, but I think the issue is different from #8368 , because repository function will throw exception when i add {asProxyWithInterceptors: true} .

export class TodoController {
  constructor(
    @inject('repositorys.TodoRepository', {asProxyWithInterceptors: true})
    public todoFailRepository: TodoRepository,

    @inject('repositorys.TodoRepository')
    public todoSucessRepository: TodoRepository,
  ) { }

  // http status code:500  fail!!!
  @get('/todos-fail')
  async findFail(
    @param.filter(Todo) filter?: Filter<Todo>,
  ): Promise<Todo[]> {
    return this.todoFailRepository.find(filter);
  }

  // http status code:200 sucess!!!
  @get('/todos-sucess')
  async findSucess(
    @param.filter(Todo) filter?: Filter<Todo>,
  ): Promise<Todo[]> {
    return this.todoSucessRepository.find(filter);
  }
}

For more detail code, i've appended reproduction: https://github.com/Embraceeeee/loopback4-repository-proxy-issue

achrinza commented 2 years ago

Hi @Embraceeeee, thanks for the reply and the the reproduction sandbox. I'll take a look at it. Ideally, both issues should be solvable through a single fix.

raymondfeng commented 2 years ago

@Embraceeeee Can you try the following?

@get('/todos-fail')
  async findFail(
    @param.filter(Todo) filter?: Filter<Todo>,
  ): Promise<Todo[]> {
    return this.todoFailRepository.find(filter, undefined);
  }
Embraceeeee commented 2 years ago

HI, @raymondfeng thanks for your reply. I tried it and found the program run correctly. Do I have to add this undefined parameter?