Skip to content

Convert SiteMesh 3 taglibs to method handlers and use SiteMesh 3.3.0-M1#15746

Open
codeconsole wants to merge 5 commits into
apache:8.0.xfrom
codeconsole:perf/sitemesh3-taglib-method-handlers
Open

Convert SiteMesh 3 taglibs to method handlers and use SiteMesh 3.3.0-M1#15746
codeconsole wants to merge 5 commits into
apache:8.0.xfrom
codeconsole:perf/sitemesh3-taglib-method-handlers

Conversation

@codeconsole

@codeconsole codeconsole commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #15713, addressing review feedback on RenderSitemeshTagLib:

To make this faster, you should use the method version instead of closure.

Converts both taglibs shipped by the SiteMesh 3 plugin from closure-based tags to the method handlers introduced in #15465, so GSP dispatch uses the faster reflective method-invocation path instead of cloning a closure on every tag invocation. This also clears the closure-based-tag deprecation warning the #15465 compiler check emits for these classes.

  • RenderSitemeshTagLib (sitemesh namespace) — applyLayout, pageProperty, ifPageProperty, layoutTitle, layoutHead, layoutBody, content.
  • Sitemesh3LayoutTagLib (grailsLayout namespace, @CompileStatic) — the compile-time capture tags captureHead, captureBody, captureTitle, wrapTitleTag, captureMeta, captureContent, parameter. These are emitted by GrailsLayoutPreprocessor and dispatched through GroovyPage.invokeTag, which already routes to method handlers (invokeTagLibMethodTagMethodInvoker).

After this change, no taglib used by the SiteMesh 3 plugin remains closure-based.

Behavior preservation

Only the tag declarations change; the tag bodies are untouched. Both the closure and method dispatch paths (TagOutput.captureTagOutput and GroovyPage.invokeTag) share the same output-stack setup and already pass TagOutput.EMPTY_BODY_CLOSURE (never null) as the body to two-argument tags, so the existing body / body instanceof Closure checks resolve identically whether each tag is a closure field or a method.

SiteMesh 3.3.0-M1

Also bumps the SiteMesh 3 dependencies (spring-boot-starter-sitemesh, spring-webmvc-sitemesh, and the transitive org.sitemesh:sitemesh core) from 3.3.0-SNAPSHOT to the released 3.3.0-M1 milestone, now on Maven Central. SiteMesh 2 (opensymphony:sitemesh 2.6.0, used by grails-layout) is unaffected.

Tests

  • Adds RenderSitemeshTagLibSpec and Sitemesh3LayoutTagLibSpec, which verify via the framework TagMethodInvoker API that all fourteen tags are discovered as invokable method handlers and no longer exist as closure fields.
  • End-to-end coverage in grails-test-examples/gsp-sitemesh3 (EndToEndSpec) continues to exercise the full capture/decoration pipeline at runtime.

Validation

  • ./gradlew :grails-sitemesh3:test — green (incl. both new specs)
  • ./gradlew :grails-sitemesh3:checkstyleMain :grails-sitemesh3:codenarcMain — green
  • ./gradlew :grails-test-examples-gsp-sitemesh3:integrationTest — green (EndToEndSpec 14/14, GrailsLayoutSpec 7/7) against SiteMesh 3.3.0-M1

Snapshot-repo regex cleanup (addresses #15710 review)

Addresses two review comments on #15710: the generated-app sitemesh snapshot repository's version filter does not need to match -SNAPSHOT explicitly, because the repository is already constrained to snapshots — snapshotsOnly: true in CreateAppCommand and VersionType.SNAPSHOT in GradleRepository. The version regex is simplified from .*-SNAPSHOT to .* in both places. (The pre-existing apache/groovy snapshot filters are left untouched.)

Convert the seven closure-based tags in RenderSitemeshTagLib
(applyLayout, pageProperty, ifPageProperty, layoutTitle, layoutHead,
layoutBody, content) to method handlers so GSP dispatch uses the faster
reflective method-invocation path added in apache#15465 instead of cloning a
closure on every invocation. This also clears the closure-based-tag
deprecation warning the apache#15465 compiler check emits for this class.

The conversion is behavior-preserving: GSP dispatch already passes
TagOutput.EMPTY_BODY_CLOSURE (never null) as the body to two-arg tags,
so the existing body checks resolve identically whether the tag is a
closure field or a method.

Sitemesh3LayoutTagLib is intentionally left as closures, matching its
SiteMesh 2 twin GrailsLayoutTagLib: those grailsLayout-namespace,
@CompileStatic capture tags driven by GrailsLayoutPreprocessor were
deliberately kept as closures in apache#15465.

Follow-up to apache#15713. Addresses review feedback on RenderSitemeshTagLib.
Bump the SiteMesh 3 dependencies (spring-boot-starter-sitemesh and
spring-webmvc-sitemesh, plus the transitive sitemesh core) from
3.3.0-SNAPSHOT to the released 3.3.0-M1 milestone, now available on
Maven Central. SiteMesh 2 (opensymphony:sitemesh 2.6.0, used by
grails-layout) is unaffected.
@codeconsole codeconsole changed the title Convert RenderSitemeshTagLib tags to method handlers Convert RenderSitemeshTagLib tags to method handlers and use SiteMesh 3.3.0-M1 Jun 18, 2026
… handlers

Convert the seven closure-based capture tags in Sitemesh3LayoutTagLib
(captureHead, captureBody, captureTitle, wrapTitleTag, captureMeta,
captureContent, parameter) to method handlers, completing the SiteMesh 3
plugin's move off closure-based tags so both shipped taglibs use the
faster method-invocation path and the apache#15465 closure-tag deprecation
warning is cleared for the whole plugin.

These grailsLayout-namespace capture tags are emitted by
GrailsLayoutPreprocessor and dispatched through GroovyPage.invokeTag,
which already routes to method handlers (invokeTagLibMethod ->
TagMethodInvoker) and passes a non-null EMPTY_BODY_CLOSURE body, so the
conversion is behavior-preserving even though the class is @CompileStatic.

Verified by the gsp-sitemesh3 EndToEndSpec integration suite (14 tests,
all passing) against SiteMesh 3.3.0-M1.
@codeconsole codeconsole changed the title Convert RenderSitemeshTagLib tags to method handlers and use SiteMesh 3.3.0-M1 Convert SiteMesh 3 taglibs to method handlers and use SiteMesh 3.3.0-M1 Jun 18, 2026
Address review feedback on apache#15710: the sitemesh snapshot-repository
version filter does not need to match -SNAPSHOT explicitly, because the
repository is already constrained to snapshots (snapshotsOnly: true in
CreateAppCommand, VersionType.SNAPSHOT in GradleRepository). Simplify the
version regex from '.*-SNAPSHOT' to '.*' in both the forge generator and
the shell-cli create-app command, matching how the version type is set.
List.of(
new VersionRegexRepoFilter(
"org[.]sitemesh.*", ".*", ".*-SNAPSHOT"
"org[.]sitemesh.*", ".*", ".*"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the M1 and actual release? I don't think this code should change since the below filter will still filter to only snapshots

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdaugherty per @matrei it's redundant and not needed. #15710


GrailsGradleRepository sitemeshSnapshots = new GrailsGradleRepository(url: 'https://central.sonatype.com/repository/maven-snapshots', snapshotsOnly: true)
sitemeshSnapshots.includeOnly('org[.]sitemesh.*', '.*', '.*-SNAPSHOT')
sitemeshSnapshots.includeOnly('org[.]sitemesh.*', '.*', '.*')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same
comment, I don't think this needs to change

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdaugherty per @matrei it's redundant and not needed. #15710

@codeconsole codeconsole requested a review from jdaugherty June 18, 2026 17:22
@testlens-app

testlens-app Bot commented Jun 18, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

⚠️ TestLens detected flakiness ⚠️

Test Summary

CI - Groovy Joint Validation Build / build_grails > :grails-test-examples-scaffolding:integrationTest

Test Runs Flakiness
UserControllerSpec > User list ❌ ✅

🏷️ Commit: 614cc29
▶️ Tests: 10452 executed
⚪️ Checks: 46/46 completed


Learn more about TestLens at testlens.app.

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.

2 participants