Register dependencies in the correct order so a service can inject them.

← Dependency Injection · Ref: Q1111

Register dependencies before the components that inject them:

  register ConsoleLogger() as Logger
  register UpperFormatter() as Formatter
  register SimpleService() as Service

The compiler validates ordering: Logger must be registered before any component that injects Logger!.

See Q228 for ordering rules. See Q229 for circular dependency detection.

Example

defines module qa.di.injectorder

  defines component

    Logger as abstract
      log() as abstract
        -> message as String
        <- output as String?
      default operator ?

    ConsoleLogger is Logger
      override log()
        -> message as String
        <- output as String: `LOG: ${message}`
      default operator ?

    Formatter as abstract
      format() as abstract
        -> text as String
        <- result as String?
      default operator ?

    UpperFormatter is Formatter
      override format()
        -> text as String
        <- result as String: text.upperCase()
      default operator ?

    Service as abstract
      process() as abstract
        -> input as String
        <- output as String?
      default operator ?

    SimpleService is Service
      logger as Logger!
      formatter as Formatter!

      override process()
        -> input as String
        <- output <- String()
        formatted <- formatter.format(input)
        output: logger.log(formatted)

      default operator ?

  defines application

    OrderedApp
      //Dependencies first, dependents after
      register ConsoleLogger() as Logger
      register UpperFormatter() as Formatter
      register SimpleService() as Service

  defines program

    InjectOrderingDemo() with application of OrderedApp
      stdout <- Stdout()
      service as Service!
      result <- service.process("hello world")
      stdout.println(result)

Common mistakes

E08200 — Dependencies must be registered BEFORE the components that inject them; registering SimpleService (which injects Logger and Formatter) before them triggers E08200. See ek9 -h E08200 for details.

Incorrect:

      register SimpleService() as Service
      register ConsoleLogger() as Logger
      register UpperFormatter() as Formatter

Correct:

      register ConsoleLogger() as Logger
      register UpperFormatter() as Formatter
      register SimpleService() as Service
Other ways to ask this
  • I need to ensure my Logger is registered before the MessageService that depends on it
  • In Spring ordering is automatic. Show the EK9 explicit registration ordering
  • Given three components with dependencies, register them in dependency order
  • Wire components so that dependencies are available before dependents are created

Coming from another language?

Spring: automatic ordering via @DependsOn or constructor analysis. Guice: Module.configure() ordering matters. EK9: explicit top-to-bottom ordering validated at compile time.

Keywords: register, compile-time, ordering, before, DI, dependency