-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
Description
Whether a persistence unit (PU) will actually exist is not a trivial question.
It will depend on whether both Hibernate ORM and Hibernate Reactive are in the classpath.
It will depend on configuration (is that PU referenced in application.properties), but not always (the default PU might be created even without any configuration).
It will depend on the nature (blocking or reactive) of the PU's datasource (see #51159), but not always (some multitenancy setups don't involve a build-time datasource).
We've been trying to throw exceptions during the build when a PU cannot be created, because just not creating it would leave users with a rather confusing exception about the relevant CDI beans (e.g. Session) simply not being there.
But in some setups that's actually counter-productive because the PU is not used anyway (see #51159).
Relatedly, we've had some conversation with @radcortez (#51105) regarding how other extensions derive the need for a client from the mere existence in the application of an injection point involving that client.
Let's try to improve the situation:
- Better discover whether an app requires a given persistence unit -- not just from configuration
- Better detect cases when a non-existing PU is actually used, still providing a clear, actionable error message.
Implementation ideas
Taking the above into account, I'd like to suggest the following:
- We formalize the concept of "persistence unit X is requested in the app", sourcing the information from:
a. Configuration: if a PU is explicitly configured, it's requested. We may not know if it's requested in blocking or reactive form, however.
b. CDI injection point: any injection point whose component is provided by the Hibernate ORM/Reactive extensions should be considered a request for the corresponding PU:SessionFactory,Session,Mutiny.SessionFactory,Mutiny.Session, and many more. In some cases we may know if it's requested in blocking or reactive form, but not all of them (e.g.Metamodelcould make sense for blocking as well as reactive).
c. Panache: the presence of a Panache entity assigned to a given PU is considered a request for the corresponding PU. In that case we know if it's requested as reactive or blocking -- at least in Panache 1. - We take that information into account at build time to come up with a list of PUs we will try to add to the app.
- When we cannot add a PU to the app (e.g. because the PU's datasource is unconfigured), we will consult the list of PU requests, and act one of two ways depending on that:
a. If the PU is for sure requested in the form we're currently handling (blocking or reactive), we will fail at build time as we do today.
b. Otherwise (this implies the PU is not injected nor used in Panache), we will create "fake" CDI beans for the PU, which are always inactive, so that any dynamic use at runtime will trigger an exception clearly explaining why the PU is not around.
I think this strikes a reasonable balance between convenience for users and complexity for us. Though I can't say this is a very-high priority task, of course :)
Thoughts, opinions?