This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts.git
The following commit(s) were added to refs/heads/main by this push:
new 76d6b1405 WW-5782 fix(tags): document and warn that s:a href ignores
nested params (#2034)
76d6b1405 is described below
commit 76d6b140538a6fe9227ebf1674f5a999599158db
Author: Lukasz Lenart <[email protected]>
AuthorDate: Fri Oct 16 12:29:16 2026 +0200
WW-5782 fix(tags): document and warn that s:a href ignores nested params
(#2034)
With an explicit href the anchor tag never applies nested <s:param> tags;
they are only used when the URL is built from value or action. The javadoc
example showed exactly that combination.
The example now uses value, the javadoc and the href attribute description
say nested params are not applied to href, and in devMode the tag logs a
warning naming the ignored params. Rendered output is unchanged; applying
params to href is WW-5783 (8.0.0).
Co-authored-by: Claude Opus 5.5 <[email protected]>
---
.../java/org/apache/struts2/components/Anchor.java | 11 +++--
core/src/site/resources/tags/a-attributes.html | 2 +-
.../apache/struts2/views/jsp/AnchorTagTest.java | 50 ++++++++++++++++++++++
3 files changed, 59 insertions(+), 4 deletions(-)
diff --git a/core/src/main/java/org/apache/struts2/components/Anchor.java
b/core/src/main/java/org/apache/struts2/components/Anchor.java
index 6bda43f20..9e7e09fc7 100644
--- a/core/src/main/java/org/apache/struts2/components/Anchor.java
+++ b/core/src/main/java/org/apache/struts2/components/Anchor.java
@@ -38,7 +38,8 @@ import java.util.Map;
* <!-- START SNIPPET: javadoc -->
* <p>
* A tag that creates a HTML <a >.This tag supports the same attributes
as the "url" tag,
- * including nested parameters using the "param" tag.
+ * including nested parameters using the "param" tag. Nested parameters are
applied only when the URL is built
+ * from the "value" or "action" attributes; they are ignored when "href" is
set.
* </p>
* <!-- END SNIPPET: javadoc -->
*
@@ -46,7 +47,7 @@ import java.util.Map;
*
* <pre>
* <!-- START SNIPPET: example1 -->
- * <s:a id="link1" href="/do-it.action">
+ * <s:a id="link1" value="/do-it.action">
* <img border="none"
src="<%=request.getContextPath()%>/images/delete.gif"/>
* <s:param name="id" value="1"/>
* </s:a>
@@ -101,6 +102,10 @@ public class Anchor extends ClosingUIBean {
if (href != null) {
addParameter("href",
ensureAttributeSafelyNotEscaped(findString(href)));
+ if (devMode && !urlParameters.isEmpty()) {
+ LOG.warn("Nested params {} are ignored because <s:a> has href
[{}], use value or action to build a URL with params",
+ urlParameters.keySet(), href);
+ }
} else {
//no href, build it from URL attributes
StringWriter sw = new StringWriter();
@@ -189,7 +194,7 @@ public class Anchor extends ClosingUIBean {
return urlProvider;
}
- @StrutsTagAttribute(description = "The URL.")
+ @StrutsTagAttribute(description = "The URL. Nested param tags are not
applied, use value or action to build a URL with params")
public void setHref(String href) {
this.href = href;
}
diff --git a/core/src/site/resources/tags/a-attributes.html
b/core/src/site/resources/tags/a-attributes.html
index 48ba23f96..738d0bc36 100644
--- a/core/src/site/resources/tags/a-attributes.html
+++ b/core/src/site/resources/tags/a-attributes.html
@@ -123,7 +123,7 @@
<td class="tag-attribute"></td>
<td class="tag-attribute">false</td>
<td class="tag-attribute">String</td>
- <td class="tag-attribute">The URL.</td>
+ <td class="tag-attribute">The URL. Nested param tags are not applied,
use value or action to build a URL with params</td>
</tr>
<tr>
<td class="tag-attribute">id</td>
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/AnchorTagTest.java
b/core/src/test/java/org/apache/struts2/views/jsp/AnchorTagTest.java
index 7bf07bd68..1b9047a2b 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/AnchorTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/AnchorTagTest.java
@@ -18,6 +18,8 @@
*/
package org.apache.struts2.views.jsp;
+import org.apache.struts2.components.Anchor;
+import org.apache.struts2.test.LogCapture;
import org.apache.struts2.views.jsp.ui.AnchorTag;
import org.apache.struts2.views.jsp.ui.StrutsBodyContent;
@@ -1646,4 +1648,52 @@ public class AnchorTagTest extends AbstractUITagTest {
pageContext.setJspWriter(jspWriter);
}
+ public void testHrefIgnoresNestedParams() throws Exception {
+ tag.setHref("/do-it.action");
+
+ try (LogCapture logs = new LogCapture(Anchor.class)) {
+ renderWithParam("id", "%{'1'}");
+
+ assertEquals(wrapWithAnchor("/do-it.action"), writer.toString());
+ assertTrue(logs.messages().toString(), logs.messages().isEmpty());
+ }
+ }
+
+ public void testHrefWithNestedParamsWarnsInDevMode() throws Exception {
+ setDevMode(true);
+ tag.setHref("/do-it.action");
+
+ try (LogCapture logs = new LogCapture(Anchor.class)) {
+ renderWithParam("id", "%{'1'}");
+
+ assertEquals(wrapWithAnchor("/do-it.action"), writer.toString());
+ assertEquals(1, logs.messages().size());
+ assertTrue(logs.messages().get(0),
logs.messages().get(0).contains("[id]"));
+ }
+ }
+
+ public void testValueWithNestedParamsDoesNotWarnInDevMode() throws
Exception {
+ setDevMode(true);
+ tag.setValue("/do-it.action");
+
+ try (LogCapture logs = new LogCapture(Anchor.class)) {
+ renderWithParam("id", "%{'1'}");
+
+ assertEquals(wrapWithAnchor("/do-it.action?id=1"),
writer.toString());
+ assertTrue(logs.messages().toString(), logs.messages().isEmpty());
+ }
+ }
+
+ private void renderWithParam(String name, String value) throws
JspException {
+ ParamTag param = new ParamTag();
+ param.setPageContext(pageContext);
+ param.setName(name);
+ param.setValue(value);
+
+ tag.doStartTag();
+ param.doStartTag();
+ param.doEndTag();
+ tag.doEndTag();
+ }
+
}