The Apache Struts 7.4.0 test build is available. This release contains a
large number of breaking changes and deprecations, mostly around
parameter binding and the REST plugin, together with bug fixes and
improvements:

Breaking changes

- Five dev-mode configuration setters were removed from
SecurityMemberAccess (useDevMode, useDevModeExcludedClasses,
useDevModeExcludedPackageNamePatterns, useDevModeExcludedPackageNames,
useDevModeExcludedPackageExemptClasses) and the remaining configuration
setters are no longer container-injected; the struts.devMode.* settings
themselves are unchanged [WW-5675].
- With struts.parameters.requireAnnotations=true, a ModelDriven action's
own members now require @StrutsParameter; only the model's members stay
exempt, and struts.parameters.requireAnnotations.transitionMode is the
migration path [WW-5698].
- @StrutsParameter enforcement now recognises fluent (non-void) setters,
so an unannotated fluent setter is rejected like a void one [WW-5709].
- A nested property annotated on a ModelDriven action itself is now
primed into the OGNL allowlist, so it binds under
struts.allowlist.enable=true [WW-5710].
- A one-argument get* or two-argument set* method that is not the
indexed accessor of a real property is no longer invoked during
parameter binding [WW-5697].
- An interceptor-ref name repeated in one action's interceptor list now
applies each ref's own params to a WithLazyParams interceptor instead of
the first ref's [WW-5663].
- struts.csp.nonceSource is now honoured alongside
struts.csp.nonce.source, so a configuration carrying
struts.csp.nonceSource=request switches to request-scoped CSP nonces on
upgrade [WW-5669].
- Forms rendered with the html5 theme now carry HTML5 constraint
attributes derived from the action's validators, so browsers validate
before submitting [WW-5695].
- The Tiles plugin's legacy OGNL: attribute evaluator is disabled by
default and throws an EvaluationException;
struts.tiles.ognl.legacy.enabled=true restores it for the transition
[WW-5713].
- The REST plugin's restDefaultStack and the Bean Validation plugin's
beanValidationDefaultStack now include the coep, coop and fetchMetadata
interceptors, so a REST API serving cross-site browser clients must
configure fetchMetadata.exemptedPaths or disable that ref [WW-5718].
- The REST plugin rejects a request body longer than
struts.rest.content.maxLength (default 2097152) with
RequestBodyTooLargeException before the action runs [WW-5723].
- REST body authorization now keys off the Java member name rather than
the Jackson wire name, so a member renamed with @JsonProperty is
authorized by its own annotation [WW-5715].
- The REST plugin's Jackson handlers no longer merge a request body into
a polymorphic property that already holds a value; the value is replaced
through the authorized path and the body must carry the type id
[WW-5726].
- With struts.parameters.requireAnnotations=true, the id property of a
type using a property-based @JsonIdentityInfo is subject to
@StrutsParameter in REST bodies like any other property [WW-5727].
- A REST body object dropped after a @StrutsParameter redaction no
longer leaks its remaining fields into the enclosing object [WW-5747].
- The JasperReports plugin's ValueStackShadowMap resolves report
parameters not passed explicitly from the value stack again, so a report
parameter named like an action property now receives that value
[WW-5729].
- The JasperReports 7 plugin no longer brings
net.sf.jasperreports:jasperreports transitively; applications must
declare it (and jasperreports-pdf for PDF output) themselves [WW-5735].
- Convention-plugin wildcard action names containing a path-spanning **
now sort after every pattern without one, so a/*/* is matched before
a/** [WW-5743].

Deprecations

- The eleven remaining SecurityMemberAccess configuration setters
(useAllowStaticFieldAccess … useDisallowDefaultPackageAccess) are
deprecated; configuration is read through SecurityMemberAccessConfig.
Removal is WW-5682 [WW-5675].
- The constant name struts.csp.nonceSource
(StrutsConstants.STRUTS_CSP_NONCE_SOURCE_LEGACY) and
DefaultCspSettings.setLegacyNonceSource are deprecated; use
struts.csp.nonce.source [WW-5669].
- JavaScript client-side validation in the xhtml and css_xhtml themes
(validate="true" on <s:form>, Form.getValidators) is deprecated; use the
html5 theme's constraint attributes. Removal is WW-5696 [WW-5694].
- ReflectionContextState.DENY_INDEXED_ACCESS_EXECUTION is deprecated.
Removal is WW-5699 [WW-5697].
- RestfulActionMapper and Restful2ActionMapper are deprecated; use the
REST plugin. Removal is WW-5708 [WW-5707].
- StrutsParameterAuthorizer.hasValidAnnotatedPropertyDescriptor is
deprecated; use findBindableAccessor with hasValidAnnotatedMethod.
Removal is WW-5739 [WW-5709].
- The Tiles OGNLAttributeEvaluator and the
struts.tiles.ognl.legacy.enabled constant are deprecated. Removal is
WW-5714 [WW-5713].
- The REST plugin's one-argument
AuthorizingSettableBeanProperty(SettableBeanProperty) constructor is
deprecated; use the (SettableBeanProperty, String memberName) overload.
Removal is WW-5744 [WW-5715].
- ValueStackShadowMap.get(String) and containsKey(String) in the
JasperReports plugin are deprecated; use the Object overloads [WW-5729].

Rejected requests

Seven tickets were closed against this release without a change to
shipped code. They are listed here so the decision is visible rather
than silent.

[WW-2278] - Move S2 Tags into a plugin - will not be implemented as
filed; core depends on the tag packages, and the lean-core direction is
Struts 8 scope under its own ticket.
[WW-2975] - client side validation and components with forms - will not
be implemented; the JavaScript validator is deprecated (WW-5694) and
superseded by HTML5 constraint attributes (WW-5695) rather than
repaired.
[WW-3193] - Form action always inherits parent extension - closed as
Duplicate of WW-4164, where the per-package extension design continues.
[WW-3226] - Add optional support to AliasInterceptor to overwrite
aliased parameters - will not be implemented; interceptor ordering
already gives both behaviours, now documented and pinned by tests.
[WW-3232] - New Cookie Interceptor - will not be implemented; reading is
covered by CookieInterceptor with @StrutsParameter, writing by
CookieProvider.
[WW-3257] - Get Controller bean from Spring - closed as Not A Problem;
the Spring plugin already creates and autowires the controller, and a
bean registered under the fully qualified class name is picked up.
[WW-3338] - <s:hidden> tag should interpret its value attribute same as
the other tags do. - will not be implemented; String-valued attributes
are parsed for the %{} notation by design, and the Tag Syntax page is
corrected.

Bug
[WW-3353] - StrutsTestCase doesn't work with rest-plugin
[WW-5663] - DefaultActionInvocation.mergedParams resolves interceptor
params by name, merging the wrong ref when a name repeats
[WW-5667] - Performance Issue: SecurityMemberAccess re-parses excluded
packages/classes config string on every OGNL access — O(n) String.split
per request
[WW-5669] - CSP nonce source is not configurable: struts.csp.nonceSource
never reaches the injection point
[WW-5670] - Dispatcher.getLocale logs "defaulting to request locale" for
a locale that may not come from the request
[WW-5685] - DefaultConversionFileProcessor silently drops the rest of a
-conversion.properties file after the first already-mapped key
[WW-5686] - <s:date/> renders a java.sql.Date with the current
wall-clock time, making DateTest.testJavaSqlDate flaky
[WW-5688] - RestActionMapper maps URIs with an id into the empty
namespace, so actions declared at namespace "/" 404
[WW-5700] - Failed type conversion stores the NO_CONVERSION_POSSIBLE
marker string into typed Maps, Lists and Collections
[WW-5701] - CollectionConverter silently drops a legitimate element
whose text equals the NO_CONVERSION_POSSIBLE marker
[WW-5703] - HTML5 pattern false-rejects whitespace-only input that the
regex validator accepts
[WW-5704] - HTML5 required false-rejects on radio/file when the bound
property is never null
[WW-5705] - StringIndexOutOfBoundsException authorizing a parameter name
that begins with a nesting character
[WW-5706] - RestfulActionMapper does not apply the action name
validation used by DefaultActionMapper
[WW-5711] - StringConverter does not bound fraction digits when
formatting BigDecimal
[WW-5712] - ParameterAuthorizingModule does not wrap the Jackson
any-setter in the REST plugin
[WW-5715] - REST body authorization keys off the Jackson external
property name instead of the Java member
[WW-5724] - Cached MessageFormat instances in
AbstractLocalizedTextProvider are shared between concurrent callers
[WW-5725] - AuthorizingSettableBeanProperty does not authorize the
buffered set() path in the REST plugin
[WW-5726] - Merged polymorphic property with a non-null initial value is
not authorized in the REST plugin
[WW-5727] - The @JsonIdentityInfo id property is not authorized in the
REST plugin
[WW-5729] - JasperReports plugin: ValueStackShadowMap overloads
get/containsKey instead of overriding them, so the value-stack fallback
never reaches JasperReports
[WW-5731] - JasperReport7CsvExporterProvider sets the record delimiter
to the field delimiter
[WW-5732] - JasperReport7Result Javadoc example uses upper-case format
"CSV" which fails the exporter lookup
[WW-5733] - JasperReports 7 exporter providers close the response stream
before the report is written — empty response on Tomcat
[WW-5735] - JasperReports 7 plugin bundles the LGPL jasperreports jar
into the release distribution
[WW-5745] - REST plugin authorizes a forward-referenced object-id
property at the depth where the reference resolves
[WW-5746] - Members of a bean-typed @JsonIdentityInfo id are authorized
at the enclosing path in the REST plugin
[WW-5747] - RedactionAwareDeserializer leaves the parser mid-object when
it drops a REST body object
[WW-5748] - Registering ParameterAuthorizingModule breaks unwrapped XML
lists in JacksonXmlHandler
[WW-5749] - REST XML handlers throw NullPointerException when there is
no target to render

New Feature
[WW-5695] - Derive HTML5 constraint attributes from validators in the
html5 theme

Improvement
[WW-1742] - new token associated execute and wait interceptor
[WW-3245] - Jasper plugin does not support supply of data via report
parameters (for example Hibernate session object)
[WW-5676] - Decide whether array and primitive types should resolve to
their element/wrapper package in OGNL security checks
[WW-5687] - Clear the conversion and validator caches on
Dispatcher.cleanup() (WW-5537 defence-in-depth follow-on)
[WW-5694] - Deprecate JavaScript client-side validation in the xhtml and
css_xhtml themes
[WW-5713] - Fail closed for legacy Tiles OGNL evaluation
[WW-5716] - Bound the per-locale definition caches in the Tiles plugin
[WW-5718] - Plugin-provided default interceptor stacks omit the
resource-isolation interceptors
[WW-5719] - Verify pinned Maven wrapper bootstrap artifacts
[WW-5720] - AuthorizingSettableAnyProperty logs one WARN per rejected
dynamic key
[WW-5723] - REST plugin does not bound the request body read in
ContentTypeInterceptor
[WW-5740] - Resolve HTML5 constraint messages for visitor-validated
fields against the visited object
[WW-5743] - ActionNameSpecificityComparator can rank a broad ** pattern
ahead of a narrower */* one

Task
[WW-5684] - Document the SecurityMemberAccess dev-mode setter removal in
the Migration Guide
[WW-5690] - Defer loading the dev-mode error template until first use
[WW-5697] - Restrict the indexed-access fast path in XWorkMethodAccessor
to real indexed property accessors
[WW-5698] - ModelDriven exemption in StrutsParameterAuthorizer also
exempts the action's own members
[WW-5702] - Polish HTML5 constraint derivation: scope gaps and attribute
hygiene found reviewing WW-5695
[WW-5707] - Deprecate legacy restful and restful2 action mappers in core
[WW-5709] - @StrutsParameter enforcement does not recognise fluent
(non-void) setters
[WW-5710] - Allowlist priming targets the ModelDriven model even when
the parameter was authorised on the action
[WW-5717] - Address OWASP dependency-check finding in Spring Framework
(spring-core)
[WW-5728] - Add a struts-site page for the JasperReports 7 plugin
[WW-5734] - Run the JasperReports 7 plugin end-to-end on an embedded
Tomcat in its test suite
[WW-5741] - Dismiss the CodeQL java/xss alert on
DefaultContentTypeHandlerManager.handleResult as a false positive

Sub-task
[WW-5674] - Cut the per-call allocations in
SecurityMemberAccess.isClassBelongsToPackages
[WW-5675] - Stop re-parsing OGNL security config on every
SecurityMemberAccess instantiation
[WW-5677] - Remove the remaining redundant getPackage() lookups on the
OGNL member-access path

Release notes:
* https://cwiki.apache.org/confluence/display/WW/Version+Notes+7.4.0

Github release
* https://github.com/apache/struts/releases/tag/STRUTS_7_4_0

Distribution:
* https://dist.apache.org/repos/dist/dev/struts/7.4.0/

Maven 2 staging repository:
* https://repository.apache.org/content/groups/staging/

Once you have had a chance to review the test build, please respond
with a vote on its quality:

[ ] Leave at test build
[ ] Alpha
[ ] Beta
[ ] General Availability (GA)

Everyone who has tested the build is invited to vote. Votes by PMC
members are considered binding. A vote passes if there are at least
three binding +1s and more +1s than -1s.

The vote will remain open for at least 72 hours, longer upon request.
A vote can be amended at any time to upgrade or downgrade the quality
of the release based on future experience. If an initial vote
designates the build as "Beta", the release will be submitted for
mirroring and announced to the user list. Once released as a public
beta, subsequent quality votes on a build may be held on the user
list.

As always, the act of voting carries certain obligations. A binding
vote not only states an opinion, but means that the voter is agreeing
to help do the work.

On behalf of the Apache Struts project
Łukasz

Reply via email to