[ 
https://issues.apache.org/jira/browse/WW-685?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16401905#comment-16401905
 ] 

ASF GitHub Bot commented on WW-685:
-----------------------------------

lukaszlenart closed pull request #215: WW-685 Add generic type conversion error 
message
URL: https://github.com/apache/struts/pull/215
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionContext.java 
b/core/src/main/java/com/opensymphony/xwork2/ActionContext.java
index 4e4367fcb..34198d1fa 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ActionContext.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ActionContext.java
@@ -18,6 +18,7 @@
  */
 package com.opensymphony.xwork2;
 
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
 import com.opensymphony.xwork2.inject.Container;
 import com.opensymphony.xwork2.util.ValueStack;
 import org.apache.struts2.dispatcher.HttpParameters;
@@ -192,7 +193,7 @@ public void setContextMap(Map<String, Object> contextMap) {
      *
      * @param conversionErrors a Map of errors which occurred when executing 
the action.
      */
-    public void setConversionErrors(Map<String, Object> conversionErrors) {
+    public void setConversionErrors(Map<String, ConversionData> 
conversionErrors) {
         put(CONVERSION_ERRORS, conversionErrors);
     }
 
@@ -202,8 +203,8 @@ public void setConversionErrors(Map<String, Object> 
conversionErrors) {
      * @return the map of conversion errors which occurred when executing the 
action or an empty map if
      *         there were no errors.
      */
-    public Map<String, Object> getConversionErrors() {
-        Map<String, Object> errors = (Map) get(CONVERSION_ERRORS);
+    public Map<String, ConversionData> getConversionErrors() {
+        Map<String, ConversionData> errors = (Map) get(CONVERSION_ERRORS);
 
         if (errors == null) {
             errors = new HashMap<>();
diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java 
b/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java
index 8e57f6d45..a1ef00e47 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java
@@ -18,6 +18,7 @@
  */
 package com.opensymphony.xwork2;
 
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
 import com.opensymphony.xwork2.inject.Container;
 import com.opensymphony.xwork2.inject.Inject;
 import com.opensymphony.xwork2.interceptor.ValidationAware;
@@ -131,9 +132,9 @@ public String getText(String key, String defaultValue, 
String[] args, ValueStack
      * @return formatted expr with format specified by key
      */
     public String getFormatted(String key, String expr) {
-        Map<String, Object> conversionErrors = 
ActionContext.getContext().getConversionErrors();
+        Map<String, ConversionData> conversionErrors = 
ActionContext.getContext().getConversionErrors();
         if (conversionErrors.containsKey(expr)) {
-            String[] vals = (String[]) conversionErrors.get(expr);
+            String[] vals = (String[]) conversionErrors.get(expr).getValue();
             return vals[0];
         } else {
             final ValueStack valueStack = 
ActionContext.getContext().getValueStack();
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/ConversionData.java
 
b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/ConversionData.java
new file mode 100644
index 000000000..2c3dd5d5f
--- /dev/null
+++ 
b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/ConversionData.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package com.opensymphony.xwork2.conversion.impl;
+
+public class ConversionData {
+    private Object value;
+    private Class toClass;
+
+    public ConversionData() {
+    }
+
+    public ConversionData(Object value, Class toClass) {
+        super();
+        this.value = value;
+        this.toClass = toClass;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+    public void setValue(Object value) {
+        this.value = value;
+    }
+    public Class getToClass() {
+        return toClass;
+    }
+    public void setToClass(Class toClass) {
+        this.toClass = toClass;
+    }
+}
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/XWorkConverter.java
 
b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/XWorkConverter.java
index 07358887b..96405ff08 100644
--- 
a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/XWorkConverter.java
+++ 
b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/XWorkConverter.java
@@ -189,7 +189,7 @@ public void setTypeConverterHolder(TypeConverterHolder 
converterHolder) {
         this.converterHolder = converterHolder;
     }
 
-    public static String getConversionErrorMessage(String propertyName, 
ValueStack stack) {
+    public static String getConversionErrorMessage(String propertyName, Class 
toClass, ValueStack stack) {
         LocalizedTextProvider localizedTextProvider = 
ActionContext.getContext().getContainer().getInstance(LocalizedTextProvider.class);
         String defaultMessage = 
localizedTextProvider.findDefaultText("xwork.default.invalid.fieldvalue",
                 ActionContext.getContext().getLocale(),
@@ -201,9 +201,15 @@ public static String getConversionErrorMessage(String 
propertyName, ValueStack s
 
         propertyName = removeAllIndexesInPropertyName(propertyName);
 
-        String getTextExpression = "getText('" + 
CONVERSION_ERROR_PROPERTY_PREFIX + propertyName + "','" + defaultMessage + "')";
+        String prefixedPropertyName = CONVERSION_ERROR_PROPERTY_PREFIX + 
propertyName;
+        String getTextExpression = "getText('" + prefixedPropertyName + "')";
         String message = (String) stack.findValue(getTextExpression);
 
+        if (message == null || prefixedPropertyName.equals(message)) {
+            getTextExpression = "getText('" + CONVERSION_ERROR_PROPERTY_PREFIX 
+ toClass.getName() + "','" + defaultMessage + "')";
+            message = (String) stack.findValue(getTextExpression);
+        }
+
         if (message == null) {
             message = defaultMessage;
         } else {
@@ -308,7 +314,7 @@ public Object convertValue(Map<String, Object> context, 
Object target, Member me
                 return tc.convertValue(context, target, member, property, 
value, toClass);
             } catch (Exception e) {
                 LOG.debug("Unable to convert value using type converter [{}]", 
tc.getClass().getName(), e);
-                handleConversionException(context, property, value, target);
+                handleConversionException(context, property, value, target, 
toClass);
 
                 return TypeConverter.NO_CONVERSION_POSSIBLE;
             }
@@ -320,7 +326,7 @@ public Object convertValue(Map<String, Object> context, 
Object target, Member me
                 return defaultTypeConverter.convertValue(context, target, 
member, property, value, toClass);
             } catch (Exception e) {
                 LOG.debug("Unable to convert value using type converter [{}]", 
defaultTypeConverter.getClass().getName(), e);
-                handleConversionException(context, property, value, target);
+                handleConversionException(context, property, value, target, 
toClass);
 
                 return TypeConverter.NO_CONVERSION_POSSIBLE;
             }
@@ -330,7 +336,7 @@ public Object convertValue(Map<String, Object> context, 
Object target, Member me
                 return super.convertValue(value, toClass);
             } catch (Exception e) {
                 LOG.debug("Unable to convert value using type converter [{}]", 
super.getClass().getName(), e);
-                handleConversionException(context, property, value, target);
+                handleConversionException(context, property, value, target, 
toClass);
 
                 return TypeConverter.NO_CONVERSION_POSSIBLE;
             }
@@ -426,7 +432,7 @@ protected Object getConverter(Class clazz, String property) 
{
         return null;
     }
 
-    protected void handleConversionException(Map<String, Object> context, 
String property, Object value, Object object) {
+    protected void handleConversionException(Map<String, Object> context, 
String property, Object value, Object object, Class toClass) {
         if (context != null && 
(Boolean.TRUE.equals(context.get(REPORT_CONVERSION_ERRORS)))) {
             String realProperty = property;
             String fullName = (String) 
context.get(CONVERSION_PROPERTY_FULLNAME);
@@ -435,14 +441,14 @@ protected void handleConversionException(Map<String, 
Object> context, String pro
                 realProperty = fullName;
             }
 
-            Map<String, Object> conversionErrors = (Map<String, Object>) 
context.get(ActionContext.CONVERSION_ERRORS);
+            Map<String, ConversionData> conversionErrors = (Map<String, 
ConversionData>) context.get(ActionContext.CONVERSION_ERRORS);
 
             if (conversionErrors == null) {
                 conversionErrors = new HashMap<>();
                 context.put(ActionContext.CONVERSION_ERRORS, conversionErrors);
             }
 
-            conversionErrors.put(realProperty, value);
+            conversionErrors.put(realProperty, new ConversionData(value, 
toClass));
         }
     }
 
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.java
 
b/core/src/main/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.java
index 2c2113b7e..f2713800f 100644
--- 
a/core/src/main/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.java
+++ 
b/core/src/main/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.java
@@ -20,6 +20,7 @@
 
 import com.opensymphony.xwork2.ActionContext;
 import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
 import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
 import com.opensymphony.xwork2.util.ValueStack;
 import org.apache.commons.lang3.StringEscapeUtils;
@@ -100,17 +101,17 @@ protected String escape(Object value) {
     public String doIntercept(ActionInvocation invocation) throws Exception {
 
         ActionContext invocationContext = invocation.getInvocationContext();
-        Map<String, Object> conversionErrors = 
invocationContext.getConversionErrors();
+        Map<String, ConversionData> conversionErrors = 
invocationContext.getConversionErrors();
         ValueStack stack = invocationContext.getValueStack();
 
         HashMap<Object, Object> fakie = null;
 
-        for (Map.Entry<String, Object> entry : conversionErrors.entrySet()) {
+        for (Map.Entry<String, ConversionData> entry : 
conversionErrors.entrySet()) {
             String propertyName = entry.getKey();
-            Object value = entry.getValue();
+            ConversionData conversionData = entry.getValue();
 
-            if (shouldAddError(propertyName, value)) {
-                String message = 
XWorkConverter.getConversionErrorMessage(propertyName, stack);
+            if (shouldAddError(propertyName, conversionData.getValue())) {
+                String message = 
XWorkConverter.getConversionErrorMessage(propertyName, 
conversionData.getToClass(), stack);
 
                 Object action = invocation.getAction();
                 if (action instanceof ValidationAware) {
@@ -122,7 +123,7 @@ public String doIntercept(ActionInvocation invocation) 
throws Exception {
                     fakie = new HashMap<>();
                 }
 
-                fakie.put(propertyName, getOverrideExpr(invocation, value));
+                fakie.put(propertyName, getOverrideExpr(invocation, 
conversionData.getValue()));
             }
         }
 
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/validator/validators/ConversionErrorFieldValidator.java
 
b/core/src/main/java/com/opensymphony/xwork2/validator/validators/ConversionErrorFieldValidator.java
index d24e0269f..3fcf02356 100644
--- 
a/core/src/main/java/com/opensymphony/xwork2/validator/validators/ConversionErrorFieldValidator.java
+++ 
b/core/src/main/java/com/opensymphony/xwork2/validator/validators/ConversionErrorFieldValidator.java
@@ -19,6 +19,7 @@
 package com.opensymphony.xwork2.validator.validators;
 
 import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
 import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
 import com.opensymphony.xwork2.validator.ValidationException;
 import org.apache.commons.lang3.StringUtils;
@@ -70,11 +71,11 @@ public void doValidate(Object object) throws 
ValidationException {
         String fieldName = getFieldName();
         String fullFieldName = 
getValidatorContext().getFullFieldName(fieldName);
         ActionContext context = ActionContext.getContext();
-        Map<String, Object> conversionErrors = context.getConversionErrors();
+        Map<String, ConversionData> conversionErrors = 
context.getConversionErrors();
         
         if (conversionErrors.containsKey(fullFieldName)) {
             if (StringUtils.isBlank(defaultMessage)) {
-                defaultMessage = 
XWorkConverter.getConversionErrorMessage(fullFieldName, 
context.getValueStack());
+                defaultMessage = 
XWorkConverter.getConversionErrorMessage(fullFieldName, 
conversionErrors.get(fullFieldName).getToClass(), context.getValueStack());
             }
             
             addFieldError(fieldName, object);
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/validator/validators/RepopulateConversionErrorFieldValidatorSupport.java
 
b/core/src/main/java/com/opensymphony/xwork2/validator/validators/RepopulateConversionErrorFieldValidatorSupport.java
index 30799215f..501a966b4 100644
--- 
a/core/src/main/java/com/opensymphony/xwork2/validator/validators/RepopulateConversionErrorFieldValidatorSupport.java
+++ 
b/core/src/main/java/com/opensymphony/xwork2/validator/validators/RepopulateConversionErrorFieldValidatorSupport.java
@@ -20,6 +20,7 @@
 
 import com.opensymphony.xwork2.ActionContext;
 import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
 import com.opensymphony.xwork2.interceptor.PreResultListener;
 import com.opensymphony.xwork2.util.ValueStack;
 import com.opensymphony.xwork2.validator.ValidationException;
@@ -155,12 +156,12 @@ public void validate(Object object) throws 
ValidationException {
     public void repopulateField(Object object) throws ValidationException {
 
         ActionInvocation invocation = 
ActionContext.getContext().getActionInvocation();
-        Map<String, Object> conversionErrors = 
ActionContext.getContext().getConversionErrors();
+        Map<String, ConversionData> conversionErrors = 
ActionContext.getContext().getConversionErrors();
 
         String fieldName = getFieldName();
         String fullFieldName = 
getValidatorContext().getFullFieldName(fieldName);
         if (conversionErrors.containsKey(fullFieldName)) {
-            Object value = conversionErrors.get(fullFieldName);
+            Object value = conversionErrors.get(fullFieldName).getValue();
 
             final Map<Object, Object> fakeParams = new LinkedHashMap<Object, 
Object>();
             boolean doExprOverride = false;
diff --git a/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java 
b/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java
index 600c61994..ed8f39b31 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ActionContextTest.java
@@ -18,6 +18,7 @@
  */
 package com.opensymphony.xwork2;
 
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
 import com.opensymphony.xwork2.util.ValueStack;
 import com.opensymphony.xwork2.util.ValueStackFactory;
 import org.apache.struts2.dispatcher.HttpParameters;
@@ -97,11 +98,11 @@ public void testParameters() {
     }
 
     public void testConversionErrors() {
-        Map<String, Object> errors = context.getConversionErrors();
+        Map<String, ConversionData> errors = context.getConversionErrors();
         assertNotNull(errors);
         assertEquals(0, errors.size());
 
-        Map<String, Object> errors2 = new HashMap<>();
+        Map<String, ConversionData> errors2 = new HashMap<>();
         context.setConversionErrors(errors);
         assertEquals(errors2, context.getConversionErrors());
     }
diff --git a/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java 
b/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java
index 26999f1b5..f712ee74b 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ActionSupportTest.java
@@ -18,6 +18,7 @@
  */
 package com.opensymphony.xwork2;
 
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
 import com.opensymphony.xwork2.util.ValueStack;
 
 import java.util.*;
@@ -303,7 +304,7 @@ public void testFormattingSupport() throws Exception {
     }
 
     public void testFormattingSupportWithConversionError() throws Exception {
-        ActionContext.getContext().getConversionErrors().put("val", new 
String[]{"4567def"});
+        ActionContext.getContext().getConversionErrors().put("val", new 
ConversionData(new String[]{"4567def"}, Double.class));
         ActionContext.getContext().setLocale(new Locale("da"));
         MyActionSupport mas = new MyActionSupport();
         container.inject(mas);
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/AnnotationXWorkConverterTest.java
 
b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/AnnotationXWorkConverterTest.java
index eb1b0f6d3..d75c6dd5b 100644
--- 
a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/AnnotationXWorkConverterTest.java
+++ 
b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/AnnotationXWorkConverterTest.java
@@ -112,10 +112,10 @@ public void 
testFieldErrorMessageAddedForComplexProperty() {
         assertEquals("Conversion should have failed.", 
OgnlRuntime.NoConversionPossible, converter.convertValue(ognlStackContext, 
action.getBean(), null, "birth", value, Date.class));
         stack.pop();
 
-        Map conversionErrors = (Map) 
stack.getContext().get(ActionContext.CONVERSION_ERRORS);
+        Map<String, ConversionData> conversionErrors = (Map<String, 
ConversionData>) stack.getContext().get(ActionContext.CONVERSION_ERRORS);
         assertNotNull(conversionErrors);
         assertTrue(conversionErrors.size() == 1);
-        assertEquals(value, conversionErrors.get("bean.birth"));
+        assertEquals(value, conversionErrors.get("bean.birth").getValue());
     }
 
     public void testFieldErrorMessageAddedWhenConversionFails() {
@@ -132,11 +132,11 @@ public void 
testFieldErrorMessageAddedWhenConversionFails() {
         assertEquals("Conversion should have failed.", 
OgnlRuntime.NoConversionPossible, converter.convertValue(ognlStackContext, 
action, null, "date", value, Date.class));
         stack.pop();
 
-        Map conversionErrors = (Map) 
ognlStackContext.get(ActionContext.CONVERSION_ERRORS);
+        Map<String, ConversionData> conversionErrors = (Map<String, 
ConversionData>) ognlStackContext.get(ActionContext.CONVERSION_ERRORS);
         assertNotNull(conversionErrors);
         assertEquals(1, conversionErrors.size());
         assertNotNull(conversionErrors.get("date"));
-        assertEquals(value, conversionErrors.get("date"));
+        assertEquals(value, conversionErrors.get("date").getValue());
     }
 
     public void testFieldErrorMessageAddedWhenConversionFailsOnModelDriven() {
@@ -153,11 +153,11 @@ public void 
testFieldErrorMessageAddedWhenConversionFailsOnModelDriven() {
         stack.pop();
         stack.pop();
 
-        Map conversionErrors = (Map) 
ognlStackContext.get(ActionContext.CONVERSION_ERRORS);
+        Map<String, ConversionData> conversionErrors = (Map<String, 
ConversionData>) ognlStackContext.get(ActionContext.CONVERSION_ERRORS);
         assertNotNull(conversionErrors);
         assertEquals(1, conversionErrors.size());
         assertNotNull(conversionErrors.get("birth"));
-        assertEquals(value, conversionErrors.get("birth"));
+        assertEquals(value, conversionErrors.get("birth").getValue());
     }
 
     public void testFindConversionErrorMessage() {
@@ -168,11 +168,11 @@ public void testFindConversionErrorMessage() {
         stack.push(action);
         stack.push(action.getModel());
 
-        String message = XWorkConverter.getConversionErrorMessage("birth", 
stack);
+        String message = XWorkConverter.getConversionErrorMessage("birth", 
Integer.class, stack);
         assertNotNull(message);
         assertEquals("Invalid date for birth.", message);
 
-        message = XWorkConverter.getConversionErrorMessage("foo", stack);
+        message = XWorkConverter.getConversionErrorMessage("foo", 
Integer.class, stack);
         assertNotNull(message);
         assertEquals("Invalid field value for field \"foo\".", message);
     }
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
 
b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
index 1c4faa3e8..5982cb4a2 100644
--- 
a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
+++ 
b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
@@ -135,10 +135,10 @@ public void 
testFieldErrorMessageAddedForComplexProperty() {
         assertEquals("Conversion should have failed.", 
OgnlRuntime.NoConversionPossible, converter.convertValue(ognlStackContext, 
action.getBean(), null, "birth", value, Date.class));
         stack.pop();
 
-        Map conversionErrors = (Map) 
stack.getContext().get(ActionContext.CONVERSION_ERRORS);
+        Map<String, ConversionData> conversionErrors = (Map<String, 
ConversionData>) stack.getContext().get(ActionContext.CONVERSION_ERRORS);
         assertNotNull(conversionErrors);
         assertTrue(conversionErrors.size() == 1);
-        assertEquals(value, conversionErrors.get("bean.birth"));
+        assertEquals(value, conversionErrors.get("bean.birth").getValue());
     }
 
     public void testFieldErrorMessageAddedWhenConversionFails() {
@@ -154,11 +154,11 @@ public void 
testFieldErrorMessageAddedWhenConversionFails() {
         assertEquals("Conversion should have failed.", 
OgnlRuntime.NoConversionPossible, converter.convertValue(ognlStackContext, 
action, null, "date", value, Date.class));
         stack.pop();
 
-        Map conversionErrors = (Map) 
ognlStackContext.get(ActionContext.CONVERSION_ERRORS);
+        Map<String, ConversionData> conversionErrors = (Map<String, 
ConversionData>) ognlStackContext.get(ActionContext.CONVERSION_ERRORS);
         assertNotNull(conversionErrors);
         assertEquals(1, conversionErrors.size());
         assertNotNull(conversionErrors.get("date"));
-        assertEquals(value, conversionErrors.get("date"));
+        assertEquals(value, conversionErrors.get("date").getValue());
     }
 
     public void testFieldErrorMessageAddedWhenConversionFailsOnModelDriven() {
@@ -174,11 +174,11 @@ public void 
testFieldErrorMessageAddedWhenConversionFailsOnModelDriven() {
         stack.pop();
         stack.pop();
 
-        Map conversionErrors = (Map) 
ognlStackContext.get(ActionContext.CONVERSION_ERRORS);
+        Map<String, ConversionData> conversionErrors = (Map<String, 
ConversionData>) ognlStackContext.get(ActionContext.CONVERSION_ERRORS);
         assertNotNull(conversionErrors);
         assertEquals(1, conversionErrors.size());
         assertNotNull(conversionErrors.get("birth"));
-        assertEquals(value, conversionErrors.get("birth"));
+        assertEquals(value, conversionErrors.get("birth").getValue());
     }
 
     public void testDateStrictConversion() throws Exception {
@@ -208,11 +208,11 @@ public void testFindConversionErrorMessage() {
         stack.push(action);
         stack.push(action.getModel());
 
-        String message = XWorkConverter.getConversionErrorMessage("birth", 
stack);
+        String message = XWorkConverter.getConversionErrorMessage("birth", 
Integer.class, stack);
         assertNotNull(message);
         assertEquals("Invalid date for birth.", message);
 
-        message = XWorkConverter.getConversionErrorMessage("foo", stack);
+        message = XWorkConverter.getConversionErrorMessage("foo", 
Integer.class, stack);
         assertNotNull(message);
         assertEquals("Invalid field value for field \"foo\".", message);
     }
@@ -234,6 +234,83 @@ public void testFindConversionMappingForInterface() {
         assertEquals(value, b.getTitle() + ":" + b.getSomethingElse());
     }
 
+    public void testDefaultFieldConversionErrorMessage() {
+        SimpleAction action = new SimpleAction();
+        container.inject(action);
+
+        stack.push(action);
+
+        String message = XWorkConverter.getConversionErrorMessage("baz", 
int.class, stack);
+        assertNotNull(message);
+        assertEquals("Invalid field value for field \"baz\".", message);
+    }
+
+    public void testCustomFieldConversionErrorMessage() {
+        SimpleAction action = new SimpleAction();
+        container.inject(action);
+
+        stack.push(action);
+
+        String message = XWorkConverter.getConversionErrorMessage("foo", 
int.class, stack);
+        assertNotNull(message);
+        assertEquals("Custom error message for foo.", message);
+    }
+
+    public void testCustomPrimitiveConversionErrorMessage() {
+        SimpleAction action = new SimpleAction();
+        container.inject(action);
+
+        stack.push(action);
+
+        String message = 
XWorkConverter.getConversionErrorMessage("percentage", double.class, stack);
+        assertNotNull(message);
+        assertEquals("Custom error message for double.", message);
+    }
+
+    public void testCustomClassConversionErrorMessage() {
+        SimpleAction action = new SimpleAction();
+        container.inject(action);
+
+        stack.push(action);
+
+        String message = XWorkConverter.getConversionErrorMessage("date", 
Date.class, stack);
+        assertNotNull(message);
+        assertEquals("Custom error message for java.util.Date.", message);
+    }
+
+    public void testDefaultIndexedConversionErrorMessage() {
+        SimpleAction action = new SimpleAction();
+        container.inject(action);
+
+        stack.push(action);
+
+        String message = 
XWorkConverter.getConversionErrorMessage("beanList[0].name", String.class, 
stack);
+        assertNotNull(message);
+        assertEquals("Invalid field value for field \"beanList[0].name\".", 
message);
+    }
+
+    public void testCustomIndexedFieldConversionErrorMessage() {
+        SimpleAction action = new SimpleAction();
+        container.inject(action);
+
+        stack.push(action);
+
+        String message = 
XWorkConverter.getConversionErrorMessage("beanList[0].count", int.class, stack);
+        assertNotNull(message);
+        assertEquals("Custom error message for beanList.count.", message);
+    }
+
+    public void testCustomIndexedClassConversionErrorMessage() {
+        SimpleAction action = new SimpleAction();
+        container.inject(action);
+
+        stack.push(action);
+
+        String message = 
XWorkConverter.getConversionErrorMessage("beanList[0].birth", Date.class, 
stack);
+        assertNotNull(message);
+        assertEquals("Custom error message for java.util.Date.", message);
+    }
+
     public void testLocalizedDateConversion() throws Exception {
         Date date = new Date(System.currentTimeMillis());
         Locale locale = Locale.GERMANY;
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptorTest.java
 
b/core/src/test/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptorTest.java
index 77d533258..9ed6f5db3 100644
--- 
a/core/src/test/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptorTest.java
+++ 
b/core/src/test/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptorTest.java
@@ -21,6 +21,7 @@
 import com.mockobjects.dynamic.C;
 import com.mockobjects.dynamic.Mock;
 import com.opensymphony.xwork2.*;
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
 import com.opensymphony.xwork2.mock.MockActionInvocation;
 import com.opensymphony.xwork2.util.ValueStack;
 
@@ -38,13 +39,13 @@
     protected ActionContext context;
     protected ActionInvocation invocation;
     protected ConversionErrorInterceptor interceptor;
-    protected Map<String, Object> conversionErrors;
+    protected Map<String, ConversionData> conversionErrors;
     protected Mock mockInvocation;
     protected ValueStack stack;
 
 
     public void testFieldErrorAdded() throws Exception {
-        conversionErrors.put("foo", 123L);
+        conversionErrors.put("foo", new ConversionData(123L, int.class));
 
         SimpleAction action = new SimpleAction();
         mockInvocation.expectAndReturn("getAction", action);
@@ -58,7 +59,7 @@ public void testFieldErrorAdded() throws Exception {
 
     public void testFieldErrorWithMapKeyAdded() throws Exception {
         String fieldName = "foo['1'].intValue";
-        conversionErrors.put(fieldName, "bar");
+        conversionErrors.put(fieldName, new ConversionData("bar", int.class));
         ActionSupport action = new ActionSupport();
         mockInvocation.expectAndReturn("getAction", action);
         stack.push(action);
@@ -70,7 +71,7 @@ public void testFieldErrorWithMapKeyAdded() throws Exception {
     }
 
     public void testWithPreResultListener() throws Exception {
-        conversionErrors.put("foo", "Hello");
+        conversionErrors.put("foo", new ConversionData("Hello", int.class));
 
         ActionContext ac = createActionContext();
         MockActionInvocation mai = createActionInvocation(ac);
@@ -93,7 +94,7 @@ public void testWithPreResultListener() throws Exception {
      * @throws Exception
      */
     public void testWithPreResultListenerAgainstMaliciousCode() throws 
Exception {
-        conversionErrors.put("foo", "\" + #root + \"");
+        conversionErrors.put("foo", new ConversionData("\" + #root + \"", 
int.class));
 
         ActionContext ac = createActionContext();
 
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/validator/ConversionErrorFieldValidatorTest.java
 
b/core/src/test/java/com/opensymphony/xwork2/validator/ConversionErrorFieldValidatorTest.java
index 007b31d79..f36a1aa46 100644
--- 
a/core/src/test/java/com/opensymphony/xwork2/validator/ConversionErrorFieldValidatorTest.java
+++ 
b/core/src/test/java/com/opensymphony/xwork2/validator/ConversionErrorFieldValidatorTest.java
@@ -23,6 +23,7 @@
 import com.opensymphony.xwork2.interceptor.ValidationAware;
 import com.opensymphony.xwork2.ValidationAwareSupport;
 import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
 import com.opensymphony.xwork2.util.ValueStack;
 import 
com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator;
 
@@ -50,8 +51,8 @@ public void setUp() throws Exception {
         ValueStack stack = ActionContext.getContext().getValueStack();
         ActionContext context = new ActionContext(stack.getContext());
 
-        Map<String, Object> conversionErrors = new HashMap<>();
-        conversionErrors.put("foo", "bar");
+        Map<String, ConversionData> conversionErrors = new HashMap<>();
+        conversionErrors.put("foo", new ConversionData("bar", Integer.class));
         context.setConversionErrors(conversionErrors);
         validator = new ConversionErrorFieldValidator();
         validationAware = new ValidationAwareSupport();
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/validator/RepopulateConversionErrorFieldValidatorSupportTest.java
 
b/core/src/test/java/com/opensymphony/xwork2/validator/RepopulateConversionErrorFieldValidatorSupportTest.java
index 889dcc841..be49dcddd 100644
--- 
a/core/src/test/java/com/opensymphony/xwork2/validator/RepopulateConversionErrorFieldValidatorSupportTest.java
+++ 
b/core/src/test/java/com/opensymphony/xwork2/validator/RepopulateConversionErrorFieldValidatorSupportTest.java
@@ -22,6 +22,7 @@
 import com.opensymphony.xwork2.ActionSupport;
 import com.opensymphony.xwork2.TextProviderFactory;
 import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
 import com.opensymphony.xwork2.mock.MockActionInvocation;
 import com.opensymphony.xwork2.util.ValueStack;
 import 
com.opensymphony.xwork2.validator.validators.RepopulateConversionErrorFieldValidatorSupport;
@@ -91,9 +92,9 @@ protected void setUp() throws Exception {
                ActionContext.getContext().setActionInvocation(invocation);
                
                String[] conversionErrorValue = new String[] { "some value" };
-               Map<String, Object> conversionErrors = 
ActionContext.getContext().getConversionErrors();
-               conversionErrors.put("someFieldName", conversionErrorValue);
-               conversionErrors.put("xxxsomeFieldName", conversionErrorValue);
+               Map<String, ConversionData> conversionErrors = 
ActionContext.getContext().getConversionErrors();
+               conversionErrors.put("someFieldName", new 
ConversionData(conversionErrorValue, Integer.class));
+               conversionErrors.put("xxxsomeFieldName", new 
ConversionData(conversionErrorValue, Integer.class));
 
                TextProviderFactory tpf = 
container.getInstance(TextProviderFactory.class);
 
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/validator/VisitorFieldValidatorTest.java
 
b/core/src/test/java/com/opensymphony/xwork2/validator/VisitorFieldValidatorTest.java
index cd66aca2f..62ed2baa2 100644
--- 
a/core/src/test/java/com/opensymphony/xwork2/validator/VisitorFieldValidatorTest.java
+++ 
b/core/src/test/java/com/opensymphony/xwork2/validator/VisitorFieldValidatorTest.java
@@ -20,6 +20,8 @@
 
 import com.opensymphony.xwork2.*;
 import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
+
 import org.easymock.EasyMock;
 
 import java.util.*;
@@ -177,8 +179,8 @@ public void testVisitorChildValidation() throws Exception {
 
     public void testVisitorChildConversionValidation() throws Exception {
         //add conversion error
-        Map<String, Object> conversionErrors = new HashMap<>();
-        conversionErrors.put("bean.child.count", "bar");
+        Map<String, ConversionData> conversionErrors = new HashMap<>();
+        conversionErrors.put("bean.child.count", new ConversionData("bar", 
Integer.class));
         ActionContext.getContext().setConversionErrors(conversionErrors);
 
         validate("visitorChildValidation");
diff --git 
a/core/src/test/java/org/apache/struts2/interceptor/StrutsConversionErrorInterceptorTest.java
 
b/core/src/test/java/org/apache/struts2/interceptor/StrutsConversionErrorInterceptorTest.java
index 6b8c9a670..d7189b868 100644
--- 
a/core/src/test/java/org/apache/struts2/interceptor/StrutsConversionErrorInterceptorTest.java
+++ 
b/core/src/test/java/org/apache/struts2/interceptor/StrutsConversionErrorInterceptorTest.java
@@ -24,13 +24,13 @@
 import com.opensymphony.xwork2.ActionContext;
 import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
 import com.opensymphony.xwork2.util.ValueStack;
 import org.apache.struts2.StrutsInternalTestCase;
 
 import java.util.HashMap;
 import java.util.Map;
 
-
 /**
  * StrutsConversionErrorInterceptorTest
  *
@@ -39,16 +39,16 @@
 
     protected ActionContext context;
     protected ActionInvocation invocation;
-    protected Map<String, Object> conversionErrors;
+    protected Map<String, ConversionData> conversionErrors;
     protected Mock mockInvocation;
     protected ValueStack stack;
     protected StrutsConversionErrorInterceptor interceptor;
 
 
     public void testEmptyValuesDoNotSetFieldErrors() throws Exception {
-        conversionErrors.put("foo", 123L);
-        conversionErrors.put("bar", "");
-        conversionErrors.put("baz", new String[]{""});
+        conversionErrors.put("foo", new ConversionData("bar", Integer.class));
+        conversionErrors.put("bar", new ConversionData("", Integer.class));
+        conversionErrors.put("baz", new ConversionData(new String[]{""}, 
Integer.class));
 
         ActionSupport action = new ActionSupport();
         mockInvocation.expectAndReturn("getAction", action);
@@ -65,7 +65,7 @@ public void testEmptyValuesDoNotSetFieldErrors() throws 
Exception {
     }
 
     public void testFieldErrorAdded() throws Exception {
-        conversionErrors.put("foo", 123L);
+        conversionErrors.put("foo", new ConversionData("bar", Integer.class));
 
         ActionSupport action = new ActionSupport();
         mockInvocation.expectAndReturn("getAction", action);
@@ -84,7 +84,7 @@ protected void setUp() throws Exception {
         invocation = (ActionInvocation) mockInvocation.proxy();
         stack = ActionContext.getContext().getValueStack();
         context = new ActionContext(stack.getContext());
-        conversionErrors = new HashMap<String, Object>();
+        conversionErrors = new HashMap<>();
         context.setConversionErrors(conversionErrors);
         mockInvocation.matchAndReturn("getInvocationContext", context);
         mockInvocation.expectAndReturn("invoke", Action.SUCCESS);
diff --git 
a/core/src/test/resources/com/opensymphony/xwork2/SimpleAction.properties 
b/core/src/test/resources/com/opensymphony/xwork2/SimpleAction.properties
index af92f350b..f4ca339d8 100644
--- a/core/src/test/resources/com/opensymphony/xwork2/SimpleAction.properties
+++ b/core/src/test/resources/com/opensymphony/xwork2/SimpleAction.properties
@@ -19,3 +19,7 @@
 foo.range=Foo Range Message
 baz.range=${getText(fieldName)} must be greater than ${min}
 baz=Baz Field
+invalid.fieldvalue.foo=Custom error message for foo.
+invalid.fieldvalue.double=Custom error message for double.
+invalid.fieldvalue.java.util.Date=Custom error message for java.util.Date.
+invalid.fieldvalue.beanList.count=Custom error message for beanList.count.


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


> Generic error message - Type Conversion Error Handling
> ------------------------------------------------------
>
>                 Key: WW-685
>                 URL: https://issues.apache.org/jira/browse/WW-685
>             Project: Struts 2
>          Issue Type: Improvement
>            Reporter: Ricardo Lecheta
>            Assignee: Aleksandr Mashchenko
>            Priority: Major
>             Fix For: 2.6
>
>
> To change the default message "invalid field value for field "xxx"", 
> you can put this line in the Action.properties
> > invalid.fieldvalue.[propertyName]
> But will be useful if there is a way to do a generic custom message to any 
> type? For example a custom message for Dates, double, boolean, etc:
> > invalid.fieldvalue.For_All_Dates=This is not a valid date.
> I don´t know how to implement it, but could be like this:
> > invalid.fieldvalue.java.lang.Integer=This is not a valid Number.
> > invalid.fieldvalue.java.util.Date=This is not a valid Date.
> -------------
> I tried the following examples, but them doesn´t work:
> invalid.fieldvalue.*=Invalid Date.
>  and
> invalid.fieldvalue.[*]=Invalid Date.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to