Skip to content

Migrate configuration metadata to @ConfigurationProperties with annotation processor for Grails 8 #15469

@jamesfredley

Description

@jamesfredley

Summary

Grails currently hand-maintains spring-configuration-metadata.json files across multiple modules. Spring Boot provides an annotation processor (spring-boot-configuration-processor) that auto-generates this metadata from @ConfigurationProperties-annotated classes at compile time. Adopting this approach would eliminate manual metadata maintenance and prevent config drift.

Current State

Hand-Maintained JSON (prone to drift)

We maintain spring-configuration-metadata.json by hand in 9 grails-core modules, grails-spring-security, and asset-pipeline. During the PR #15426 / #1210 work, we discovered 62 properties had drifted out of sync in Spring Security alone (83 of 145 were present).

Modules that already have @ConfigurationProperties classes but lack the processor

These 5 modules already define config as POJOs but don't use the annotation processor to auto-generate metadata:

  • grails-databinding - DataBindingConfigurationProperties.java
  • grails-web-url-mappings - GrailsCorsConfiguration.groovy
  • grails-cache - CachePluginConfiguration.groovy
  • grails-views-gson - JsonViewConfiguration.groovy
  • grails-views-markup - MarkupViewConfiguration.groovy

Modules that use Groovy DSL closures for config

These cannot use the annotation processor without refactoring:

  • grails-core - config via application.groovy merging
  • grails-spring-security - DefaultSecurityConfig.groovy (Groovy closure DSL, 145 properties)
  • grails-web-core - mixed approach

Proposed Approach for Grails 8

Phase 1: Quick wins (add processor to existing @ConfigurationProperties modules)

Add the annotation processor dependency to the 5 modules that already have @ConfigurationProperties classes:

annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"

This would auto-generate the metadata JSON at compile time from the existing annotated classes. Javadoc on fields becomes the property description. Field initializers become the defaults. Zero manual JSON maintenance for these modules.

Phase 2: Migrate Groovy DSL config to @ConfigurationProperties POJOs

Refactor configuration that currently lives in Groovy DSL closures (like DefaultSecurityConfig.groovy) into @ConfigurationProperties-annotated Java or Groovy classes. For example:

Before (Groovy DSL - cannot be processed):

security {
    rememberMe {
        cookieName = 'grails_remember_me'
        tokenValiditySeconds = 1209600
    }
}

After (@ConfigurationProperties POJO - auto-generates metadata):

@ConfigurationProperties(prefix = "grails.plugin.springsecurity.rememberMe")
public class RememberMeProperties {
    /** Name of the remember-me cookie. */
    private String cookieName = "grails_remember_me";
    
    /** How long the token is valid in seconds (default 14 days). */
    private int tokenValiditySeconds = 1209600;
    
    // getters/setters
}

Phase 3: Use additional-spring-configuration-metadata.json for edge cases

For properties that can't be expressed via annotations (value hints, deprecations, class references), use src/main/resources/META-INF/additional-spring-configuration-metadata.json. The processor automatically merges this into the final output.

Benefits

  • No more drift - metadata stays in sync with code automatically
  • Descriptions from Javadoc - single source of truth, no duplication
  • IDE support - autocomplete, hover docs, validation in application.yml / application.properties all work from the generated file
  • Compile-time validation - processor catches issues during build
  • Standard Spring Boot pattern - familiar to the broader ecosystem

Considerations

  • Groovy DSL config is deeply embedded in the Grails config merging system - migration needs careful backward compatibility handling
  • Some properties use Groovy-specific types (closures, GStrings) that may need adaptation
  • The application.groovy config merging mechanism itself may need adjustment to work with bound @ConfigurationProperties beans
  • External plugins (Spring Security, asset-pipeline) would need their own migration timeline

Related PRs

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions