Skip to content

WW-5326 Upgrade OGNL to 3.5.0-BETA8 and introduce StrutsContext - #1654

Draft
lukaszlenart wants to merge 15 commits into
mainfrom
feat/ognl-3.5-upgrade
Draft

lukaszlenart wants to merge 15 commits into
mainfrom
feat/ognl-3.5-upgrade

Conversation

@lukaszlenart

@lukaszlenart lukaszlenart commented Apr 6, 2026 •

Copy link
Copy Markdown
Member

Summary

Fixes WW-5326

Upgrades OGNL from 3.4.15 to 3.5.0-BETA8 and introduces StrutsContext extends OgnlContext<StrutsContext> as the framework's own OGNL evaluation context. Targeted at Struts 8.0.0; the PR stays in draft until OGNL 3.5.0 is released as GA.

Changes

  • OGNL version bump: 3.4.15 → 3.5.0-BETA8 (Java 17 baseline)
  • StrutsContext: new class extending OgnlContext<StrutsContext> (@since 8.0.0)
  • Generic type ripple: all OGNL interface implementations in core (SecurityMemberAccess, accessors, null handler, type converters) are parameterized with <StrutsContext>
  • Direct context construction: OgnlUtil and OgnlValueStack build new StrutsContext(...) instead of calling Ognl.createDefaultContext()
  • Tiles plugin: the Tiles-side accessors stay on raw OgnlContext. The deprecated legacy OGNLAttributeEvaluator now evaluates with a StrutsContext that allows public members only, which is what Ognl.createDefaultContext gave it before
  • Tests: migrated to new StrutsContext(sma), including SecurityMemberAccessArrayTargetTest and the CDI plugin's CdiSecurityMemberAccessProxyTest, which landed on main after this branch was started

Compatibility (8.0.0 migration notes)

Struts registers its accessors in OGNL's JVM-global OgnlRuntime, including the method accessor for Object.class, and they now take a StrutsContext. Code in the same application that evaluates OGNL with its own raw OgnlContext (Ognl.getValue(expr, root), Ognl.createDefaultContext(...)) reaches those accessors and fails with a ClassCastException. Such code has to evaluate with a StrutsContext instead. This is what broke the legacy Tiles evaluator, and why it changed.

The same applies to a plain OgnlContext passed to OgnlUtil's getValue/setValue/setProperty methods: Struts now expects the StrutsContext it creates itself.

Custom PropertyAccessor / MethodAccessor / MemberAccess / TypeConverter implementations have to move to the generic OGNL 3.5 signatures.

Related

Design decisions

  • Direct construction over Ognl.withBuilderProvider(): Struts owns the context lifecycle, and no global provider is installed for other OGNL users in the JVM
  • Phase 1 only: introduces the class with no behavioural change. Promoting ReflectionContextState map entries to typed StrutsContext fields is Phase 2

Test plan

  • Core: 3411 tests, 0 failures
  • Tiles plugin: 565 tests, 0 failures
  • REST 223, JSON 167, Spring 61, Convention 55, Velocity 22, CDI 17, JUnit 12: 0 failures
  • Full reactor test-compile on the default and -Pjakartaee11 profiles
  • Full CI pipeline validation

🤖 Generated with Claude Code

@sonarqubecloud

sonarqubecloud Bot commented Apr 7, 2026

Copy link
Copy Markdown

lukaszlenart and others added 14 commits October 6, 2026 17:20
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…utsContext>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…h StrutsContext

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… StrutsContext construction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…sContext

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tiles accessors are called by OGNL internal machinery with raw OgnlContext,
not within a Struts evaluation context, so they cannot use StrutsContext.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Context

SecurityMemberAccessArrayTargetTest and CdiSecurityMemberAccessProxyTest still built a raw
OgnlContext via Ognl.createDefaultContext and no longer compiled against the typed
SecurityMemberAccess.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Struts registers its accessors in the JVM-global OgnlRuntime, including the method
accessor for Object.class, and they are now typed with StrutsContext. Ognl.getValue(expr, root)
builds a raw OgnlContext, so the legacy evaluator failed with a ClassCastException in the
accessors' bridge methods whenever struts.tiles.ognl.legacy.enabled=true.

The evaluator now builds a StrutsContext with the same public-members-only access that
Ognl.createDefaultContext uses, so its behaviour is unchanged.

Any other code in the same application that calls OGNL with its own raw OgnlContext hits
the same globally registered accessors and must switch to a StrutsContext.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lukaszlenart
lukaszlenart force-pushed the feat/ognl-3.5-upgrade branch from b039dc5 to a6c9f27 Compare October 6, 2026 15:28
@lukaszlenart lukaszlenart changed the title WW-5326 Upgrade OGNL from 3.4.10 to 3.5.0-BETA4 and introduce StrutsContext WW-5326 Upgrade OGNL to 3.5.0-BETA8 and introduce StrutsContext Oct 6, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Oct 8, 2026

Copy link
Copy Markdown

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant