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 6bda43f209..9e7e09fc7a 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 @@ * *
* 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. *
* * @@ -46,7 +47,7 @@ * *
*
- * <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 @@ protected void evaluateExtraParams() {
if (href != null) {
addParameter("href", ensureAttributeSafelyNotEscaped(findString(href)));
+ if (devMode && !urlParameters.isEmpty()) {
+ LOG.warn("Nested params {} are ignored because 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 UrlProvider getUrlProvider() {
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 48ba23f962..738d0bc369 100644
--- a/core/src/site/resources/tags/a-attributes.html
+++ b/core/src/site/resources/tags/a-attributes.html
@@ -123,7 +123,7 @@
false
String
- The URL.
+ The URL. Nested param tags are not applied, use value or action to build a URL with params
id
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 7bf07bd686..1b9047a2b8 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 @@ protected void setUp() throws Exception {
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();
+ }
+
}