[
https://issues.apache.org/jira/browse/WW-5827?focusedWorklogId=1052414&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1052414
]
ASF GitHub Bot logged work on WW-5827:
--------------------------------------
Author: ASF GitHub Bot
Created on: 04/Nov/26 12:26
Start Date: 04/Nov/26 12:26
Worklog Time Spent: 10m
Work Description: arunmanni-ai commented on PR #2084:
URL: https://github.com/apache/struts/pull/2084#issuecomment-6630558352
Both folded in, and the trailing whitespace is gone.
Three judgement calls in the `StrutsPreparerFactory` section, cheap to
change now and awkward after merge:
**The `super.createPreparer` fallback stays, but only for a genuine build
failure.** I read the ticket as scoping the double construction to the cast
path, so that is the path I closed: the type is checked before `buildBean`, and
a bean that is built but does not conform throws instead of falling back.
Nothing is constructed twice on either route. A real `buildBean` failure still
falls back, which is what an application gets today when the preparer is a
plain class the object factory cannot build. Say the word if you wanted the
fallback gone entirely and I will drop it.
**`checkType` lets `ClassNotFoundException` pass.** A preparer name is not
always a class name — bean names resolved by the object factory reach
`buildBean` as well, and failing those at the type check would break
configurations that work today. A name that does not resolve is logged at DEBUG
and left to the object factory; the final `instanceof` still catches it if what
comes back is not a `ViewPreparer`.
**The non-conforming case throws rather than returning null.** Same
reasoning as the `ClassUtil` section: null here would be swallowed by
`ignoreMissing` in `BasicTilesContainer.prepare` and turn a misconfigured
preparer into a silent no-op.
On the logging: the fallback is now WARN with the exception message and the
stack trace at DEBUG, so a misconfigured name no longer produces an ERROR stack
trace per request.
`mvn test -DskipAssembly -pl plugins/tiles` — 576 tests, 0 failures.
Description updated for the third section.
Issue Time Tracking
-------------------
Worklog Id: (was: 1052414)
Time Spent: 1h (was: 50m)
> Tiles plugin: check the preparer type before instantiating it and do not
> cache failed preparer lookups
> ------------------------------------------------------------------------------------------------------
>
> Key: WW-5827
> URL: https://issues.apache.org/jira/browse/WW-5827
> Project: Struts 2
> Issue Type: Improvement
> Components: Plugin - Tiles
> Reporter: Lukasz Lenart
> Priority: Major
> Time Spent: 1h
> Remaining Estimate: 0h
>
> Three issues in how the Tiles plugin resolves view preparers.
> *ClassUtil instantiates before checking the type*
> {{ClassUtil.getClass(String, Class)}} loads the class with
> {{Class.forName(className, true, classLoader)}}, so static initialisation
> runs on lookup. {{ClassUtil.instantiate(String, boolean)}} passes
> {{Object.class}} as the base type and calls {{newInstance()}}; the
> {{ViewPreparer}} check happens only afterwards, as a cast in
> {{BasicPreparerFactory.createPreparer}}. A configured preparer name that is
> not a {{ViewPreparer}} is therefore loaded, initialised and constructed
> before it is rejected.
> Expected: resolve the class without initialising it, apply the expected base
> type ({{ViewPreparer}}) before instantiation, and fail without constructing
> anything when it does not match.
> *BasicPreparerFactory caches failed lookups in a non-thread-safe map*
> {{BasicPreparerFactory.getPreparer}} stores the result of {{createPreparer}}
> in a plain {{HashMap}}, including the {{null}} returned when the class cannot
> be found. A failed lookup stays cached for the lifetime of the factory, and
> the map is read and written concurrently by request threads.
> Expected: do not cache failed lookups, and use a thread-safe map (e.g.
> {{ConcurrentHashMap}}).
> *StrutsPreparerFactory constructs before checking the type, twice on failure,
> and logs every failure at ERROR*
> {{StrutsPreparerFactory.createPreparer}} builds the preparer through
> {{ObjectFactory.buildBean}} and casts to {{ViewPreparer}} afterwards, so the
> type check above is not applied on this path. When the cast fails, the
> {{catch (Exception)}} falls back to {{super.createPreparer}}, which
> constructs the class a second time. The fallback logs at ERROR with a full
> stack trace; once failed lookups are no longer cached, a misconfigured
> preparer name would log that on every request instead of once.
> Expected: check the type before building the bean, construct at most once,
> and keep a failed lookup from producing a full ERROR stack trace per request.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)