Skip to content

8.0.x - make configurable: allow-bean-definition-overriding / allow-circular-references#15765

Merged
jdaugherty merged 5 commits into
apache:8.0.xfrom
codeconsole:feat/configurable-bean-overriding-circular-refs
Jul 1, 2026
Merged

8.0.x - make configurable: allow-bean-definition-overriding / allow-circular-references#15765
jdaugherty merged 5 commits into
apache:8.0.xfrom
codeconsole:feat/configurable-bean-overriding-circular-refs

Conversation

@codeconsole

@codeconsole codeconsole commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

We shouldn't force bad practices and start providing an exit strategy

WARNING: Bean overriding will be deprecated in a future release.

GrailsApp and the unit-test harness GrailsApplicationBuilder hardcoded
allowBeanDefinitionOverriding(true) and allowCircularReferences(true). This
silently overrode any value an application set through the standard Spring Boot
properties spring.main.allow-bean-definition-overriding and
spring.main.allow-circular-references — so there was no way to turn either off.

Both now resolve those properties from the configured environment and default
to true
to preserve Grails' historical behavior (a plain Spring Boot app
defaults both to false). Applications can now opt into stricter startup
semantics:

spring:
  main:
    allow-bean-definition-overriding: false
    allow-circular-references: false

Changes

  • grails-coreGrailsApp.createApplicationContext() resolves both flags
    from the configured environment (defaulting to true).
  • grails-testing-support-coreGrailsApplicationBuilder.createMainContext()
    resolves the same properties, read after configuration data is loaded and
    before refresh().
  • docs — new "Bean Definition Overriding and Circular References" section in
    the Application class configuration guide.
  • testsGrailsAppContextOverridingSpec (grails-core) and
    GrailsApplicationBuilderContextOverridingSpec (grails-databinding).

Notes

  • The default is intentionally true. Grails' own bootstrap relies on bean
    definition overriding (the harness re-registers infrastructure beans such as
    internalConfigurationAnnotationProcessor). The test suite documents that
    disabling overriding makes a Grails context fail fast with
    BeanDefinitionOverrideException — which is exactly why the default differs
    from Spring Boot's.
  • GrailsApplicationBuilder lives in grails-testing-support-core, but its full
    bootstrap requires the servlet API, so its behavioral test lives in
    grails-databinding (which has the servlet API on its test classpath and
    already exercises the builder).

Verification

  • ./gradlew :grails-core:test :grails-databinding:test :grails-testing-support-core:test :grails-fields:test --rerun-tasks — green.
  • checkstyleMain/codenarcMain + checkstyleTest/codenarcTest on the
    changed modules — no violations.

@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 49.4717%. Comparing base (87c000a) to head (7e7fd90).
⚠️ Report is 69 commits behind head on 8.0.x.

Additional details and impacted files

Impacted file tree graph

@@               Coverage Diff                @@
##             8.0.x     #15765         +/-   ##
================================================
+ Coverage         0   49.4717%   +49.4717%     
- Complexity       0      16685      +16685     
================================================
  Files            0       1947       +1947     
  Lines            0      92469      +92469     
  Branches         0      16150      +16150     
================================================
+ Hits             0      45746      +45746     
- Misses           0      39619      +39619     
- Partials         0       7104       +7104     
Files with missing lines Coverage Δ
...-core/src/main/groovy/grails/boot/GrailsApp.groovy 45.9302% <100.0000%> (ø)
...core/src/main/groovy/grails/config/Settings.groovy 100.0000% <ø> (ø)
...org/grails/testing/GrailsApplicationBuilder.groovy 87.6190% <100.0000%> (ø)

... and 1944 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…rable

GrailsApp and the unit-test harness GrailsApplicationBuilder hardcoded
allowBeanDefinitionOverriding(true) and allowCircularReferences(true),
silently overriding any value set through the standard Spring Boot properties
spring.main.allow-bean-definition-overriding and
spring.main.allow-circular-references.

Both now resolve those properties from the configured environment, defaulting
to true to preserve Grails' historical behavior (a plain Spring Boot app
defaults both to false). Applications can opt into stricter startup semantics
via application.yml.

- grails-core: GrailsApp.createApplicationContext reads both flags from the
  configured environment.
- grails-testing-support-core: GrailsApplicationBuilder.createMainContext reads
  the same properties after configuration data is loaded and before refresh.
- docs: new section in the Application class configuration guide.
- tests: GrailsAppContextOverridingSpec (grails-core) and
  GrailsApplicationBuilderContextOverridingSpec (grails-databinding). The latter
  documents that disabling bean definition overriding fails a Grails unit
  context with BeanDefinitionOverrideException, which is why the default is true.
@codeconsole codeconsole force-pushed the feat/configurable-bean-overriding-circular-refs branch from dbc161b to 0713d3c Compare June 26, 2026 15:36
@codeconsole codeconsole changed the title Make bean definition overriding and circular references configurable 8.0.x - allow-bean-definition-overriding / allow-circular-references Jun 26, 2026
@codeconsole codeconsole changed the title 8.0.x - allow-bean-definition-overriding / allow-circular-references 8.0.x - make configurable: allow-bean-definition-overriding / allow-circular-references Jun 27, 2026
@codeconsole codeconsole force-pushed the feat/configurable-bean-overriding-circular-refs branch 2 times, most recently from e3b5acf to 9482237 Compare June 30, 2026 04:57
// behavior) but can be turned off via the standard spring.main.* properties. These are read
// after prepareContext so that application.yml (loaded by ConfigDataApplicationContextInitializer)
// and other property sources are available, and before refresh so the values take effect.
def environment = context.environment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The environment can be initialized prior to the context. As part of the context creation, can't beans be created? This would this make the settings after the fact?

@codeconsole codeconsole Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdaugherty Reordered so the environment is initialized and the spring.main.* flags are set before any bean definitions are registered (and before refresh()) — they now apply to the whole context lifecycle instead of after the fact.

@bito-code-review

Copy link
Copy Markdown

The environment is indeed initialized during the configureEnvironment phase, which occurs before createApplicationContext is called. In the provided changes, createApplicationContext uses configuredEnvironment to resolve settings, which is safe because the environment is already prepared by the time this method executes. While beans are created after the context is created, the configuration settings (like bean overriding and circular references) must be set on the ApplicationContext before the bean definitions are processed, which is exactly what this implementation achieves by calling the setters before super.createApplicationContext().

grails-core/src/main/groovy/grails/boot/GrailsApp.groovy

@Override
    protected ConfigurableApplicationContext createApplicationContext() {
        setAllowBeanDefinitionOverriding(isAllowedByConfig(Settings.SPRING_MAIN_ALLOW_BEAN_DEFINITION_OVERRIDING))
        setAllowCircularReferences(isAllowedByConfig(Settings.SPRING_MAIN_ALLOW_CIRCULAR_REFERENCES))
        ConfigurableApplicationContext applicationContext = super.createApplicationContext()

@codeconsole codeconsole requested a review from jdaugherty July 1, 2026 01:54
@testlens-app

testlens-app Bot commented Jul 1, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: 7e7fd90
▶️ Tests: 45255 executed
⚪️ Checks: 44/44 completed


Learn more about TestLens at testlens.app.

@jdaugherty jdaugherty merged commit 7543d6e into apache:8.0.x Jul 1, 2026
48 of 49 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants