You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2022/11/11 08:19:38 UTC

[struts] branch WW-5260-global-submit-unchecked created (now 279cef1db)

This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a change to branch WW-5260-global-submit-unchecked
in repository https://gitbox.apache.org/repos/asf/struts.git


      at 279cef1db WW-5260 Introduces a constant to set submitUnchecked attribute of checkbox tag globally

This branch includes the following new commits:

     new 279cef1db WW-5260 Introduces a constant to set submitUnchecked attribute of checkbox tag globally

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[struts] 01/01: WW-5260 Introduces a constant to set submitUnchecked attribute of checkbox tag globally

Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5260-global-submit-unchecked
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 279cef1db5070d844b3b812f62f180c6cce732e6
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Fri Nov 11 09:19:28 2022 +0100

    WW-5260 Introduces a constant to set submitUnchecked attribute of checkbox tag globally
---
 .../java/org/apache/struts2/StrutsConstants.java   |  5 +-
 .../org/apache/struts2/components/Checkbox.java    | 37 +++++++----
 .../main/resources/template/simple/checkbox.ftl    |  6 +-
 .../site/resources/tags/checkbox-attributes.html   |  2 +-
 .../apache/struts2/views/jsp/ui/CheckboxTest.java  | 71 ++++++++++++++++------
 .../resources/struts-checkbox-submit-unchecked.xml | 31 ++++++++++
 6 files changed, 116 insertions(+), 36 deletions(-)

diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java
index b7dec53b2..c75ff3d54 100644
--- a/core/src/main/java/org/apache/struts2/StrutsConstants.java
+++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java
@@ -379,7 +379,7 @@ public final class StrutsConstants {
     public static final String STRUTS_CONVERTER_FILE_PROCESSOR = "struts.converter.file.processor";
     public static final String STRUTS_CONVERTER_ANNOTATION_PROCESSOR = "struts.converter.annotation.processor";
     public static final String STRUTS_CONVERTER_CREATOR = "struts.converter.creator";
-    public static final String STRUTS_CONVERTER_HOLDER = "struts..converter.holder";
+    public static final String STRUTS_CONVERTER_HOLDER = "struts.converter.holder";
 
     public static final String STRUTS_EXPRESSION_PARSER = "struts.expression.parser";
 
@@ -462,4 +462,7 @@ public final class StrutsConstants {
     public static final String STRUTS_URL_QUERY_STRING_PARSER = "struts.url.queryStringParser";
     public static final String STRUTS_URL_ENCODER = "struts.url.encoder";
     public static final String STRUTS_URL_DECODER = "struts.url.decoder";
+
+    /** A global flag to set property {@link org.apache.struts2.components.Checkbox#setSubmitUnchecked(String)} */
+    public static final String STRUTS_UI_CHECKBOX_SUBMIT_UNCHECKED = "struts.ui.checkbox.submitUnchecked";
 }
diff --git a/core/src/main/java/org/apache/struts2/components/Checkbox.java b/core/src/main/java/org/apache/struts2/components/Checkbox.java
index 81ea73fa7..77733140b 100644
--- a/core/src/main/java/org/apache/struts2/components/Checkbox.java
+++ b/core/src/main/java/org/apache/struts2/components/Checkbox.java
@@ -18,13 +18,14 @@
  */
 package org.apache.struts2.components;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.struts2.StrutsConstants;
 import org.apache.struts2.views.annotations.StrutsTag;
 import org.apache.struts2.views.annotations.StrutsTagAttribute;
 
-import com.opensymphony.xwork2.util.ValueStack;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
 /**
  * <!-- START SNIPPET: javadoc -->
@@ -46,16 +47,17 @@ import com.opensymphony.xwork2.util.ValueStack;
  *
  * <!-- END SNIPPET: example -->
  * </pre>
- *
  */
 @StrutsTag(
-    name="checkbox",
-    tldTagClass="org.apache.struts2.views.jsp.ui.CheckboxTag",
-    description="Render a checkbox input field",
-    allowDynamicAttributes=true)
+    name = "checkbox",
+    tldTagClass = "org.apache.struts2.views.jsp.ui.CheckboxTag",
+    description = "Render a checkbox input field",
+    allowDynamicAttributes = true)
 public class Checkbox extends UIBean {
     final public static String TEMPLATE = "checkbox";
 
+    private String submitUncheckedGlobal;
+
     protected String fieldValue;
     protected String submitUnchecked;
 
@@ -77,27 +79,36 @@ public class Checkbox extends UIBean {
         if (submitUnchecked != null) {
             Object parsedValue = findValue(submitUnchecked, Boolean.class);
             addParameter("submitUnchecked", parsedValue == null ? Boolean.valueOf(submitUnchecked) : parsedValue);
+        } else if (submitUncheckedGlobal != null) {
+            addParameter("submitUnchecked", Boolean.parseBoolean(submitUncheckedGlobal));
         } else {
             addParameter("submitUnchecked", false);
         }
     }
 
-    protected Class getValueClassType() {
+    protected Class<?> getValueClassType() {
         return Boolean.class; // for checkboxes, everything needs to end up as a Boolean
     }
 
-    @StrutsTagAttribute(description="The actual HTML value attribute of the checkbox.", defaultValue="true")
+    @Inject(value = StrutsConstants.STRUTS_UI_CHECKBOX_SUBMIT_UNCHECKED, required = false)
+    public void setSubmitUncheckedGlobal(String submitUncheckedGlobal) {
+        this.submitUncheckedGlobal = submitUncheckedGlobal;
+    }
+
+    @StrutsTagAttribute(description = "The actual HTML value attribute of the checkbox.", defaultValue = "true")
     public void setFieldValue(String fieldValue) {
         this.fieldValue = fieldValue;
     }
 
-    @StrutsTagAttribute(description="If set to true, unchecked elements will be submitted with the form.", type="Boolean", defaultValue="false")
+    @StrutsTagAttribute(description = "If set to true, unchecked elements will be submitted with the form. " +
+        "Since Struts 6.1.1 you can use a constant \"" + StrutsConstants.STRUTS_UI_CHECKBOX_SUBMIT_UNCHECKED + "\" to set this attribute globally",
+        type = "Boolean", defaultValue = "false")
     public void setSubmitUnchecked(String submitUnchecked) {
         this.submitUnchecked = submitUnchecked;
     }
 
     @Override
-    @StrutsTagAttribute(description="Define label position of form element (top/left), also 'right' is supported when using 'xhtml' theme")
+    @StrutsTagAttribute(description = "Define label position of form element (top/left), also 'right' is supported when using 'xhtml' theme")
     public void setLabelPosition(String labelPosition) {
         super.setLabelPosition(labelPosition);
     }
diff --git a/core/src/main/resources/template/simple/checkbox.ftl b/core/src/main/resources/template/simple/checkbox.ftl
index a344e6d30..af563f4b5 100644
--- a/core/src/main/resources/template/simple/checkbox.ftl
+++ b/core/src/main/resources/template/simple/checkbox.ftl
@@ -38,11 +38,11 @@
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
-/>
+/><#rt/>
 <#if parameters.submitUnchecked!false>
 <input type="hidden" id="__checkbox_${parameters.id}" name="__checkbox_${parameters.name}" value="${parameters.fieldValue}"<#rt/>
 <#if parameters.disabled!false>
  disabled="disabled"<#rt/>
 </#if>
- />
-</#if><#rt/>
+ /><#rt/>
+</#if>
diff --git a/core/src/site/resources/tags/checkbox-attributes.html b/core/src/site/resources/tags/checkbox-attributes.html
index de448af92..ffc6ab1f8 100644
--- a/core/src/site/resources/tags/checkbox-attributes.html
+++ b/core/src/site/resources/tags/checkbox-attributes.html
@@ -283,7 +283,7 @@
         <td class="tag-attribute">false</td>
         <td class="tag-attribute">false</td>
         <td class="tag-attribute">Boolean</td>
-        <td class="tag-attribute">If set to true, unchecked elements will be submitted with the form.</td>
+        <td class="tag-attribute">If set to true, unchecked elements will be submitted with the form. Since Struts 6.1.1 you can use a constant "struts.ui.checkbox.submitUnchecked" to set this property globally</td>
     </tr>
     <tr>
         <td class="tag-attribute">tabindex</td>
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java
index 5f35b8acd..137b3db21 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java
@@ -18,11 +18,21 @@
  */
 package org.apache.struts2.views.jsp.ui;
 
-import java.util.Map;
-
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.config.ConfigurationProvider;
+import com.opensymphony.xwork2.inject.ContainerBuilder;
+import com.opensymphony.xwork2.test.StubConfigurationProvider;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.location.LocatableProperties;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsConstants;
 import org.apache.struts2.TestAction;
 import org.apache.struts2.views.jsp.AbstractUITagTest;
 
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
 public class CheckboxTest extends AbstractUITagTest {
 
     /**
@@ -31,7 +41,7 @@ public class CheckboxTest extends AbstractUITagTest {
      * String, String[])} as properties to verify.<br> This implementation extends testdata from AbstractUITag.
      *
      * @return A Map of PropertyHolders values bound to {@link org.apache.struts2.views.jsp.AbstractUITagTest.PropertyHolder#getName()}
-     *         as key.
+     * as key.
      */
     @Override
     protected Map<String, PropertyHolder> initializedGenericTagTestProperties() {
@@ -73,7 +83,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testChecked_clearTagStateSet() throws Exception {
@@ -102,7 +112,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testCheckedWithTopLabelPosition() throws Exception {
@@ -129,10 +139,10 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
-    public void testCheckedWithTopLabelPosition_clearTagStateSet()  throws Exception {
+    public void testCheckedWithTopLabelPosition_clearTagStateSet() throws Exception {
         TestAction testAction = (TestAction) action;
         testAction.setFoo("true");
 
@@ -159,7 +169,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testCheckedWithLeftLabelPosition() throws Exception {
@@ -186,7 +196,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testCheckedWithLeftLabelPosition_clearTagStateSet() throws Exception {
@@ -216,7 +226,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testCheckedWithError() throws Exception {
@@ -245,7 +255,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testCheckedWithError_clearTagStateSet() throws Exception {
@@ -277,7 +287,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testCheckedWithErrorStyle() throws Exception {
@@ -306,7 +316,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testCheckedWithErrorStyle_clearTagStateSet() throws Exception {
@@ -338,7 +348,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testUnchecked() throws Exception {
@@ -362,7 +372,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testUnchecked_clearTagStateSet() throws Exception {
@@ -389,7 +399,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testDisabled() throws Exception {
@@ -414,7 +424,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertFalse("Tag state after doEndTag() under default tag clear state is equal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testDisabled_clearTagStateSet() throws Exception {
@@ -442,7 +452,7 @@ public class CheckboxTest extends AbstractUITagTest {
         freshTag.setPageContext(pageContext);
         assertTrue("Tag state after doEndTag() and explicit tag state clearing is inequal to new Tag with pageContext/parent set.  " +
                 "May indicate that clearTagStateForTagPoolingServers() calls are not working properly.",
-                strutsBodyTagsAreReflectionEqual(tag, freshTag));
+            strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
     public void testSubmitUncheckedAsFalse() throws Exception {
@@ -487,4 +497,29 @@ public class CheckboxTest extends AbstractUITagTest {
         verify(CheckboxTag.class.getResource("Checkbox-8.txt"));
     }
 
+    public void testSubmitUncheckedGlobalAsTrue() throws Exception {
+        initDispatcherWithConfigs("struts-default.xml, struts-checkbox-submit-unchecked.xml");
+        String submitUnchecked = container.getInstance(String.class, StrutsConstants.STRUTS_UI_CHECKBOX_SUBMIT_UNCHECKED);
+        assertEquals("true", submitUnchecked);
+
+        createMocks();
+
+        TestAction testAction = (TestAction) action;
+        testAction.setFoo("true");
+
+        CheckboxTag tag = new CheckboxTag();
+        tag.setPageContext(pageContext);
+        tag.setLabel("mylabel");
+        tag.setName("foo");
+        tag.setFieldValue("baz");
+        // tag.setSubmitUnchecked("true"); - value should be injected by container
+        tag.setTitle("mytitle");
+        tag.setDisabled("true");
+
+        tag.doStartTag();
+        tag.doEndTag();
+
+        verify(CheckboxTag.class.getResource("Checkbox-8.txt"));
+    }
+
 }
diff --git a/core/src/test/resources/struts-checkbox-submit-unchecked.xml b/core/src/test/resources/struts-checkbox-submit-unchecked.xml
new file mode 100644
index 000000000..d94dde62f
--- /dev/null
+++ b/core/src/test/resources/struts-checkbox-submit-unchecked.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+-->
+<!DOCTYPE struts PUBLIC
+        "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN"
+        "https://struts.apache.org/dtds/struts-6.0.dtd">
+<struts>
+    <constant name="struts.ui.checkbox.submitUnchecked" value="true"/>
+
+    <package name="default" extends="struts-default">
+    </package>
+
+</struts>