codeconsole opened a new pull request, #15934:
URL: https://github.com/apache/grails-core/pull/15934
### Summary
Supersedes #15755, implementing the design agreed in its review discussion:
instead of adding a new lifecycle method, the **existing** plugin entry point
is retimed. Completes the follow-up scoped out of #15409 ("we could move
plugins completely to the autoconfiguration workflow") and delivers the visible
half of #14915.
- **`doWithSpring`/`doWithRuntimeConfiguration` now runs before Spring Boot
auto-configuration.** An `ApplicationContextInitializer` adds a
manually-registered `BeanDefinitionRegistryPostProcessor`, which Spring runs
ahead of `ConfigurationClassPostProcessor`. Plugin beans are in the registry
before auto-configuration conditions are evaluated, so Boot's
`@ConditionalOnMissingBean` beans defer to plugin beans — no more overriding
Boot beans after the fact.
- **The plugin manager and `GrailsApplication` are built exactly once**, in
the early phase, from `PluginDiscovery` (the 7.x bootstrap infrastructure),
then promoted as singletons that `GrailsApplicationPostProcessor` reuses. No
throwaway instances, no double plugin instantiation.
- **Artefact discovery moves into the same early phase** (resolving
application classes via the same `classes()` path as before, honoring the
compile-time `packageNames()` injection), so `doWithSpring` closures that
iterate artefacts — controllers, services, interceptors — work unmodified.
- **`BeanRegistrar` is the new native registration API for plugins**:
`beanRegistrar()` on `GrailsApplicationLifeCycle`/`Plugin`, applied pre-refresh
through Spring's own `BeanRegistryAdapter` (the mechanism
`GenericApplicationContext.register(BeanRegistrar...)` uses). AOT-friendly by
design.
- **The bean DSL entry point is deprecated** (`@Deprecated(since = '8.0')`
on `doWithSpring`) pointing at `beanRegistrar()`. Deprecated DSL closures keep
draining through the existing `RuntimeSpringConfiguration` path — just earlier
— until removal. The DSL internals are deliberately *not* reimplemented on
`BeanRegistry`: the DSL supports constructs with no clean equivalent
(parent/abstract beans, late-resolved references, `BeanConfiguration`
post-processing), the plumbing is invisible to users, and that translation work
would be deleted at DSL removal anyway.
`resources.groovy`/`resources.xml` and the application class's own
`doWithSpring` drain where they always did, so application beans still override
plugin beans under the default `allow-bean-definition-overriding=true`. The one
behavioral edge — apps explicitly setting it `false` now get
`BeanDefinitionOverrideException` where the old single-drain merge was silent —
is documented in the upgrade notes.
### Regressions found and fixed by verification
The retiming sweep caught two real breakages, both fixed generally in this
PR:
1. **OSIV silently disabled** (differential-tested: passes on 8.0.x, failed
on the branch before the fix): the Hibernate/Mongo datastore initializers
detected "web application" via `containsBeanDefinition('dispatcherServlet')` —
an auto-configuration bean, always absent at the early drain.
`AbstractDatastoreInitializer.isWebApplicationRegistry()` now also does a
registration-order-independent `WebApplicationContext` type check. Follow-up:
`Neo4jDataStoreSpringInitializer` needs the identical one-line change in its
own build (separate PR).
2. **Controllers in sibling packages lost their beans**: early artefact
discovery initially scanned only the Application class's package, missing the
injected `packageNames()` override. Fixed by resolving application classes
through `classes()` for exact parity with the previous behavior.
### Verification
All green, zero failures: grails-core (433), grails-test-suite-uber (556),
grails-test-suite-web (339), grails-gsp (489), grails-controllers,
grails-web-boot, sitemesh3 (63), mongodb-core (612, testcontainers), hibernate7
(18), hibernate5 (10), plus full hibernate7 `app1:integrationTest` (689) and
`app1:integrationTest` (691). New coverage: ordering specs proving a plugin
`doWithSpring` bean and a plugin `beanRegistrar()` bean each win a
`@ConditionalOnMissingBean` race (with a no-early-phase control),
app-over-plugin override under default settings, and an end-to-end app3
integration test in a real booted application. Neo4j's suite could not run here
(independent Gradle build resolving from Maven); noted as the follow-up above.
Docs: new upgrade-notes section covering the retiming, the override edge,
and the DSL deprecation; the plugin guide's runtime-configuration page now
documents `beanRegistrar()` first with `doWithSpring` as the
deprecated-but-working alternative.
Related: #15755 (superseded), #15409 / #15408 (7.x groundwork), #14915 (bean
DSL deprecation ticket), #13863 / #15916 (independent extractions from #15755).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]