From discussion on #1571
I have a model called Category with a parentId field that points to the parent Category
Category Model:
export class Category extends Entity {
@property({
type: 'number',
id: true,
generated: true
})
id?: number;
@belongsTo(() => Category)
parentId: number;
@belongsTo(() => Domain)
containerId: number;
@property({
type: 'boolean',
default: false,
})
internal?: boolean;
@property({
type: 'string',
required: true,
})
title: string;
@property({
type: 'string',
})
description?: string;
@property({
type: 'string',
})
state?: string;
constructor(data?: Partial<Category>) {
super(data);
}
}
I created a /categories/{id}/parent endpoint per the docs
When I call that endpoint I get this error:
Unhandled error in GET /categories/2/parent: 500 Error: Circular dependency detected: controllers.CategoryParentController --> @CategoryParentController.constructor[0] --> repositories.CategoryRepository --> @CategoryRepository.constructor[2] --> repositories.CategoryRepository
Category Parent Controller:
export class CategoryParentController {
constructor(@repository(CategoryRepository) protected categoryRepository: CategoryRepository) { }
@get('/categories/{id}/parent')
async getCustomer(
@param.path.number('id') id: number,
): Promise<Category> {
return await this.categoryRepository.parent(id);
}
}
Category Repository
export class CategoryRepository extends DefaultCrudRepository<
Category,
typeof Category.prototype.id
> {
public readonly container: BelongsToAccessor<Domain, number>;
public readonly parent: BelongsToAccessor<Category, number>;
constructor(
@inject('datasources.db') dataSource: DbDataSource,
@repository.getter(DomainRepository)
protected domainRepositoryGetter: Getter<DomainRepository>,
@repository.getter(CategoryRepository)
protected categoryRepositoryGetter: Getter<CategoryRepository>
) {
super(Category, dataSource);
this.container = this._createBelongsToAccessorFor('container', domainRepositoryGetter);
this.parent = this._createBelongsToAccessorFor('parent', categoryRepositoryGetter);
}
}
Note that the container part works as expected, only parent is broken.
In your CategoryRepository, you are injecting a getter for obtaining the same repository again.
Since your relation is referring back to the same model, you can reuse the same repository.
Could you please check if the following code fixes to problem for you?
export class CategoryRepository extends DefaultCrudRepository<
Category,
typeof Category.prototype.id
> {
public readonly container: BelongsToAccessor<Domain, number>;
public readonly parent: BelongsToAccessor<Category, number>;
constructor(
@inject('datasources.db') dataSource: DbDataSource,
@repository.getter(DomainRepository)
protected domainRepositoryGetter: Getter<DomainRepository>,
) {
super(Category, dataSource);
this.container = this._createBelongsToAccessorFor('container', domainRepositoryGetter);
this.parent = this._createBelongsToAccessorFor('parent', Getter.fromValue(this));
}
}
I think you won't be the last person encountering this issue, let's describe the problem & the solution in our docs, e.g. hasMany relation and belongsTo relation. (Feel free to propose other places where you would be looking for this information.)
Would you @hvlawren like to contribute this documentation change yourself?
That fixed it!
I'd say those two places probably make the most sense.
I've got a lot on my plate right now, so I'd suggest someone else add the docs.
That fixed it!
Great! 馃帀
I'd say those two places probably make the most sense.
I've got a lot on my plate right now, so I'd suggest someone else add the docs.
We all have a lot on our plates, don't we? 馃槈
It would be great if you could find some time later to contribute back, but I will understand if you don't.
Let's keep this issue open, I think it's a good opportunity for new contributors.
Well, I am sniffing around for good first issues. Will take this up.
Hello.
I made a PR to update document for this issue: https://github.com/strongloop/loopback-next/pull/2196
Please help me check it.
I just realized that if the above CategoryRepository has a hasMany relation to DocumentRepository and DocumentRepository has a belongsTo relation to CategoryRepository then you get a circular dependency error.
What should be done in this case as the Getter.fromValue(this) isnt really usefull here?
@mmeilby: do you found a solution for the case
@mmeilby: do you found a solution for the case
Yes, the solution in May was to add this line before the repository class definition:
@bind({scope: BindingScope.SINGLETON})
export class SomeRepository extends DefaultTransactionalRepository ...
Most helpful comment
I just realized that if the above CategoryRepository has a hasMany relation to DocumentRepository and DocumentRepository has a belongsTo relation to CategoryRepository then you get a circular dependency error.
What should be done in this case as the Getter.fromValue(this) isnt really usefull here?