Replace config-properties.yml with standard spring-configuration-metadata.json#15426
Replace config-properties.yml with standard spring-configuration-metadata.json#15426jamesfredley merged 22 commits into7.0.xfrom
Conversation
Add a comprehensive Application Properties reference page under
ref/Configuration/ listing all Grails-specific configuration keys
with descriptions and default values. Covers core framework, GORM,
DataSource, Hibernate, Database Migration Plugin, Cache Plugin,
Asset Pipeline Plugin, Spring Security Plugin, and MongoDB GORM Plugin.
All external links use doc variables ({springBootVersion},
{hibernate5Reference}) for version-safe URLs.
Assisted-by: OpenCode <opencode@opencode.ai>
Assisted-by: Claude <claude@anthropic.com>
Merge curated property metadata from the Application Properties documentation with runtime-collected values from the Spring Environment. The command now outputs a 3-column AsciiDoc table (Property, Description, Default) organized by functional category (Core Properties, Web & Controllers, CORS, GORM, etc.). Runtime values override static defaults for known properties. Properties not found in the metadata appear in a separate Other Properties section. - Add config-properties.yml with ~160 properties across 21 categories - Modify ConfigReportCommand to load YAML metadata and merge with runtime - Update unit tests for 3-column hybrid format - Update integration tests for hybrid category-based layout Assisted-by: Claude Code <Claude@Claude.ai>
Add Apache license headers to config-properties.yml and logback.xml that were missing required ASF headers, causing CI RAT audit failure. Assisted-by: Claude Code <Claude@Claude.ai>
There was a problem hiding this comment.
Pull request overview
Adds a hybrid ConfigReportCommand to Grails that merges curated configuration-property metadata (from a new classpath YAML file) with runtime-resolved values from Spring’s ConfigurableEnvironment, and includes a new grails-test-examples/config-report sample app to validate the output format end-to-end.
Changes:
- Introduces
ConfigReportCommandto generate a categorized AsciiDoc report using static metadata + runtime overrides, with an “Other Properties” section for non-metadata keys. - Adds
META-INF/grails/config-properties.ymlcontaining categorized property metadata (descriptions + defaults). - Adds/updates unit + integration tests, including a new
grails-test-examples/config-reportmodule wired intosettings.gradle.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| settings.gradle | Adds the new grails-test-examples-config-report included build project. |
| grails-core/src/main/groovy/grails/dev/commands/ConfigReportCommand.groovy | Implements the hybrid config report generator (runtime collection + metadata merge + AsciiDoc output). |
| grails-core/src/main/resources/META-INF/grails/config-properties.yml | Supplies categorized metadata used to render known properties. |
| grails-core/src/test/groovy/grails/dev/commands/ConfigReportCommandSpec.groovy | Unit tests for property collection, metadata loading, escaping, and report layout. |
| grails-test-examples/config-report/** | New sample application + integration spec validating runtime config capture and report structure. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add instanceof Map guard after Yaml.load() in loadPropertyMetadata() to prevent NPE when the YAML resource is empty or contains a non-Map root. Remove unused @tempdir field and its import from the integration test. Assisted-by: Claude Code <Claude@Claude.ai>
|
@jdaugherty As long as CI passes, I think this is ready to review as the hybrid approach to generate the Configuration Reference. |
…ies doc Document how config properties are global by default and can be overridden per environment. Include default environments table (development/dev, test/test, production/prod), custom environment support, and activation via -Dgrails.env / GRAILS_ENV. Assisted-by: Claude Code <Claude@Claude.ai>
|
Updated screenshot with environments section: The-Grails-Framework-7-0-8-SNAPSHOT-02-26-2026_10_37_AM.pdf |
Replace custom YAML metadata with Spring configuration metadata, refactor config reporting to parse JSON resources, and generate docs during guide builds. Assisted-by: OpenCode <opencode@opencode.ai> Assisted-by: Claude Code <Claude@Claude.ai>
Use the correct Gradle project path :grails-data-hibernate5-core instead of :grails-data-hibernate5:core which does not exist as a project. Assisted-by: Claude Code <Claude@Claude.ai>
Remove java.util.Enumeration, java.util.Locale, and java.net.URL imports that are auto-imported in Groovy and cause UnnecessaryGroovyImport CodeNarc violations. Assisted-by: Claude Code <Claude@Claude.ai>
Follow-up: Configuration Metadata for Other PluginsThis PR standardizes grails-core on
Each plugin can follow the same pattern: add a |
…d JSON Views Add spring-configuration-metadata.json files for in-repo plugin modules: - grails-cache: 6 properties (grails.cache.*) - grails-data-hibernate5-dbmigration: 15 properties (grails.plugin.databasemigration.*) - grails-data-mongodb: 23 properties (grails.mongodb.*) - grails-views-gson: 9 properties (grails.views.json.*) Update grails-gsp metadata descriptions to match original documentation. Update generateConfigReference Gradle task to include all new modules and fix Plugin References with direct anchor links to config sections. Fix consecutive blank lines CodeNarc violation in ConfigReportCommand. Assisted-by: Claude Code <Claude@Claude.ai>
- Move spring-configuration-metadata.json from grails-gsp/src/ to grails-gsp/plugin/src/ to match the :grails-gsp project directory (grails-gsp/plugin). This was preventing 13 Views & GSP properties from appearing in the generated doc. - Update Spring Security link to correct published docs path - Update Asset Pipeline link to GitHub Pages URL Assisted-by: Claude Code <Claude@Claude.ai>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
✅ All tests passed ✅🏷️ Commit: 9a6dd39 Learn more about TestLens at testlens.app. |
matrei
left a comment
There was a problem hiding this comment.
Perhaps we should make a functional test app with tests that verify the defaults?
| "name": "grails.urlmapping.cache.maxsize", | ||
| "type": "java.lang.Integer", | ||
| "description": "The maximum size of the URL mapping cache.", | ||
| "defaultValue": 1000 |
There was a problem hiding this comment.
I think this is actually 5000 (DefaultUrlMappingsHolder). But in generated application.yml files it is set to 1000.
There was a problem hiding this comment.
@jdaugherty I think this came from the desire to pull them from a generated app vs the default in the code. Similar for comments below. Should it be default in code or in generated app, I lean towards code.
There was a problem hiding this comment.
We should change the default in the code.
There was a problem hiding this comment.
Resolved in e768e20: changed DEFAULT_MAX_WEIGHTED_CAPACITY in DefaultUrlMappingsHolder from 5000 to 1000 so the code default now matches the documented value (and what the generated application.yml used to contain before #15574 removed it). The JSON metadata stays at 1000 and now reflects the true code default.
| "name": "grails.views.default.codec", | ||
| "type": "java.lang.String", | ||
| "description": "The default encoding codec for GSP output. Set to `html` to reduce XSS risk. Options: `none`, `html`, `base64`.", | ||
| "defaultValue": "none" |
There was a problem hiding this comment.
I think, this property is only used as fallback default value of grails.views.gsp.codecs if that is not set, and in that case defaults to html. (GroovyPageParser, OutputEncodingSettings)
There was a problem hiding this comment.
Resolved in e768e20: changed defaultValue from none to html and updated the description to clarify that this is the fallback default used for grails.views.gsp.codecs.expression / scriptlet / taglib / staticparts when those are not set.
| "name": "grails.views.gsp.htmlcodec", | ||
| "type": "java.lang.String", | ||
| "description": "The HTML codec for GSP output (xml or html).", | ||
| "defaultValue": "xml" |
There was a problem hiding this comment.
I think this has no default value, but if specified and the value does not start with xml or equal (ignoring case) xhtml, it uses legacy HTML4Encoder instead of HTMLEncoder (HTMLCodec)
There was a problem hiding this comment.
Resolved in e768e20: removed the misleading xml default and rewrote the description to match the actual behavior - when unset (or when the value does not start with xml or equal xhtml ignoring case), a legacy HTML4-compatible encoder is used; setting it to xml or xhtml selects the XML-safe encoder.
| "name": "grails.mime.disable.accept.header.userAgents", | ||
| "type": "java.util.List<java.lang.String>", | ||
| "description": "List of user agent substrings (e.g., Gecko, WebKit) for which Accept header processing is disabled.", | ||
| "defaultValue": [] |
There was a problem hiding this comment.
I think default value is: ['Gecko', 'WebKit', 'Presto', 'Trident'] (HttpServletResponseExtension)
There was a problem hiding this comment.
Resolved in e768e20: changed defaultValue from [] to ["Gecko", "WebKit", "Presto", "Trident"] to match the regex pattern baked into HttpServletResponseExtension.useDefaultConfig(). Also tweaked the description to note the match is case-insensitive.
|
@jamesfredley I approved #15574 , once it's merged can you please update this & adjust for the feedback that @matrei has provided? We can then approve. |
… urlmapping cache size Addresses review feedback from matrei on #15426, reflecting the state after PR #15574 removed redundant defaults from generated application.yml files. - grails.urlmapping.cache.maxsize: change DEFAULT_MAX_WEIGHTED_CAPACITY in DefaultUrlMappingsHolder from 5000 to 1000 so the code default matches the documented value (the generated application.yml value removed in #15574). - grails.views.default.codec: correct defaultValue from 'none' to 'html' and clarify it is the fallback for the grails.views.gsp.codecs.* properties. - grails.views.gsp.htmlcodec: remove misleading 'xml' default and describe the actual behavior (when unset, the legacy HTML4-compatible encoder is used; setting it to 'xml' or 'xhtml' selects the XML-safe encoder). - grails.mime.disable.accept.header.userAgents: correct defaultValue from [] to ['Gecko', 'WebKit', 'Presto', 'Trident'] to match the regex baked into HttpServletResponseExtension. Assisted-by: sisyphus:claude-opus-4-7
Summary
Replaces the custom
config-properties.ymlmetadata with Spring Boot's standardspring-configuration-metadata.jsonformat, distributed across the 9 modules that own each set of properties. This gives IDEs (IntelliJ, VS Code, Eclipse STS) auto-completion and hover documentation for Grails configuration properties out of the box.The generated
Application Properties.adocreference recovers all content from the previous hand-written doc (descriptions, defaults, sections) while making it maintainable - each module owns its own metadata JSON and the doc is generated at build time. Compared to the old 135-property hand-written doc, the generated doc now covers 206 properties across 24 sections.For Grails 8, a follow-up initiative (#15469) proposes migrating to
@ConfigurationPropertiesannotated classes with the Spring Boot annotation processor, which would auto-generate the metadata JSON at compile time and eliminate manual maintenance entirely.What Changed
New
spring-configuration-metadata.jsonFiles (9 modules)grails-coregrails-web-coregrails-gspgrails-databindinggrails-data-hibernate5/coregrails-cachegrails-data-hibernate5/dbmigrationgrails-data-mongodb/grails-plugingrails-views-gsonTotal: 152 properties across 9 modules, generating a 866-line reference doc with 24 sections.
Refactored
ConfigReportCommandMETA-INF/spring-configuration-metadata.jsonfrom the classpath viaClassLoader.getResources()instead of custom YAMLConfigPropertyMetadataandMetadataResultimmutable data classes instead of raw mapsSystem.getenv()) into their own report sectionGenerated Documentation
generateConfigReferenceGradle task ingrails-doc/build.gradlereads metadata JSON from all 9 module JARs and generatesApplication Properties.adocduringpublishGuidedevelopment,test,production)Removed
grails-core/src/main/resources/META-INF/grails/config-properties.yml(814 lines of custom format)grails-doc/src/en/ref/Configuration/Application Properties.adoc(1440 lines of checked-in content, now generated)Companion PRs for External Plugins
Properties for plugins with their own repositories now have
spring-configuration-metadata.jsonin their respective repos, each with a generated properties reference doc:The "Plugin References" section in the generated doc links directly to the configuration properties section in each plugin's published documentation:
Future Direction
For Grails 8, issue #15469 tracks migrating to
@ConfigurationPropertiesannotated classes with thespring-boot-configuration-processor. Five modules already have@ConfigurationPropertiesclasses (DataBindingConfigurationProperties,GrailsCorsConfiguration,CachePluginConfiguration,JsonViewConfiguration,MarkupViewConfiguration) and could adopt auto-generation immediately. Modules using Groovy DSL config (like Spring Security'sDefaultSecurityConfig.groovy) would need a phased migration.Testing
ConfigReportCommandSpectests passgenerateConfigReferenceGradle task verified locally (866-line doc, 24 sections)