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]

Reply via email to