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

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

                Author: ASF GitHub Bot
            Created on: 11/Sep/26 13:47
            Start Date: 11/Sep/26 13:47
    Worklog Time Spent: 10m 
      Work Description: lukaszlenart opened a new pull request, #1915:
URL: https://github.com/apache/struts/pull/1915

   Fixes [WW-5724](https://issues.apache.org/jira/browse/WW-5724)
   
   Backport of #1914 to the 6.x line.
   
   `AbstractLocalizedTextProvider` caches `MessageFormat` instances by pattern 
and locale and returned the cached instance itself from `buildMessageFormat`. 
`MessageFormat` is not thread-safe, so concurrent callers rendering the same 
message formatted through one shared instance; with a date or time sub-format 
that produced output for the wrong argument or an exception.
   
   `buildMessageFormat` now returns a clone of the cached instance, so the 
cached entry is only ever a template and is never formatted directly. 
`MessageFormat.clone()` deep-copies the sub-formats on Java 8 as well 
(`Calendar`, `DigitList`, `DateFormatSymbols`). The pattern-parsing cache is 
kept.
   
   Two tests added to `StrutsLocalizedTextProviderTest`, matching the main 
change: one asserts two lookups of the same pattern no longer return the same 
instance while the cache still holds one entry; the other renders a 
`{0,date,short}` message from four threads with distinct dates and asserts 
every output matches its own argument. Both failed before the change.
   
   No configuration or API change.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   




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

    Worklog Id:     (was: 1040946)
    Time Spent: 0.5h  (was: 20m)

> Cached MessageFormat instances in AbstractLocalizedTextProvider are shared 
> between concurrent callers
> -----------------------------------------------------------------------------------------------------
>
>                 Key: WW-5724
>                 URL: https://issues.apache.org/jira/browse/WW-5724
>             Project: Struts 2
>          Issue Type: Bug
>            Reporter: Lukasz Lenart
>            Priority: Major
>             Fix For: 6.12.0, 7.4.0
>
>          Time Spent: 0.5h
>  Remaining Estimate: 0h
>
> h2. Summary
> {{AbstractLocalizedTextProvider}} caches {{java.text.MessageFormat}} 
> instances keyed by pattern and locale and returns the cached instance from 
> {{buildMessageFormat}}, while {{DefaultTextProvider}} builds a fresh instance 
> per call. {{MessageFormat}} is not thread-safe, so callers rendering the same 
> message concurrently format through one shared instance.
> h2. Current behaviour
> {{buildMessageFormat}} returns the cached instance on a hit and 
> {{formatWithNullDetection}} calls {{format()}} on it directly. The provider 
> is a singleton bean, so the cache and every instance in it are shared 
> application-wide. The sibling {{DefaultTextProvider.getText}} constructs a 
> new {{MessageFormat}} on each call.
> A pattern carrying a date or time sub-format delegates to a 
> {{SimpleDateFormat}} held by the {{MessageFormat}}, which keeps per-call 
> state in its {{Calendar}}; concurrent {{format()}} calls on the shared 
> instance can render the wrong argument or throw. Number and choice 
> sub-formats and plain placeholders are not affected on current JDKs.
> h2. Proposed change
> Keep the cache, but have {{buildMessageFormat}} return a clone of the cached 
> instance, so the cached entry is only ever a template and is never formatted 
> directly. {{MessageFormat.clone()}} deep-copies its sub-formats. This 
> preserves the pattern-parsing cache the WW-5540 work relies on; measured 
> against a fresh instance per call and against synchronizing on the shared 
> instance, cloning is the cheapest of the three.
> h2. Compatibility notes
> No configuration or API change. Descendant classes that override 
> {{buildMessageFormat}} keep their current behaviour; only the base 
> implementation changes.
> Applies to both maintenance lines.



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

Reply via email to