Skip to content

Clarify specification in ABD#addBean #872

@manovotn

Description

@manovotn

The original issue and discussion can be found under weld/core#3191.

The disputed specification text is the following section for AfterBeanDiscovery (mind the emphasis made in the quote):

addBean() fires an event of type ProcessSyntheticBean containing the given Bean *and then* registers the Bean with the container, thereby making it available for injection into other beans. The given Bean may implement Interceptor or Decorator.

This wording makes a difference in case two or more extensions (or rather observers) are attempting to both, monitor the ProcessSyntheticBean event and conditionally register synthetic bean. I.e. should the ProcessSyntheticBean be fired in between notifications of other AfterBeanDiscovery observers or should all the ABD observers be fired first, and then fire ProcessSyntheticBean events?

Weld chooses to notify all of the ABD observers before firing ProcessSyntheticBean events. Below is the case I presented in the linked issue.

Imagine the following situation, should you be allowed to intertwine various lifecycle observer notifications:

  • Two CDI extensions, let's call them ExtensionA a ExtensionB
    • They have no ordering of events nor do they know about each other (which is pretty common and perfectly fine in bigger apps)
  • ExtensionA always unconditionally registers a bean with type Foo (and no qualifiers) as a synthetic bean during ABD event
  • ExtensionB monitors ProcessSyntheticBean<Foo>, make note of its presence/absence and then in ABD attempt to add a synthetic bean Foo if it was missing

Now, since CDI imposes exactly no rules on ordering of extensions, two situations can occur.

First one:

  1. ExtensionA is notified first and registers synth bean Foo
  2. ExtensionB gets the ProcessSyntheticBean event delivered, makes note of it and in its own execution skip the registration of the bean
  3. Your app runs fine

Second one:

  1. ExtensionB is notified first; as there is no Foo bean yet, it registers it
  2. ExtensionA then registers the bean as well
  3. You now have ambiguous dependency resolution

Cc @ljnelson and @Ladicek who participated in the discussion. Let's move it here and see what others think about it. We could/should also discuss it in the next CDI call.

As a side note - a very similar situation applies to registering a synthetic annotated type (which triggers PAT event).

Metadata

Metadata

Assignees

No one assigned

    Labels

    spec-clarificationAn issue requesting clarification in the specification

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions