loopbackio / loopbackio/loopback-next

@service(GeocoderProvider) Fails with "No Binding Found" in LoopBack Component

Open
#11,062 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
5.1k
Forks
1.1k
Avg merge
2d 21h
Merged PRs (30d)
27

Description

### Describe the bug

**Problem Description**
@service(GeocoderProvider) Fails with "No Binding Found" in LoopBack Component after overriding the same class via Service booter in application.

❓ **Problem Statement**
You created a custom LoopBack Component named DummyComponent, which declares and registers models, repositories, controllers, and a service (GeocoderProvider):

```ts
export class DummyComponent implements Component {
...
services?: ServiceOrProviderClass[];
...
constructor(
@inject(CoreBindings.APPLICATION_INSTANCE)
private application: Application,
) {
this.services = [GeocoderProvider]; // <-- Intended to register the service
}
}
```

and used in a controller as
```ts
export class TodoController {
constructor(
@repository(TodoRepository)
public todoRepository: TodoRepository,

@service(GeocoderProvider) // <-- This fails
protected geoService: Geocoder,
) {}
}
```
i added DummyComponent in application.ts as
```ts
this.component(DummyComponent);
```

this works fine. but when i override the GeocoderProvider via Service Booter.
this gives me error
```
500 Error: No binding found for GeocoderProvider.
Make sure a service binding is created in context RequestContext-xxxx with serviceInterface (GeocoderProvider).
```
***Steps to reproduce:***
- clone repo https://github.com/Tyagi-Sunny/loopback-next/tree/master
- do npm i
- move to branch ***bug-no-binding-found***
- move to todo example in examples dir - cd examples/todo/
- run npm start
- go to http://localhost:3000
- hit GET /todo

Reason for this error->
@service decorator filters the binding based on a functions
```ts
export function filterByServiceInterface(
serviceInterface: ServiceInterface,
): BindingFilter {
return binding =>
binding.valueConstructor === serviceInterface ||
binding.tagMap[CoreTags.SERVICE_INTERFACE] === serviceInterface;
}
```

and if we explicitly does not provide interface then it uses class itself as interface and used it for comparison. and we end up with two different services that causes comparison to fail and returning no binding found.
As we don't have any options to provide this interface(serviceOptions) via service booter. either we need to Manually bind services after the boot process (defeating the purpose of convention-based discovery)

***Solution:***
I have created a decorator @serviceOptions decorator that allows you to annotate service classes with configuration options metadata. It uses the factory pattern to create decorators with a specific options metadata key.
Then createServiceBinding function is the core registration mechanism that:
- Extracts metadata: Retrieves decorator-defined options from the class
- Merges configurations: Combines decorator metadata with manually passed options (manual options take precedence)
- and rest will be same

### Logs

```shell

```

### Additional information

_No response_

### Reproduction

https://github.com/Tyagi-Sunny/loopback-next/tree/bug-no-binding-found

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in the todo example's application.ts and trace the Service Booter registration into @service and filterByServiceInterface. Read the createServiceBinding path and the proposed @serviceOptions metadata behavior, then reproduce the failure with the bug-no-binding-found branch and GET /todo. Done means the overridden GeocoderProvider resolves through @service without a No binding found error.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.