Skip to content

Let autoConfigurationName name a package as well as a class - #16221

Open
codeconsole wants to merge 1 commit into
apache:8.0.xfrom
codeconsole:feat/beans-dsl-qualified-autoconfiguration-name-8.0.x
Open

Let autoConfigurationName name a package as well as a class#16221
codeconsole wants to merge 1 commit into
apache:8.0.xfrom
codeconsole:feat/beans-dsl-qualified-autoconfiguration-name-8.0.x

Conversation

@codeconsole

Copy link
Copy Markdown
Contributor

@GrailsBeans(autoConfigurationName = "...") sets only the simple name of the generated sibling; the package is always the plugin descriptor's own. Its documented purpose, though, is preserving the identity of an auto-configuration class a descriptor is being converted from:

Set this when converting an existing public @AutoConfiguration class whose name doesn't follow that convention and whose class identity must be preserved (e.g. for exclude = references, before=/after= ordering from other modules, or tests that import it by name).

Every one of those references names the qualified name. And a plugin descriptor conventionally sits in the package its implementation classes sit beneath rather than alongside them, so the class being converted is usually in a different package — which means identity changed anyway and the attribute could not prevent it.

This came up converting asset-pipeline, whose descriptor is asset.pipeline.AssetPipelineGrailsPlugin while its hand-written auto-configuration is asset.pipeline.grails.AssetPipelineAutoConfiguration. There is no value of autoConfigurationName that keeps that name today.

The change

siblingSimpleName() becomes siblingName() and returns the qualified name, so createAutoConfigurationSibling no longer prepends the descriptor's package unconditionally. Validation moves from SourceVersion.isIdentifier to SourceVersion.isName, which accepts a dotted sequence and rejects any part that is a keyword.

return name.indexOf('.') < 0 ? qualify(packageName, name) : name;
package com.example

@GrailsBeans(autoConfigurationName = 'com.example.web.ExampleAutoConfiguration')
@AutoConfiguration
class ExampleGrailsPlugin extends Plugin { def beans = { /* ... */ } }

Backward compatible. A dot was rejected outright before this, so every value that compiles today is a bare identifier and still resolves in the plugin's package. The non-literal and blank error paths are untouched; only the "is not a valid name" message extends to mention qualified names.

I deliberately did not restrict the package to one the plugin already owns — that would block legitimate conversions such as a descriptor at com.foo.plugins.BarGrailsPlugin replacing com.foo.bar.BarAutoConfiguration. Instead the javadoc and the guide both warn that generating into a package the plugin does not otherwise own splits that package across two jars, which modular and native-image consumers pay for. Happy to enforce rather than document it if you would prefer.

Tests

Eight cases added to GrailsBeansASTTransformationSpec:

  • a qualified name generates the sibling in the package it names, and not in the plugin's
  • a qualified name still carries the annotations that move to the sibling (@AutoConfiguration, @ConditionalOnWebApplication), and they still leave the plugin class
  • a bare name still names the sibling in the plugin's own package
  • five @Unrolled rejections: keyword package part, leading dot, trailing dot, empty part, space in a part

173 specs in grails-beans-dsl, 0 failures. Every module consuming the DSL was also run: grails-core, grails-i18n, grails-domain-class, grails-sitemesh3, and both beans-dsl test-example applications. ./gradlew codeStyle is clean.

Docs

GrailsBeans.java's javadoc no longer promises identity preservation it could not deliver, and hookingIntoRuntimeConfiguration.adoc had an explicit "(still generated in the plugin's own package)" that is replaced with the qualified-name form and a worked example.

Targets 8.0.x, where @GrailsBeans is new and unreleased. No ticket — happy to file one if you want it for the change log.

The attribute exists to preserve the identity of an auto-configuration class a
plugin descriptor is being converted from, which its own documentation gives as
the reason to set it: an exclude=, a before=/after= from another module, an entry
in AutoConfiguration.imports, a test importing it by name. Each of those names
the qualified name, and the attribute set only the simple one - the sibling was
always generated in the descriptor's own package.

A plugin descriptor conventionally sits in the package its implementation classes
sit beneath rather than alongside them, so the class being converted is usually
in another package and its identity changed anyway. Accepting a qualified name
lets it be kept.

A bare identifier still names the sibling in the plugin's package, so nothing
that compiles today changes: a dot was rejected outright before this.
@codecov

codecov Bot commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 54.1267%. Comparing base (27b6097) to head (ae65d13).

Files with missing lines Patch % Lines
...s/compiler/beans/GrailsBeansASTTransformation.java 85.7143% 0 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##                8.0.x     #16221        +/-   ##
==================================================
+ Coverage     54.1129%   54.1267%   +0.0138%     
- Complexity      20301      20312        +11     
==================================================
  Files            2107       2107                
  Lines          101146     101146                
  Branches        17922      17922                
==================================================
+ Hits            54733      54747        +14     
+ Misses          38605      38595        -10     
+ Partials         7808       7804         -4     
Files with missing lines Coverage Δ
...s/compiler/beans/GrailsBeansASTTransformation.java 86.2559% <85.7143%> (ø)

... and 4 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.

@testlens-app

testlens-app Bot commented Aug 25, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: ae65d13
▶️ Tests: 69408 executed
⚪️ Checks: 83/83 completed


Learn more about TestLens at testlens.app/docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant