Skip to content

Register the scaffolding view resolver without the bean DSL#15966

Merged
jdaugherty merged 6 commits into
apache:8.0.xfrom
codeconsole:refactor/scaffolding-static-descriptor
Jul 11, 2026
Merged

Register the scaffolding view resolver without the bean DSL#15966
jdaugherty merged 6 commits into
apache:8.0.xfrom
codeconsole:refactor/scaffolding-static-descriptor

Conversation

@codeconsole

Copy link
Copy Markdown
Contributor

Summary

Migrates ScaffoldingGrailsPlugin off the deprecated doWithSpring() bean DSL (deprecated by #15934) and makes the descriptor fully @CompileStatic — the second in-tree plugin on the modern registration API, following the SiteMesh 3 module in #15964. The two PRs are independent; both preserve the same view-resolver pipeline.

Why not a straight beanRegistrar() port

The old DSL definition relied on bean.parent = 'abstractViewResolver', and parent/abstract bean templates are one of the DSL constructs BeanRegistry deliberately has no equivalent for (per #15934). Re-declaring the GSP resolver defaults inside scaffolding would duplicate them and drift.

Instead, beanRegistrar() registers a small ScaffoldingViewResolverDefinitionPostProcessor that contributes the jspViewResolver definition — same class, same abstractViewResolver parent, same lazyInit — at order -2, which slots into the established post-processor pipeline exactly where the DSL registration used to sit:

order post-processor behaviour
-2 ScaffoldingViewResolverDefinitionPostProcessor (this PR) contributes the scaffolding resolver definition unless one exists
-1 GrailsLayoutViewResolverPostProcessor (grails-layout / SiteMesh 2) embeds the existing definition as its inner view resolver
0 GroovyPagesPostProcessor (grails-gsp) contributes the plain GSP resolver only when no definition exists
+10 Sitemesh3ViewResolverDefinitionPostProcessor (#15964) wraps the definition for SiteMesh 3 decoration

Behavioural parity notes:

  • An existing jspViewResolver definition (application resources.groovy, another plugin) still wins, matching the old override semantics.
  • grails.scaffolding.enableNamespaceViewDefaults is now read from the Spring Environment rather than the Grails config object — equivalent since the config is built from the environment.
  • The reload-enabled computation (Environment.current / development-mode metadata) is unchanged, just relocated.

Testing

  • New ScaffoldingViewResolverDefinitionPostProcessorSpec covering registration (parent template, lazy-init, property values), the environment-driven enableNamespaceViewDefaults, existing-definition precedence, and the pipeline ordering contract.
  • :grails-scaffolding:test passes.
  • Verified end-to-end on a real application with this module and the Apply SiteMesh 3 decoration at the bean-definition level #15964 module swapped in together (the eventual merged state): scaffolded controller pages and (view:) URL mappings both render with layouts applied through the SiteMesh 3 view-resolver chain, and the resolver arrives wrapped as GrailsSiteMeshViewResolver[inner=ScaffoldingViewResolver].

Move the jspViewResolver registration out of doWithSpring() into a
ScaffoldingViewResolverDefinitionPostProcessor registered through
beanRegistrar(). The post-processor runs at order -2 — before the
SiteMesh 2 module's GrailsLayoutViewResolverPostProcessor (-1), which
embeds the definition as its inner view resolver, and before the GSP
plugin's GroovyPagesPostProcessor (0), which only contributes the plain
GSP resolver when no definition exists — so the established resolver
pipeline is preserved exactly. An existing jspViewResolver definition
still wins, matching the old override semantics.

The definition keeps the abstractViewResolver parent template rather
than duplicating the GSP resolver defaults, and reads
grails.scaffolding.enableNamespaceViewDefaults from the Spring
Environment instead of the post-hoc Grails config.

With no bean-builder closure left, the plugin descriptor is annotated
@CompileStatic.
Pure Spring infrastructure with no Groovy idiom - Java matches the
sibling Sitemesh3ViewResolverDefinitionPostProcessor, puts the class
under checkstyle, and drops the awkward fully-qualified references
that the grails.util.Environment / Spring Environment name clash
forced in Groovy.
The declared BeanRegistrar return type already coerces the returned
closure; the 'as BeanRegistrar' was redundant.
Hardcoding -2 would silently misorder the resolver pipeline if the GSP
post-processor's order ever moved. grails-scaffolding already depends on
the GSP plugin at runtime (loadAfter groovyPages, the abstractViewResolver
parent bean), so declaring the compile dependency makes the coupling
explicit and lets the constant be relative.
@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 49.6359%. Comparing base (81aa7c2) to head (f40b21b).
⚠️ Report is 25 commits behind head on 8.0.x.

Files with missing lines Patch % Lines
...ffoldingViewResolverDefinitionPostProcessor.groovy 83.3333% 0 Missing and 3 partials ⚠️
.../plugin/scaffolding/ScaffoldingGrailsPlugin.groovy 0.0000% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##                8.0.x     #15966        +/-   ##
==================================================
+ Coverage     49.6092%   49.6359%   +0.0267%     
- Complexity      16955      16968        +13     
==================================================
  Files            1999       2000         +1     
  Lines           93791      93803        +12     
  Branches        16421      16424         +3     
==================================================
+ Hits            46529      46560        +31     
+ Misses          40090      40073        -17     
+ Partials         7172       7170         -2     
Files with missing lines Coverage Δ
.../plugin/scaffolding/ScaffoldingGrailsPlugin.groovy 0.0000% <0.0000%> (ø)
...ffoldingViewResolverDefinitionPostProcessor.groovy 83.3333% <83.3333%> (ø)

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

The ordering test asserted against a literal with the collaborators'
orders recorded only in a comment, so renumbering
GrailsLayoutViewResolverPostProcessor or GroovyPagesPostProcessor would
break the pipeline while the test kept passing. It now asserts against
the real constants, with grails-layout added as a test dependency.

Also correct the stand-down comment: suppression applies to any existing
definition, which is stricter than the old doWithSpring() registration
that overwrote definitions from earlier-loading plugins.
@testlens-app

This comment has been minimized.

@jdaugherty jdaugherty merged commit 10960ba into apache:8.0.x Jul 11, 2026
54 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.

2 participants