apache / apache/grails-core

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

Open
#15,469 4 comments 1 reaction 0 assignees View on GitHub
feature maintenance relates-to:v8
Dominant language
Groovy
Stars
2.9k
Forks
975
Avg merge
1d 22h
Merged PRs (30d)
92

Description

## 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:

```groovy
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):
```groovy
security {
rememberMe {
cookieName = 'grails_remember_me'
tokenValiditySeconds = 1209600
}
}
```

**After** (@ConfigurationProperties POJO - auto-generates metadata):
```java
@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

- #15426 - Hybrid config report using hand-maintained JSON (grails-core, 9 modules)
- apache/grails-spring-security#1210 - Hand-maintained metadata for Spring Security (145 properties)
- wondrify/asset-pipeline#445 - Hand-maintained metadata for asset-pipeline (23 properties)

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the five existing configuration classes: DataBindingConfigurationProperties.java, GrailsCorsConfiguration.groovy, CachePluginConfiguration.groovy, JsonViewConfiguration.groovy, and MarkupViewConfiguration.groovy, along with their module build files. Verify how the annotation processor is configured and how generated metadata is checked during module builds. Done means the selected modules generate accurate metadata without hand-maintained duplicates, while preserving existing configuration behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
groovy, spring-boot
Domain
backend, build-system
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.