Keep BeanBuilder DSL independent of XML setup - #15824
Conversation
Avoid eager Spring XML reader setup when evaluating ordinary BeanBuilder DSLs so resources.groovy remains compatible with Spring Framework 7. Move XML reader and namespace support behind a lazy helper used only by XML import and xmlns paths. Add grails-spring regression coverage for plain DSL, XML import, and namespace support, and wire the module into the shared test configuration so those tests execute. Document the compatibility behavior in the Grails 8 upgrade and Spring DSL guides. Assisted-by: Hephaestus:openai/gpt-5.5 codex-review
There was a problem hiding this comment.
Pull request overview
This PR refactors grails.spring.BeanBuilder to keep the standard resources.groovy DSL path independent of Spring XML reader/context initialization, while preserving compatibility for XML-based imports (importBeans with XML resources) and Spring XML namespace DSL usage via xmlns. It also adds regression tests and documents the Grails 8 compatibility behavior in the guide and upgrade notes.
Changes:
- Introduced lazy, encapsulated XML/namespace support (
BeanBuilderXmlSupport) so XML infrastructure is only initialized when needed. - Updated
BeanBuilderto delegate XML import and namespace parsing to the new support class. - Added
grails-springregression tests and updated documentation to clarify Grails 8 behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| grails-spring/src/test/groovy/grails/spring/BeanBuilderTests.groovy | Adds regressions covering plain DSL (no XML init), XML import, and xmlns namespace usage. |
| grails-spring/src/main/groovy/grails/spring/BeanBuilderXmlSupport.java | New helper to lazily manage Spring XML reader/context and namespace handler resolution. |
| grails-spring/src/main/groovy/grails/spring/BeanBuilder.java | Removes eager XML initialization and routes XML-related behavior through BeanBuilderXmlSupport. |
| grails-spring/build.gradle | Applies shared test-config.gradle for module test setup. |
| grails-doc/src/en/guide/upgrading/upgrading80x.adoc | Documents Grails 8 BeanBuilder/XML compatibility and recommended path. |
| grails-doc/src/en/guide/spring/theBeanBuilderDSLExplained.adoc | Clarifies that XML namespace support is compatibility-focused and initialized on-demand. |
| grails-doc/src/en/guide/spring/springdslAdditional.adoc | Notes continued resources.xml support and encourages resources.groovy for new definitions. |
| grails-doc/src/en/guide/introduction/whatsNew.adoc | Highlights the Grails 8 BeanBuilder behavior change at a high level. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
The suggested change is correct and aligns with the goal of avoiding unnecessary initialization of Spring XML infrastructure in the error path. By using This change effectively prevents the potential masking of the "No namespace handler found" error and improves performance in the exception path. grails-spring/src/main/groovy/grails/spring/BeanBuilder.java |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## 8.0.x #15824 +/- ##
================================================
+ Coverage 0 51.1390% +51.1390%
- Complexity 0 17615 +17615
================================================
Files 0 2042 +2042
Lines 0 95520 +95520
Branches 0 16587 +16587
================================================
+ Hits 0 48848 +48848
- Misses 0 39383 +39383
- Partials 0 7289 +7289
🚀 New features to boost your workflow:
|
Use the existing BeanBuilder resource when reporting missing XML namespace handlers so the error path does not create a reader context. Add coverage that fails if the XML reader path initializes while building the missing namespace error. Assisted-by: opencode:gpt-5.5 codex-review
|
FYI: spring started enforcing certain configuration like AMPQ / rabbit to be associated to an application context. Why are we maintaining the link to the bean builder dsl that Spring has stated will no longer be supported? Can't we adjust the beanDsl to use a BeanRegistrar instead which is the programmatic way Spring suggests using now? |
Assisted-by: opencode:gpt-5.5
- Rename the new SPI to GrailsBeanRegistryAdapter (impl BeanBuilderGrailsBeanRegistryAdapter) to avoid colliding with Spring's org.springframework.beans.factory.support.BeanRegistryAdapter - Validate the BeanBuilder constructor argument with Assert.notNull - Align @SInCE and the guide wording to 8.0.x and soften the #15824 reference - Add the ASF license header to the new upgrading guide page Assisted-by: Sisyphus:openai/gpt-5.6-terra [gpt-coding]
Review feedback addressedMerged the latest Copilot review comment (unknown-namespace error path initializing XML reader/context): already satisfied on this branch. The Follow-up (documented, not changed here): the lazy XML refactor means Local verification: |
Assisted-by: opencode:gpt-5.6-sol
How this relates to #16019These two PRs are complementary, not alternatives. This PR (#15824) keeps the existing BeanBuilder path working cleanly on Spring 7. It moves Spring XML reader / namespace / parser setup behind a lazy helper so ordinary #16019 is the forward registration model. It adds
Recommendation: land this PR for Spring 7 BeanBuilder compatibility; continue #16019 as the longer-term way to declare beans. Merging #16019 does not make this PR unnecessary while BeanBuilder / |
✅ All tests passed ✅🏷️ Commit: c47fb1e Learn more about TestLens at testlens.app. |
Fixes #14915
Why this is needed
Grails 8 is moving onto Spring Framework 7, but existing applications still need their
grails-app/conf/spring/resources.groovyBeanBuilder DSL files to keep working without application-side changes.The problem with the previous implementation was that
BeanBuildereagerly initialized Spring XML reader/context infrastructure even for ordinary programmaticresources.groovybean definitions. That made the standard DSL path more tightly coupled to Spring XML internals than it needs to be.This PR keeps the public BeanBuilder DSL behavior backward compatible while avoiding that eager XML setup for the common
resources.groovypath.What changed
XmlReaderContext, and parser context setup into a lazyBeanBuilderXmlSupporthelper.BeanDefinitionpath.importBeanswith.xmlresources still loads XML bean definitions.xmlnsstill resolves Spring XML namespace handlers on demand.DynamicElementReaderstill receives the parser context it needs for namespace DSL usage.grails-springso module-local JUnit Platform tests are actually discovered and run.importBeansstill registers XML bean definitions.xmlnsnamespace support still works through the BeanBuilder DSL.resources.groovyfor new custom bean definitions.Compatibility behavior
No application changes are required for existing
resources.groovyBeanBuilder DSL files.Existing
resources.xml, XML imports, and Spring XML namespace DSL usage remain supported as compatibility paths. They now initialize XML support only when those XML features are actually used.Review feedback addressed
getXmlSupport().getReaderContext(...)(which would lazily initialize the XML reader/context just to build an errorLocation). This is already satisfied on the branch: the"No namespace handler found"error builds itsLocationdirectly from the already-availablebeanBuildResource, so it never forces XML reader/context initialization on the exception path, andtestUnknownNamespaceDoesNotInitializeXmlReaderForErrorLocationlocks that in. Merged the latest8.0.x.setClassLoaderno longer dispatches to the protectedinitializeBeanBuilderForClassLoaderhook. No in-repo subclass overrides it, so this only affects hypothetical external subclasses; noted for a possible follow-up to preserve the hook dispatch.Verification
Passed from the visible checkout on
fix/14915-beanbuilder-spring7:JAVA_HOME=/home/james/.jdks/corretto-21 PATH=/home/james/.jdks/corretto-21/bin:$PATH ./gradlew :grails-spring:test --rerun-tasksJAVA_HOME=/home/james/.jdks/corretto-21 PATH=/home/james/.jdks/corretto-21/bin:$PATH ./gradlew :grails-spring:codeStylegrails-springruntime classpath:PASS plain BeanBuilder DSL did not initialize XML supportReview gate:
f1e6f82bdd5a4035a8230306b3d519b03ac1a61aas GREEN..omo/run-continuationsession metadata. That file was not staged or committed.Full-suite notes
./gradlew cleancompleted successfully../gradlew aggregateViolations --continuewas attempted, but the build is currently blocked by unrelated existing compile errors outside this change:grails-validation/src/main/groovy/grails/validation/Validateable.groovy: unable to resolvegroovy.transform.Virtualgrails-data-graphql/core/.../Arguable.groovyandComplexTyped.groovy: static type checking cannot findwithDelegate(Closure, Object)./gradlew :grails-test-report:check --continuewas attempted and exceeded the 20 minute tool timeout after producing broad test output.