Brad Bird
Brad Bird

Reputation: 737

Nest can't resolve dependencies of the BlahService although it is Global()

I have an issue with NestJS and it appears to be for just 1 module and all the others work fine. I have the following modules.

The error is:

[ExceptionHandler] Nest can't resolve dependencies of the ApplicationService (ApplicationModel, AwsService, UserService, ?, JobService). Please make sure that the argument at index [3] is available in the ApplicationModule context.

The AgencyService is [3]. If I remove the AgencyModule from the ApplicationModule NestJS successfully compiles and I can make API calls.

AgencyModule,
ApplicationModule,
AuthModule,
JobModule,
UserModule,

All these modules are required by other modules for their service providers so rather than import them between each other using forwardRef() I just made them Global() - May not be best practice but hey ho (it works).

My AppModule file.

@Module({
  imports: [
    MongooseModule.forRootAsync({
      useFactory: (configService: ConfigService) => ({
        uri: configService.get('MONGO_DB_URL'),
        useNewUrlParser: true,
      }),
      imports: [ConfigModule],
      inject: [ConfigService],
    }),
    ConfigModule,
    AgencyModule,
    ApplicationModule,
    AuthModule,
    DevModule,
    JobModule,
    UserModule,
    VideoModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Each module folder has the following structure.

agency/
- dto/
- agency.controller.ts
- agency.interface.ts
- agency.schema.ts
- agency.service.ts
- agency.module.ts

My AgencyModule file.

@Global()
@Module({
  imports: [
    SharedModule,
    MongooseModule.forFeature([{ name: 'Agency', schema: AgencySchema }]),
  ],
  controllers: [
    AgencyController,
  ],
  providers: [
    AgencyService,
    AwsService,
  ],
  exports: [
    AgencyService,
  ],
})
export class AgencyModule implements NestModule {
  public configure(consumer: MiddlewareConsumer) {
    consumer
      .apply()
      .forRoutes(
        { path: 'agency', method: RequestMethod.GET },
      );
  }
}

My AgencyService file.

@Injectable()
export class AgencyService {
  constructor(
    @InjectModel('Agency') private readonly agencyModel: Model<Agency>,
    private readonly awsService: AwsService,
    private readonly applicationService: ApplicationService,
  ) {
    //
  }

  // More stuff here but not worth adding to the snippet.

}

My ApplicationModule file.

@Global()
@Module({
  imports: [
    SharedModule,
    MongooseModule.forFeature([{ name: 'Application', schema: ApplicationSchema }]),
  ],
  controllers: [
    ApplicationController,
  ],
  providers: [
    ApplicationService,
    AwsService,
  ],
  exports: [
    ApplicationService,
  ],
})
export class ApplicationModule implements NestModule {
  public configure(consumer: MiddlewareConsumer) {
    consumer
      .apply()
      .forRoutes(
        { path: 'application', method: RequestMethod.GET },
      );
  }
}

My ApplicationService file.

@Injectable()
export class ApplicationService {
  constructor(
    @InjectModel('Application') private readonly applicationModel: Model<Application>,
    private readonly awsService: AwsService,
    private readonly userService: UserService,
    private readonly agencyService: AgencyService,
    private readonly jobService: JobService,
  ) {
    //
  }

  // More stuff here but not worth adding to the snippet.

}

The AwsService is a shared service without a module.

Upvotes: 2

Views: 2060

Answers (1)

Kim Kern
Kim Kern

Reputation: 60347

Using @Global() does not automatically resolve circular dependencies, you still have to use @Inject(forwardRef(() => MyService)) on both sides, see the docs.


As you noted yourself, circular dependencies (forwardRef) and global modules (@Global) are bad style and should be avoided. Rather make your dependencies explicit. If you encounter a circular dependency extract the commonly used parts in a shared service/module that is imported by both sides, see this thread.

Upvotes: 2

Related Questions