[ 
https://issues.apache.org/jira/browse/WW-5641?focusedWorklogId=1028298&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1028298
 ]

ASF GitHub Bot logged work on WW-5641:
--------------------------------------

                Author: ASF GitHub Bot
            Created on: 06/Jul/26 17:36
            Start Date: 06/Jul/26 17:36
    Worklog Time Spent: 10m 
      Work Description: lukaszlenart opened a new pull request, #1766:
URL: https://github.com/apache/struts/pull/1766

   Fixes [WW-5641](https://issues.apache.org/jira/browse/WW-5641)
   
   ## Problem
   
   A custom JSON writer/reader configured the documented way is silently 
ignored on the 7.2.x line — the framework always uses the default 
`StrutsJSONWriter` / `StrutsJSONReader`:
   
   ```xml
   <bean type="org.apache.struts2.json.JSONWriter" name="flexJSONWriter"
         class="org.demo.FlexJSONWriter" scope="prototype"/>
   <constant name="struts.json.writer" value="flexJSONWriter"/>
   ```
   
   This worked on 7.1.x and regressed in 7.2.x. The extension point is still 
documented at <https://struts.apache.org/plugins/json/>, so this is a 
regression, not an intended API change.
   
   ## Root cause
   
   Writer/reader selection moved from a **runtime, by-name lookup** (7.1.x) to 
a **container-build-time alias** (7.2.x, introduced with the JSON hardening 
rework that added `<bean-selection>` to the plugin's `struts-plugin.xml`).
   
   `XmlDocConfigurationProvider.registerBeanSelection()` invokes 
`JSONBeanSelectionProvider.register()` → 
`AbstractBeanSelectionProvider.alias()` **inline, the moment the 
`<bean-selection>` element is parsed** in the JSON plugin's 
`struts-plugin.xml`. At that instant the shared `props` hold only the plugin's 
own `struts.json.writer=struts`; the application `struts.xml` is a *later* 
`ContainerProvider` whose override bean/constant have not been folded in yet. 
So `alias()` locks `JSONWriter/DEFAULT_NAME → StrutsJSONWriter`, and nothing 
re-runs the selection once the app config loads. `JSONUtil` in 7.2.x injected 
that frozen default binding.
   
   The 7.1.x code was immune because `JSONUtil` resolved the writer/reader by 
the constant value at container-use time — after the full container (including 
the app `struts.xml`) was built.
   
   ## Fix
   
   Restore 7.1.x-style deferred resolution, confined to `JSONUtil`: inject the 
`Container` and resolve the writer/reader from the **effective** 
`struts.json.writer` / `struts.json.reader` constant values (named lookup) at 
injection time, instead of relying on the build-time default alias. 
`setWriter`/`setReader` remain public plain setters (only `@Inject` removed).
   
   Preserves the 7.2.x hardening:
   - `StrutsJSONWriter` / `StrutsJSONReader` remain the shipped defaults.
   - JSON DoS limits (`maxDepth`, `maxElements`, `maxLength`, 
`maxStringLength`, `maxKeyLength`) untouched — their `@Inject` setters still 
fire on the resolved bean.
   - `JSONUtil` and the writer/reader stay `prototype`; `serialize(...)` never 
touches `container`, so per-instance resolution and thread-safety of the 
bean-info cache are unchanged.
   
   The `<bean-selection>` / default alias is left in place (harmless) so any 
external `container.getInstance(JSONWriter.class)` keeps working.
   
   ## Test
   
   `JSONWriterOverrideTest` boots the real `Dispatcher` config chain 
(`struts-default.xml,struts-plugin.xml,struts-json-override.xml`, in that 
order) so the provider ordering that causes the bug is reproduced, and asserts 
the **effective** writer (serialize sentinel) and reader 
(`getReader().getClass()`) — covering both `struts.json.writer` and 
`struts.json.reader`. Verified failing before the fix, passing after. Full 
`struts2-json-plugin` suite: 127/127 green.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   




Issue Time Tracking
-------------------

            Worklog Id:     (was: 1028298)
    Remaining Estimate: 0h
            Time Spent: 10m

> JSON plugin ignores struts.json.writer / struts.json.reader override 
> (regression since 7.2.x)
> ---------------------------------------------------------------------------------------------
>
>                 Key: WW-5641
>                 URL: https://issues.apache.org/jira/browse/WW-5641
>             Project: Struts 2
>          Issue Type: Bug
>          Components: Plugin - JSON
>    Affects Versions: 7.2.1
>            Reporter: Lukasz Lenart
>            Assignee: Lukasz Lenart
>            Priority: Major
>             Fix For: 7.3.0
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> h2. Summary
> A custom JSON writer/reader configured the documented way via the 
> {{struts.json.writer}} /
> {{struts.json.reader}} constants is silently ignored. The framework always 
> uses the default
> {{StrutsJSONWriter}} / {{StrutsJSONReader}}. This worked in the 7.1.x line 
> and regressed in
> 7.2.x as a side effect of the JSON hardening rework that introduced 
> {{<bean-selection>}} for
> the JSON plugin.
> The extension point is still documented at 
> [https://struts.apache.org/plugins/json/], so this
> is a regression, not an intended API change.
> h2. How to reproduce
> In an application {{struts.xml}}:
> {code:xml}
> <bean type="org.apache.struts2.json.JSONWriter" name="flexJSONWriter"
>       class="org.demo.FlexJSONWriter" scope="prototype"/>
> <constant name="struts.json.writer" value="flexJSONWriter"/>
> {code}
> *Expected:* JSON is serialized by {{FlexJSONWriter}}.
> *Actual:* JSON is serialized by the default {{StrutsJSONWriter}}; the 
> override is never used.
> Confirmed via the {{json-customize}} module reproduction in 
> apache/struts-examples PR #535
> ({{ProduceActionTest}}): passes on 7.1.x, fails on 7.2.x.
> h2. Root cause
> Writer/reader selection moved from a *runtime, by-name lookup* to a 
> *container-build-time alias*.
> * In 7.1.x, {{JSONUtil}} injected the {{Container}} and resolved the 
> writer/reader at use time
>   from the constant value — this ran after the full container (including the 
> app {{struts.xml}})
>   was built, so overrides applied.
> * In 7.2.x, {{JSONUtil}} injects the default {{JSONWriter}} / {{JSONReader}} 
> binding, which is
>   chosen once by the new {{JSONBeanSelectionProvider}} (wired via 
> {{<bean-selection>}} in the
>   plugin's {{struts-plugin.xml}}).
> {{XmlDocConfigurationProvider.registerBeanSelection()}} invokes the 
> bean-selection provider
> *inline, the moment the {{<bean-selection>}} element is parsed* in the 
> plugin's
> {{struts-plugin.xml}}. At that instant the shared {{props}} hold only the 
> plugin's own
> {{struts.json.writer=struts}}; the application {{struts.xml}} is a later 
> {{ContainerProvider}}
> whose override bean/constant have not been folded in yet. So
> {{AbstractBeanSelectionProvider.alias()}} takes the "found by default name" 
> branch and locks
> {{JSONWriter/DEFAULT_NAME -> StrutsJSONWriter}}. Nothing re-runs the 
> selection once the app
> config loads, so the override is dropped. The 7.1.x deferred runtime lookup 
> was immune to this
> ordering.
> h2. Proposed fix
> Restore deferred, runtime by-name resolution in {{JSONUtil}} (mirrors 7.1.x): 
> inject the
> {{Container}} and resolve the writer/reader from the *effective* 
> {{struts.json.writer}} /
> {{struts.json.reader}} constant values at injection time, instead of relying 
> on the
> build-time default alias.
> * Change is localized to {{JSONUtil}}; {{JSONUtil}} is the only consumer of 
> {{JSONWriter}} /
>   {{JSONReader}}.
> * Preserves the 7.2.x hardening: {{StrutsJSONWriter}} / {{StrutsJSONReader}} 
> remain the shipped
>   defaults, and the DoS limits ({{struts.json.maxDepth}}, {{maxElements}}, 
> {{maxLength}},
>   {{maxStringLength}}, {{maxKeyLength}}) are unchanged.
> * Preserves {{prototype}} scope and per-instance resolution — no 
> thread-safety regression for
>   the stateful bean-info caching.
> h2. Regression test
> Add a test exercising the full bootstrap ({{struts-default.xml}} + the JSON 
> plugin's
> {{struts-plugin.xml}} + a user override config, in that order) and assert the 
> *effective*
> writer and reader used by {{JSONUtil}} are the overrides — covering both 
> {{struts.json.writer}}
> and {{struts.json.reader}}.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to