This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/struts-site.git
The following commit(s) were added to refs/heads/asf-site by this push:
new f793f2fca Automatic Site Publish by Buildbot
f793f2fca is described below
commit f793f2fca798d7756910f634b32f0e7c74796592
Author: buildbot <[email protected]>
AuthorDate: Fri Oct 2 10:19:19 2026 +0000
Automatic Site Publish by Buildbot
---
output/core-developers/action-mapper.html | 3 +-
.../execute-and-wait-interceptor.html | 35 +++++++++++-
output/core-developers/restful-action-mapper.html | 7 +++
.../struts-parameter-annotation.html | 65 +++++++++++++++++-----
output/plugins/bean-validation/index.html | 8 +++
output/plugins/jasperreports/index.html | 5 +-
output/plugins/jasperreports7/index.html | 19 ++++++-
output/plugins/rest/index.html | 49 ++++++++++++++++
8 files changed, 171 insertions(+), 20 deletions(-)
diff --git a/output/core-developers/action-mapper.html
b/output/core-developers/action-mapper.html
index 2445fb460..6e1c5eb93 100644
--- a/output/core-developers/action-mapper.html
+++ b/output/core-developers/action-mapper.html
@@ -305,7 +305,8 @@ methods.</p>
</code></pre></div></div>
<p><code class="language-plaintext
highlighter-rouge">CompositeActionMapper</code> will be configured with 2
ActionMapper, namely “struts” which is <code class="language-plaintext
highlighter-rouge">org.apache.struts2.dispatcher.mapper.DefaultActionMapper</code>
-and “restful” which is <code class="language-plaintext
highlighter-rouge">org.apache.struts2.dispatcher.mapper.RestfulActionMapper</code>.</p>
+and “restful” which is <code class="language-plaintext
highlighter-rouge">org.apache.struts2.dispatcher.mapper.RestfulActionMapper</code>.
The <code class="language-plaintext highlighter-rouge">restful</code> and
<code class="language-plaintext highlighter-rouge">restful2</code> mappers
+are deprecated since 7.4.0 and 6.12.0, see <a
href="restful-action-mapper">RestfulActionMapper</a>.</p>
<p><code class="language-plaintext
highlighter-rouge">CompositeActionMapper</code> would consult each of them in
order described above.</p>
diff --git a/output/core-developers/execute-and-wait-interceptor.html
b/output/core-developers/execute-and-wait-interceptor.html
index ed00e435a..ed45f0828 100644
--- a/output/core-developers/execute-and-wait-interceptor.html
+++ b/output/core-developers/execute-and-wait-interceptor.html
@@ -156,7 +156,10 @@
<ul id="markdown-toc">
<li><a href="#parameters" id="markdown-toc-parameters">Parameters</a></li>
- <li><a href="#extending-the-interceptor"
id="markdown-toc-extending-the-interceptor">Extending the Interceptor</a></li>
+ <li><a href="#extending-the-interceptor"
id="markdown-toc-extending-the-interceptor">Extending the Interceptor</a>
<ul>
+ <li><a href="#one-background-process-per-browser-tab"
id="markdown-toc-one-background-process-per-browser-tab">One background process
per browser tab</a></li>
+ </ul>
+ </li>
<li><a href="#using-executorprovider"
id="markdown-toc-using-executorprovider">Using ExecutorProvider</a></li>
<li><a href="#examples" id="markdown-toc-examples">Examples</a> <ul>
<li><a href="#example-code-1" id="markdown-toc-example-code-1">Example
code 1</a></li>
@@ -225,6 +228,36 @@ for obtaining and releasing resources that the background
process will need to e
background
process extension, extend <code class="language-plaintext
highlighter-rouge">ExecuteAndWaitInterceptor</code> and implement the <code
class="language-plaintext highlighter-rouge">getNewBackgroundProcess()</code>
method.</p>
+<h3 id="one-background-process-per-browser-tab">One background process per
browser tab</h3>
+
+<p>The background process is keyed by action name alone, so a second browser
tab of the same session joins the process
+already running instead of starting its own. Override <code
class="language-plaintext
highlighter-rouge">getBackgroundProcessName(ActionProxy)</code> to widen that
key, for
+example with the transaction token, so that each tab gets its own process:</p>
+
+<div class="language-java highlighter-rouge"><div class="highlight"><pre
class="highlight"><code><span class="kd">public</span> <span
class="kd">class</span> <span
class="nc">TokenizedExecuteAndWaitInterceptor</span> <span
class="kd">extends</span> <span class="nc">ExecuteAndWaitInterceptor</span>
<span class="o">{</span>
+ <span class="nd">@Override</span>
+ <span class="kd">protected</span> <span class="nc">String</span> <span
class="nf">getBackgroundProcessName</span><span class="o">(</span><span
class="nc">ActionProxy</span> <span class="n">proxy</span><span
class="o">)</span> <span class="o">{</span>
+ <span class="nc">String</span> <span class="n">token</span> <span
class="o">=</span> <span class="nc">TokenHelper</span><span
class="o">.</span><span class="na">getToken</span><span class="o">();</span>
+ <span class="k">return</span> <span class="n">token</span> <span
class="o">==</span> <span class="kc">null</span>
+ <span class="o">?</span> <span class="kd">super</span><span
class="o">.</span><span class="na">getBackgroundProcessName</span><span
class="o">(</span><span class="n">proxy</span><span class="o">)</span>
+ <span class="o">:</span> <span class="kd">super</span><span
class="o">.</span><span class="na">getBackgroundProcessName</span><span
class="o">(</span><span class="n">proxy</span><span class="o">)</span> <span
class="o">+</span> <span class="s">"_"</span> <span class="o">+</span> <span
class="n">token</span><span class="o">;</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre></div></div>
+
+<p>Two caveats apply to any key that varies per request:</p>
+
+<ul>
+ <li>the entry is dropped from the session only when a request observes the
process as done, so every run the user
+abandons leaves a background process, and the action instance it holds, in the
session. With the action-name key
+that is at most one per action; with a per-tab key it grows without limit.</li>
+ <li>the wait page must send the value used in the key on every refresh, for
instance with <code class="language-plaintext highlighter-rouge"><s:url
includeParams="all"/></code>
+together with the <a href="token-interceptor">Token Interceptor</a>. Otherwise
each refresh starts another background process
+instead of joining the running one.</li>
+</ul>
+
+<p>See <a href="https://issues.apache.org/jira/browse/WW-1742">WW-1742</a>.</p>
+
<h2 id="using-executorprovider">Using ExecutorProvider</h2>
<p>Since Struts 6.2.0 it is possible to use your own <code
class="language-plaintext highlighter-rouge">ExecutorProvider</code> to run
<em>background tasks</em>. To use your own executor
diff --git a/output/core-developers/restful-action-mapper.html
b/output/core-developers/restful-action-mapper.html
index 99a3477a7..9760056ad 100644
--- a/output/core-developers/restful-action-mapper.html
+++ b/output/core-developers/restful-action-mapper.html
@@ -155,6 +155,7 @@
<h1 class="no_toc" id="restfulactionmapper">RestfulActionMapper</h1>
<ul id="markdown-toc">
+ <li><a href="#restfulactionmapper-1"
id="markdown-toc-restfulactionmapper-1">RestfulActionMapper</a></li>
<li><a href="#restful2actionmapper"
id="markdown-toc-restful2actionmapper">Restful2ActionMapper</a> <ul>
<li><a href="#example" id="markdown-toc-example">Example</a></li>
<li><a href="#unit-testing" id="markdown-toc-unit-testing">Unit
testing</a></li>
@@ -162,6 +163,12 @@
</li>
</ul>
+<p class="alert alert-warning"><code class="language-plaintext
highlighter-rouge">RestfulActionMapper</code> and <code
class="language-plaintext highlighter-rouge">Restful2ActionMapper</code> are
deprecated since Struts 7.4.0 and 6.12.0 and will be removed in a
+future release (<a
href="https://issues.apache.org/jira/browse/WW-5707">WW-5707</a>). Both predate
the
+<a href="../plugins/rest">REST Plugin</a>, which is the maintained way to
build REST-style applications; use it instead.</p>
+
+<h2 id="restfulactionmapper-1">RestfulActionMapper</h2>
+
<p>A custom action mapper using the following format:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre
class="highlight"><code>http://HOST/ACTION_NAME/PARAM_NAME1/PARAM_VALUE1/PARAM_NAME2/PARAM_VALUE2
diff --git a/output/core-developers/struts-parameter-annotation.html
b/output/core-developers/struts-parameter-annotation.html
index 28dc7fd8d..4cddbdeb5 100644
--- a/output/core-developers/struts-parameter-annotation.html
+++ b/output/core-developers/struts-parameter-annotation.html
@@ -157,6 +157,7 @@
<ul id="markdown-toc">
<li><a href="#where-authorization-applies"
id="markdown-toc-where-authorization-applies">Where authorization applies</a>
<ul>
<li><a href="#creator-bound-properties"
id="markdown-toc-creator-bound-properties">Creator-bound properties</a></li>
+ <li><a href="#rest-body-properties-are-matched-by-their-java-name"
id="markdown-toc-rest-body-properties-are-matched-by-their-java-name">REST body
properties are matched by their Java name</a></li>
<li><a href="#jackson-any-setters"
id="markdown-toc-jackson-any-setters">Jackson any-setters</a></li>
</ul>
</li>
@@ -193,7 +194,7 @@ action chaining (opt-in via <code class="language-plaintext
highlighter-rouge">s
<li><a href="../../plugins/json">JSON</a> and <a
href="../../plugins/rest">REST</a> plugins — per-property
authorization performed during deserialization, so an unauthorized property is
not set on
the target object. This covers the properties the deserializer binds
<strong>by name</strong>; in the
-REST plugin a Jackson any-setter is a separate sink that is not covered — see
+REST plugin a Jackson any-setter is covered only when you opt in — see
<a href="#jackson-any-setters">Jackson any-setters</a> below.</li>
</ul>
@@ -215,25 +216,61 @@ object under construction is dropped instead of failing
the request.</p>
the same way as any nested object: <code class="language-plaintext
highlighter-rouge">@StrutsParameter(depth = ...)</code> on the getter that
reaches them, or a <code class="language-plaintext
highlighter-rouge">ModelDriven</code>
model. Otherwise those values silently stop arriving.</p>
+<h3 id="rest-body-properties-are-matched-by-their-java-name">REST body
properties are matched by their Java name</h3>
+
+<p>The REST plugin authorizes a request-body property against the Java member
Jackson writes to — the
+field, or the bean property its setter is named after — not against the name
used on the wire. A
+member renamed with <code class="language-plaintext
highlighter-rouge">@JsonProperty</code>, <code class="language-plaintext
highlighter-rouge">@JsonAlias</code> or a <code class="language-plaintext
highlighter-rouge">PropertyNamingStrategy</code> is authorized by the
+annotation on that member. Up to Struts 7.3.0 the wire name was used, so a
renamed annotated member
+was rejected as unannotated (<a
href="https://issues.apache.org/jira/browse/WW-5715">WW-5715</a>).</p>
+
+<p>Since Struts 7.4.0 two more REST paths are checked like any other
property:</p>
+
+<ul>
+ <li>the id property of a type using a property-based <code
class="language-plaintext highlighter-rouge">@JsonIdentityInfo</code>
+(<a href="https://issues.apache.org/jira/browse/WW-5727">WW-5727</a>);</li>
+ <li>a polymorphic (<code class="language-plaintext
highlighter-rouge">@JsonTypeInfo</code>) property that is mergeable and already
holds a value. The body is no longer merged
+into the existing value; the property is replaced through the authorized path,
so the body must carry the type id
+(<a href="https://issues.apache.org/jira/browse/WW-5726">WW-5726</a>).</li>
+</ul>
+
<h3 id="jackson-any-setters">Jackson any-setters</h3>
<p>A class that declares a Jackson any-setter — <code
class="language-plaintext highlighter-rouge">@JsonAnySetter</code> on a method,
on a field, or on a
<code class="language-plaintext highlighter-rouge">@JsonCreator</code>
parameter — tells Jackson to route <strong>every otherwise-unknown key</strong>
in the request body
to that member. The REST plugin’s authorization wrapper covers the properties
Jackson binds by name;
-an any-setter is a separate sink and is not wrapped. Keys arriving through it
are therefore set
-without an <code class="language-plaintext
highlighter-rouge">@StrutsParameter</code> check, even with <code
class="language-plaintext
highlighter-rouge">struts.parameters.requireAnnotations</code> enabled, and
-even in the same request in which an ordinary unannotated setter on the same
class is correctly
-rejected.</p>
+by default an any-setter is not wrapped, so keys arriving through it are set
without an
+<code class="language-plaintext highlighter-rouge">@StrutsParameter</code>
check, even with <code class="language-plaintext
highlighter-rouge">struts.parameters.requireAnnotations</code> enabled.</p>
+
+<p>Since Struts 7.4.0 you can bring any-setters under authorization by setting
+<code class="language-plaintext
highlighter-rouge">struts.rest.anySetter.requireAnnotations</code> to <code
class="language-plaintext highlighter-rouge">true</code>
+(<a href="https://issues.apache.org/jira/browse/WW-5712">WW-5712</a>). The
setting defaults to <code class="language-plaintext
highlighter-rouge">false</code> for compatibility and,
+like the rest of REST body authorization, takes effect only when <code
class="language-plaintext
highlighter-rouge">struts.parameters.requireAnnotations</code> is enabled.
+With it on, an any-setter receives keys only when the method or field carries
+<code class="language-plaintext
highlighter-rouge">@StrutsParameter(allowDynamicKeys = true)</code>:</p>
+
+<div class="language-java highlighter-rouge"><div class="highlight"><pre
class="highlight"><code><span class="nd">@StrutsParameter</span><span
class="o">(</span><span class="n">allowDynamicKeys</span> <span
class="o">=</span> <span class="kc">true</span><span class="o">,</span> <span
class="n">depth</span> <span class="o">=</span> <span class="mi">1</span><span
class="o">)</span>
+<span class="nd">@JsonAnySetter</span>
+<span class="kd">public</span> <span class="kt">void</span> <span
class="nf">setExtra</span><span class="o">(</span><span
class="nc">String</span> <span class="n">key</span><span class="o">,</span>
<span class="nc">Object</span> <span class="n">value</span><span
class="o">)</span> <span class="o">{</span>
+ <span class="n">extras</span><span class="o">.</span><span
class="na">put</span><span class="o">(</span><span class="n">key</span><span
class="o">,</span> <span class="n">value</span><span class="o">);</span>
+<span class="o">}</span>
+</code></pre></div></div>
+
+<p><code class="language-plaintext highlighter-rouge">depth</code> limits how
deeply nested each dynamic key’s value may be: <code class="language-plaintext
highlighter-rouge">depth = 0</code> accepts scalar values only, <code
class="language-plaintext highlighter-rouge">depth = 1</code>
+also accepts an object or array one level deep. A key whose any-setter is
unannotated, or whose value is nested deeper
+than allowed, is dropped. An any-setter on a <code class="language-plaintext
highlighter-rouge">@JsonCreator</code> parameter rejects every key. Rejected
keys are logged as
+one WARN per any-setter and reason, not one per key. <code
class="language-plaintext highlighter-rouge">allowDynamicKeys</code> has no
effect on ordinary request parameters.</p>
+
+<div class="language-xml highlighter-rouge"><div class="highlight"><pre
class="highlight"><code><span class="nt"><constant</span> <span
class="na">name=</span><span
class="s">"struts.rest.anySetter.requireAnnotations"</span> <span
class="na">value=</span><span class="s">"true"</span><span
class="nt">/></span>
+</code></pre></div></div>
-<p>Two limits are worth knowing. An any-setter beneath an <strong>unauthorized
parent</strong> is still unreachable:
-the parent is rejected first and its whole subtree is skipped. And <code
class="language-plaintext highlighter-rouge">@JsonUnwrapped</code> is a named
-property, so it is unaffected by this.</p>
+<p>An any-setter beneath an <strong>unauthorized parent</strong> is
unreachable either way: the parent is rejected first and its whole
+subtree is skipped. <code class="language-plaintext
highlighter-rouge">@JsonUnwrapped</code> is a named property, so it is
unaffected by this.</p>
-<p class="alert alert-warning">Declaring an any-setter on a class bound from a
REST request body is the application accepting
-arbitrary names and values off the wire — the same decision as binding a <code
class="language-plaintext highlighter-rouge">Map</code>, and it deserves the
-same scrutiny. Where that is not what you want, do not declare one on a
request-bound class, or
-narrow what the method accepts before storing it. Tracked as
-<a href="https://issues.apache.org/jira/browse/WW-5712">WW-5712</a>.</p>
+<p class="alert alert-warning">With <code class="language-plaintext
highlighter-rouge">struts.rest.anySetter.requireAnnotations</code> left at
<code class="language-plaintext highlighter-rouge">false</code>, declaring an
any-setter on a class bound from a REST
+request body is the application accepting arbitrary names and values off the
wire — the same decision as binding a
+<code class="language-plaintext highlighter-rouge">Map</code>, and it deserves
the same scrutiny. Enable the setting, do not declare an any-setter on a
request-bound class, or
+narrow what the method accepts before storing it.</p>
<h2 id="modeldriven-actions">ModelDriven actions</h2>
@@ -302,7 +339,7 @@ bindable, use action properties annotated with <code
class="language-plaintext h
<p>The placement of the <code class="language-plaintext
highlighter-rouge">@StrutsParameter</code> annotation is crucial and depends on
how you want to populate your action properties.</p>
<ul>
- <li><strong>On a public setter method:</strong> Place the annotation on a
setter method when you want to populate the property with a value from the
request. This applies to:
+ <li><strong>On a public setter method:</strong> Place the annotation on a
setter method when you want to populate the property with a value from the
request. Since Struts 7.4.0 this includes fluent setters that return a value
instead of <code class="language-plaintext highlighter-rouge">void</code>;
before, an annotation on a fluent setter was ignored (<a
href="https://issues.apache.org/jira/browse/WW-5709">WW-5709</a>). This applies
to:
<ul>
<li>Simple types (String, int, boolean, etc.).</li>
<li>Checkboxes (single or multiple values).</li>
diff --git a/output/plugins/bean-validation/index.html
b/output/plugins/bean-validation/index.html
index 5574b0311..177b58e4e 100644
--- a/output/plugins/bean-validation/index.html
+++ b/output/plugins/bean-validation/index.html
@@ -209,6 +209,14 @@ by extending your own application package from <code
class="language-plaintext h
<span class="nt"></struts></span>
</code></pre></div></div>
+<p class="alert alert-warning">Since Struts 7.4.0 and 6.12.0 the plugin’s
<code class="language-plaintext
highlighter-rouge">beanValidationDefaultStack</code> contains the
+<a href="/core-developers/coep-interceptor"><code class="language-plaintext
highlighter-rouge">coep</code></a>, <a
href="/core-developers/coop-interceptor"><code class="language-plaintext
highlighter-rouge">coop</code></a> and
+<a href="/core-developers/fetch-metadata-interceptor"><code
class="language-plaintext highlighter-rouge">fetchMetadata</code></a>
interceptors, configured as in core’s <code class="language-plaintext
highlighter-rouge">defaultStack</code>
+(<a href="https://issues.apache.org/jira/browse/WW-5718">WW-5718</a>). Earlier
versions left them out. Cross-site requests that
+use a method other than GET and are not navigations are now rejected: the
action is not invoked and the interceptor
+returns the result code <code class="language-plaintext
highlighter-rouge">403</code>, which needs a matching (global) result to render
a response. Set
+<code class="language-plaintext
highlighter-rouge">fetchMetadata.disabled</code> to <code
class="language-plaintext highlighter-rouge">true</code> on the stack for
actions that must accept such requests.</p>
+
<p>Here is another example that shows how you can combine bean-validation with
other plugins by configuring your own
Interceptor-Stack (note: this is just a very short example. In a real app you
should take more care about your stack).
You can combine bean validation with classic struts validation (or disable
either) by putting the according interceptors
diff --git a/output/plugins/jasperreports/index.html
b/output/plugins/jasperreports/index.html
index f20759675..311057b1f 100644
--- a/output/plugins/jasperreports/index.html
+++ b/output/plugins/jasperreports/index.html
@@ -199,7 +199,10 @@ If no format is specified, PDF will be used</li>
<li>imageServletUrl - name of the url that, when prefixed with the context
page, can return report images</li>
<li>reportParameters - (since 2.1.2+) OGNL expression used to retrieve a map
of report parameters from the value stack.
The parameters may be accessed in the report via the usual JR mechanism and
might include data not part of the
-dataSource, such as the user name of the report creator, etc.</li>
+dataSource, such as the user name of the report creator, etc.
+A report parameter that is not in this map is looked up on the value stack by
its name, so a parameter <code class="language-plaintext
highlighter-rouge">title</code>
+receives the action’s <code class="language-plaintext
highlighter-rouge">getTitle()</code>. This lookup did not reach JasperReports
from 6.0.0 to 7.3.0, so those
+parameters were <code class="language-plaintext
highlighter-rouge">null</code>; it works again since 7.4.0 (<a
href="https://issues.apache.org/jira/browse/WW-5729">WW-5729</a>).</li>
<li>exportParameters - (since 2.1.2+) OGNL expression used to retrieve a map
of JR exporter parameters from the value stack.
The export parameters are used to customize the JR export. For example, a PDF
export might enable encryption
and set the user password to a string known to the report creator.</li>
diff --git a/output/plugins/jasperreports7/index.html
b/output/plugins/jasperreports7/index.html
index afef9728b..026239dc9 100644
--- a/output/plugins/jasperreports7/index.html
+++ b/output/plugins/jasperreports7/index.html
@@ -361,8 +361,9 @@ extension when <code class="language-plaintext
highlighter-rouge">documentName</
<h3 id="installation">Installation</h3>
<p>This plugin can be installed by copying the plugin jar into your
application’s <code class="language-plaintext
highlighter-rouge">/WEB-INF/lib</code> directory. The plugin
-brings the JasperReports 7 core library with it, but the PDF exporter lives in
a separate JasperReports artifact
-which is an optional dependency of the plugin. As <code
class="language-plaintext highlighter-rouge">pdf</code> is the default format,
most applications need to add it:</p>
+does not bring JasperReports with it: add the <code class="language-plaintext
highlighter-rouge">jasperreports</code> library yourself, and the <code
class="language-plaintext highlighter-rouge">jasperreports-pdf</code> exporter
as
+well when you produce PDF output, which as the default format most
applications do. The plugin is built against
+JasperReports 7.0.7.</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre
class="highlight"><code><span class="nt"><dependencies></span>
...
@@ -371,6 +372,11 @@ which is an optional dependency of the plugin. As <code
class="language-plaintex
<span
class="nt"><artifactId></span>struts2-jasperreports7-plugin<span
class="nt"></artifactId></span>
<span class="nt"><version></span>STRUTS_VERSION<span
class="nt"></version></span>
<span class="nt"></dependency></span>
+ <span class="nt"><dependency></span>
+ <span class="nt"><groupId></span>net.sf.jasperreports<span
class="nt"></groupId></span>
+ <span class="nt"><artifactId></span>jasperreports<span
class="nt"></artifactId></span>
+ <span class="nt"><version></span>JASPERREPORTS_VERSION<span
class="nt"></version></span>
+ <span class="nt"></dependency></span>
<span class="nt"><dependency></span>
<span class="nt"><groupId></span>net.sf.jasperreports<span
class="nt"></groupId></span>
<span class="nt"><artifactId></span>jasperreports-pdf<span
class="nt"></artifactId></span>
@@ -380,7 +386,14 @@ which is an optional dependency of the plugin. As <code
class="language-plaintex
<span class="nt"></dependencies></span>
</code></pre></div></div>
-<p>Use the same <code class="language-plaintext
highlighter-rouge">JASPERREPORTS_VERSION</code> as the <code
class="language-plaintext highlighter-rouge">jasperreports</code> artifact
pulled in by the plugin.</p>
+<p>Use the same <code class="language-plaintext
highlighter-rouge">JASPERREPORTS_VERSION</code> for both artifacts.</p>
+
+<p class="alert alert-warning">Struts 7.1.0 to 7.3.0 declared <code
class="language-plaintext highlighter-rouge">jasperreports</code> as a compile
dependency of the plugin, so it arrived transitively and
+was bundled in the release distribution. JasperReports is LGPL licensed and
cannot be shipped in an Apache release,
+so since 7.4.0 it is a <code class="language-plaintext
highlighter-rouge">provided</code> dependency, as it has always been in the
+<a href="../jasperreports">JasperReports Plugin</a> (<a
href="https://issues.apache.org/jira/browse/WW-5735">WW-5735</a>). When
upgrading,
+add the <code class="language-plaintext
highlighter-rouge">jasperreports</code> dependency yourself, otherwise the
application fails at runtime with missing JasperReports
+classes.</p>
<h2 id="migrating-from-the-jasperreports-plugin">Migrating from the
JasperReports plugin</h2>
diff --git a/output/plugins/rest/index.html b/output/plugins/rest/index.html
index a9e0c7f43..cfb3f89de 100644
--- a/output/plugins/rest/index.html
+++ b/output/plugins/rest/index.html
@@ -177,6 +177,8 @@
<li><a href="#xstream-configuration"
id="markdown-toc-xstream-configuration">XStream configuration</a></li>
<li><a href="#custom-contenttypehandlers"
id="markdown-toc-custom-contenttypehandlers">Custom ContentTypeHandlers</a></li>
<li><a href="#settings" id="markdown-toc-settings">Settings</a></li>
+ <li><a href="#request-body-size-limit"
id="markdown-toc-request-body-size-limit">Request body size limit</a></li>
+ <li><a href="#resource-isolation-in-restdefaultstack"
id="markdown-toc-resource-isolation-in-restdefaultstack">Resource isolation in
restDefaultStack</a></li>
</ul>
</li>
<li><a href="#resources" id="markdown-toc-resources">Resources</a></li>
@@ -601,9 +603,56 @@ For more configuration options see the <a
href="../convention">Convention Plugin
<td>true</td>
<td>eg. put struts.rest.content.restrictToGET = false in
struts.properties</td>
</tr>
+ <tr>
+ <td>struts.rest.content.maxLength</td>
+ <td>Maximum number of characters read from a request body, see <a
href="#request-body-size-limit">Request body size limit</a>. Since 7.4.0 and
6.12.0</td>
+ <td>2097152</td>
+ <td>Any integer of 1 or more</td>
+ </tr>
+ <tr>
+ <td>struts.rest.anySetter.requireAnnotations</td>
+ <td>Whether keys bound through a Jackson any-setter require <code
class="language-plaintext highlighter-rouge">@StrutsParameter(allowDynamicKeys
= true)</code>, see <a
href="/core-developers/struts-parameter-annotation#jackson-any-setters">Jackson
any-setters</a>. Since 7.4.0</td>
+ <td>false</td>
+ <td>true, false</td>
+ </tr>
</tbody>
</table>
+<h3 id="request-body-size-limit">Request body size limit</h3>
+
+<p>Since Struts 7.4.0 and 6.12.0 the plugin stops reading a request body once
it passes <code class="language-plaintext
highlighter-rouge">struts.rest.content.maxLength</code>
+characters (2 MB by default, the same as <code class="language-plaintext
highlighter-rouge">struts.json.maxLength</code> in the <a href="../json">JSON
plugin</a>) and fails the request
+with a <code class="language-plaintext
highlighter-rouge">RequestBodyTooLargeException</code> before the action runs
+(<a href="https://issues.apache.org/jira/browse/WW-5723">WW-5723</a>). The
limit is applied while the content-type handler reads
+the body, so requests whose handler never reads it — HTML, form-urlencoded,
multipart — are not affected.</p>
+
+<div class="language-xml highlighter-rouge"><div class="highlight"><pre
class="highlight"><code><span class="nt"><constant</span> <span
class="na">name=</span><span class="s">"struts.rest.content.maxLength"</span>
<span class="na">value=</span><span class="s">"10485760"</span><span
class="nt">/></span>
+</code></pre></div></div>
+
+<p class="alert alert-warning">An API that accepts JSON or XML payloads larger
than 2 MB must raise <code class="language-plaintext
highlighter-rouge">struts.rest.content.maxLength</code> when upgrading,
+otherwise those requests start failing.</p>
+
+<h3 id="resource-isolation-in-restdefaultstack">Resource isolation in
restDefaultStack</h3>
+
+<p>Since Struts 7.4.0 and 6.12.0 <code class="language-plaintext
highlighter-rouge">restDefaultStack</code> contains the <a
href="/core-developers/coep-interceptor"><code class="language-plaintext
highlighter-rouge">coep</code></a>,
+<a href="/core-developers/coop-interceptor"><code class="language-plaintext
highlighter-rouge">coop</code></a> and <a
href="/core-developers/fetch-metadata-interceptor"><code
class="language-plaintext highlighter-rouge">fetchMetadata</code></a>
+interceptors, configured as in core’s <code class="language-plaintext
highlighter-rouge">defaultStack</code>
+(<a href="https://issues.apache.org/jira/browse/WW-5718">WW-5718</a>). Earlier
versions left them out, so a package extending
+<code class="language-plaintext highlighter-rouge">rest-default</code> sent no
COOP/COEP headers and skipped the Fetch Metadata check. A request rejected by
the Fetch Metadata
+check is answered with HTTP status 403 and no response body.</p>
+
+<p class="alert alert-warning">The Fetch Metadata check rejects browser
requests sent with <code class="language-plaintext
highlighter-rouge">Sec-Fetch-Site: cross-site</code> that use a method other
+than GET and are not navigations, which includes <code
class="language-plaintext highlighter-rouge">POST</code>, <code
class="language-plaintext highlighter-rouge">PUT</code> and <code
class="language-plaintext highlighter-rouge">DELETE</code> calls made with
<code class="language-plaintext highlighter-rouge">fetch()</code>/XHR from a
+single-page application served from another site. If your REST API is meant to
be called from such a page, disable the
+check for the stack serving it:</p>
+
+<div class="language-xml highlighter-rouge"><div class="highlight"><pre
class="highlight"><code><span class="nt"><interceptor-ref</span> <span
class="na">name=</span><span class="s">"restDefaultStack"</span><span
class="nt">></span>
+ <span class="nt"><param</span> <span class="na">name=</span><span
class="s">"fetchMetadata.disabled"</span><span class="nt">></span>true<span
class="nt"></param></span>
+<span class="nt"></interceptor-ref></span>
+</code></pre></div></div>
+
+<p>Requests sent by non-browser clients carry no <code
class="language-plaintext highlighter-rouge">Sec-Fetch-Site</code> header and
are not affected.</p>
+
<h2 id="resources">Resources</h2>
<ul>