Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider introducing @Eager or similar annotation for bean eager init #835

Open
manovotn opened this issue Jan 20, 2025 · 8 comments
Open
Labels
enhancement New feature or request
Milestone

Comments

@manovotn
Copy link
Contributor

manovotn commented Jan 20, 2025

This has been discussed and requested repeatedly (last I know of was here).
Note that this is not a new feature as the same can be achieved via declaration of Startup event observer in any given bean.
However, that is often perceived as a workaround instead of a solution and is admittedly longer than using an annotation.

The idea would be to introduce an annotation such as @Eager/@Startup (name is subject to change), declarable at bean class level, which would make CDI initialize the bean on container startup.

Some thoughts:

  • This makes most sense for @ApplicationScoped (or @Singleton) beans but can technically work for all scopes
    • Should we forbid it for some scopes? Doesn't seem to make much sense for dependent beans for instance.
    • What about contexts that aren't active at startup? We should probably align this with how a startup event observer would behave.
  • Nothing in CDI specification requires impl to behave lazily (not create a bean until its method is invoked) yet this features indirectly assumes it as it would otherwise have no effect. This doesn't prevent us from adding it; just saying :)

FTR, some discussion about implementation took place in the aforementioned issue (here). It boils down to:

  • Gathering information about eager-init beans during discovery
  • Resolving them after container starts (along the lines of Instance#get())
    • Beans without client proxies will be created as soon as they are resolved.
    • Bean with client proxies will need to be "forcefully" initialized.
      • Dumb version is invoking their toString() which would work in 99% cases.
      • Otherwise needs to manually invoke their creation cycle for which some impls already have code anyway (here's Weld bit)
@manovotn manovotn added the enhancement New feature or request label Jan 20, 2025
@manovotn manovotn added this to the CDI 5.0 milestone Jan 20, 2025
@Ladicek
Copy link
Contributor

Ladicek commented Jan 20, 2025

Agree this doesn't make much sense for other scopes than @Signleton and @ApplicationScoped. For @Dependent, the solution is simple, just create an instance and immediately destroy it; for other scopes, such as @RequestScoped, it's more problematic. I'd say it's probably best to make it a deployment problem if non-singleton beans are @Eager.

Another question: should this be limited to class-based beans? I guess producers and synthetic beans could benefit from this as well.

@Azquelt
Copy link
Member

Azquelt commented Jan 20, 2025

It would seem odd if we used "eager" to mean "created at startup", rather than "created eagerly". I would expect an "eager" @RequestScoped bean, to be created at the start of every request.

IIRC though, there's no requirement for scopes to have a defined beginning?

@Azquelt
Copy link
Member

Azquelt commented Jan 20, 2025

My other thought is that, if eager initialization is only going to be used to run something at startup, then observing Startup to run something at startup is far more logical.

The only problem is when this startup logic is also some kind of initialization for your bean. Having it in @PostConstruct guarantees (almost?) that it runs before any other methods on your bean are called, whereas having it in a Startup observer method doesn't. Then you end up putting your initialization logic in a @PostConstruct method and having an empty Startup observer method, which is ugly.

@manovotn
Copy link
Contributor Author

For @dependent, the solution is simple, just create an instance and immediately destroy it

Sure, but if we are talking an annotation, it doesn't make much sense as you won't execute anything and it will get destroyed immediately?
If you want some logic executed and it is a dependent bean, the observer seem like much better fit.

Another question: should this be limited to class-based beans? I guess producers and synthetic beans could benefit from this as well.

Hm, I assume the idea there is to pre-create beans that are time consuming to create on demand?
However, in such case we are no longer just making it just more convenient than the OM you can currently use as this adds functionality that you cannot otherwise have.

It would seem odd if we used "eager" to mean "created at startup", rather than "created eagerly". I would expect an "eager" @RequestScoped bean, to be created at the start of every request.

Yes, I thought about that as well but personally I find creating beans on scope/context start very awkward.

IIRC though, there's no requirement for scopes to have a defined beginning?

They are basically defined by firing an initialized event which you can observe. Can't think of anything else.

@manovotn
Copy link
Contributor Author

My other thought is that, if eager initialization is only going to be used to run something at startup, then observing Startup to run something at startup is far more logical.

The only problem is when this startup logic is also some kind of initialization for your bean. Having it in @PostConstruct guarantees (almost?) that it runs before any other methods on your bean are called, whereas having it in a Startup observer method doesn't. Then you end up putting your initialization logic in a @PostConstruct method and having an empty Startup observer method, which is ugly.

I basically agree. Yet I keep hearing about @Startup from ejb and omnifaces.
I suppose the other use case is not having application logic executed but just initializing your bean that's time consuming to create right from the get go? Although I am not sure what would have to be inside that bean to make it that costly...

Either way, I am not sold on this annotation either, I just want to create a tracking issue and see if there is any interest in it 🤷

@m-reza-rahman
Copy link

Very much in support of this. I come across this repeatedly. People always miss the event observer. A simple annotation would greatly reduce ongoing confusion.

@tandraschko
Copy link

+1 for @Eager as shortcut to @Overserves @Initialized(SomeScope) Object event

@kiswanij
Copy link

I didn't follow up with the spec since while, but if its not there ( specially in the App scope and Singleton, as mentioned in one of the comments) it should be; in many designs we desire to fail early in case of mis-configuration or initialization problems than in th middle of a process that has customers engagement. There is alot to learn from the Servlets specs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

6 participants