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

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

lukaszlenart closed pull request #199:  fix conversion by annotation and WW-4906
URL: https://github.com/apache/struts/pull/199
 
 
   

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/conversion/annotations/TypeConversion.java
 
b/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/TypeConversion.java
index 8039f97bb..6c86d4a6d 100644
--- 
a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/TypeConversion.java
+++ 
b/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/TypeConversion.java
@@ -82,15 +82,15 @@
  * </tr>
  * <tr>
  * <td>converter</td>
- * <td>DEPRECATED: either this or value</td>
+ * <td>either this or value</td>
  * <td>&nbsp;</td>
- * <td>The class name of the TypeConverter to be used as converter.</td>
+ * <td>The class or bean name of the TypeConverter to be used as 
converter.</td>
  * </tr>
  * <tr>
  * <td>converterClass</td>
  * <td>either this or value</td>
- * <td>&nbsp;</td>
- * <td>The class of the TypeConverter to be used as converter. 
XWorkBasicConverter by default.</td>
+ * <td>XWorkBasicConverter</td>
+ * <td>The class of the TypeConverter to be used as converter.</td>
  * </tr>
  * <tr>
  * <td>value</td>
@@ -181,14 +181,13 @@
     ConversionRule rule() default ConversionRule.PROPERTY;
 
     /**
-     * The class of the TypeConverter to be used as converter.
+     * The class or bean name of the TypeConverter to be used as converter.
      *
      * Note: This can not be used with ConversionRule.KEY_PROPERTY!
      *
-     * @return class of the TypeConverter to be used as converter
-     * @deprecated user {@link #converterClass()} instead
+     * @return class or bean name of the TypeConverter to be used as converter
+     * @see {@link #converterClass()}
      */
-    @Deprecated
     String converter() default "";
 
     /**
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionAnnotationProcessor.java
 
b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionAnnotationProcessor.java
index bfe355b3e..8021f3f92 100644
--- 
a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionAnnotationProcessor.java
+++ 
b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionAnnotationProcessor.java
@@ -26,6 +26,7 @@
 import com.opensymphony.xwork2.conversion.annotations.ConversionType;
 import com.opensymphony.xwork2.conversion.annotations.TypeConversion;
 import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.ClassLoaderUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -69,7 +70,7 @@ public void process(Map<String, Object> mapping, 
TypeConversion tc, String key)
                     mapping.put(key, tc.value());
                 }
                 //for properties of classes
-                else if (tc.rule() != ConversionRule.ELEMENT || tc.rule() == 
ConversionRule.KEY || tc.rule() == ConversionRule.COLLECTION) {
+                else if (tc.rule() != ConversionRule.ELEMENT && tc.rule() != 
ConversionRule.KEY && tc.rule() != ConversionRule.COLLECTION) {
                     if (StringUtils.isNoneEmpty(tc.converter())) {
                         mapping.put(key, 
converterCreator.createTypeConverter(tc.converter()));
                     } else {
@@ -80,18 +81,22 @@ else if (tc.rule() != ConversionRule.ELEMENT || tc.rule() 
== ConversionRule.KEY
                 else if (tc.rule() == ConversionRule.KEY) {
                     Class<?> converterClass;
                     if (StringUtils.isNoneEmpty(tc.converter())) {
-                        converterClass = 
Thread.currentThread().getContextClassLoader().loadClass(tc.converter());
-                        //check if the converter is a type converter if it is 
one
-                        //then just put it in the map as is. Otherwise
-                        //put a value in for the type converter of the class
+                        converterClass = 
ClassLoaderUtil.loadClass(tc.converter(), this.getClass());
                     } else {
                         converterClass = tc.converterClass();
                     }
 
                     LOG.debug("Converter class: [{}]", converterClass);
 
+                    //check if the converter is a type converter if it is one
+                    //then just put it in the map as is. Otherwise
+                    //put a value in for the type converter of the class
                     if (converterClass.isAssignableFrom(TypeConverter.class)) {
-                        mapping.put(key, 
converterCreator.createTypeConverter(tc.converter()));
+                        if (StringUtils.isNoneEmpty(tc.converter())) {
+                            mapping.put(key, 
converterCreator.createTypeConverter(tc.converter()));
+                        } else {
+                            mapping.put(key, 
converterCreator.createTypeConverter(tc.converterClass()));
+                        }
                     } else {
                         mapping.put(key, converterClass);
                         LOG.debug("Object placed in mapping for key [{}] is 
[{}]", key, mapping.get(key));
@@ -100,7 +105,7 @@ else if (tc.rule() == ConversionRule.KEY) {
                 //elements(values) of maps / lists
                 else {
                     if (StringUtils.isNoneEmpty(tc.converter())) {
-                        mapping.put(key, 
Thread.currentThread().getContextClassLoader().loadClass(tc.converter()));
+                        mapping.put(key, 
ClassLoaderUtil.loadClass(tc.converter(), this.getClass()));
                     } else {
                         mapping.put(key, tc.converterClass());
                     }
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionFileProcessor.java
 
b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionFileProcessor.java
index d07cf3cce..7995b7dc3 100644
--- 
a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionFileProcessor.java
+++ 
b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionFileProcessor.java
@@ -86,7 +86,7 @@ else if 
(!(key.startsWith(DefaultObjectTypeDeterminer.ELEMENT_PREFIX) ||
                     //for keys of Maps
                     else if 
(key.startsWith(DefaultObjectTypeDeterminer.KEY_PREFIX)) {
 
-                        Class converterClass = 
Thread.currentThread().getContextClassLoader().loadClass((String) 
entry.getValue());
+                        Class converterClass = 
ClassLoaderUtil.loadClass((String) entry.getValue(), this.getClass());
 
                         //check if the converter is a type converter if it is 
one
                         //then just put it in the map as is. Otherwise
@@ -102,7 +102,7 @@ else if 
(key.startsWith(DefaultObjectTypeDeterminer.KEY_PREFIX)) {
                     }
                     //elements(values) of maps / lists
                     else {
-                        Class _c = 
Thread.currentThread().getContextClassLoader().loadClass((String) 
entry.getValue());
+                        Class _c = ClassLoaderUtil.loadClass((String) 
entry.getValue(), this.getClass());
                         LOG.debug("\t{}:{} [treated as Class {}]", key, 
entry.getValue(), _c);
                         mapping.put(key, _c);
                     }
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 ac4b611b7..07358887b 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
@@ -500,15 +500,32 @@ protected void addConverterMapping(Map<String, Object> 
mapping, Class clazz) {
             for (Annotation annotation : annotations) {
                 if (annotation instanceof TypeConversion) {
                     TypeConversion tc = (TypeConversion) annotation;
-                    if (mapping.containsKey(tc.key())) {
-                        break;
-                    }
                     String key = tc.key();
-                    // Default to the property name
+                    // Default to the property name with prefix
                     if (StringUtils.isEmpty(key)) {
                         key = AnnotationUtils.resolvePropertyName(method);
+                        switch (tc.rule()) {
+                            case COLLECTION:
+                                key = 
DefaultObjectTypeDeterminer.DEPRECATED_ELEMENT_PREFIX + key;
+                                break;
+                            case CREATE_IF_NULL:
+                                key = 
DefaultObjectTypeDeterminer.CREATE_IF_NULL_PREFIX + key;
+                                break;
+                            case ELEMENT:
+                                key = 
DefaultObjectTypeDeterminer.ELEMENT_PREFIX + key;
+                                break;
+                            case KEY:
+                                key = DefaultObjectTypeDeterminer.KEY_PREFIX + 
key;
+                                break;
+                            case KEY_PROPERTY:
+                                key = 
DefaultObjectTypeDeterminer.KEY_PROPERTY_PREFIX + key;
+                                break;
+                        }
                         LOG.debug("Retrieved key [{}] from method name [{}]", 
key, method.getName());
                     }
+                    if (mapping.containsKey(key)) {
+                        break;
+                    }
                     annotationProcessor.process(mapping, tc, key);
                 }
             }
diff --git a/core/src/test/java/com/opensymphony/xwork2/AnnotatedTestBean.java 
b/core/src/test/java/com/opensymphony/xwork2/AnnotatedTestBean.java
index c851aa41e..cf4cec6fb 100644
--- a/core/src/test/java/com/opensymphony/xwork2/AnnotatedTestBean.java
+++ b/core/src/test/java/com/opensymphony/xwork2/AnnotatedTestBean.java
@@ -18,6 +18,9 @@
  */
 package com.opensymphony.xwork2;
 
+import com.opensymphony.xwork2.conversion.annotations.TypeConversion;
+import com.opensymphony.xwork2.conversion.impl.FooBarConverter;
+import com.opensymphony.xwork2.util.Bar;
 import com.opensymphony.xwork2.validator.annotations.IntRangeFieldValidator;
 import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;
 import com.opensymphony.xwork2.validator.annotations.Validations;
@@ -37,6 +40,7 @@
     private Date birth;
     private String name;
     private int count;
+    private Bar bar;
 
     //~ Constructors 
///////////////////////////////////////////////////////////
 
@@ -76,4 +80,13 @@ public void setName(String name) {
     public String getName() {
         return name;
     }
+
+    public Bar getSupperBarObj() {
+        return bar;
+    }
+
+    @TypeConversion(converter = 
"com.opensymphony.xwork2.conversion.impl.FooBarConverter")
+    public void setSupperBarObj(Bar b) {
+        bar = b;
+    }
 }
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 bca99e5c2..eb1b0f6d3 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
@@ -177,7 +177,7 @@ public void testFindConversionErrorMessage() {
         assertEquals("Invalid field value for field \"foo\".", message);
     }
 
-    public void testFindConversionMappingForInterface() {
+    public void testFindConversionMappingForInterfaceAndSuperclass() {
         ModelDrivenAnnotationAction2 action = new 
ModelDrivenAnnotationAction2();
         ValueStack stack = ActionContext.getContext().getValueStack();
         stack.push(action);
@@ -193,6 +193,14 @@ public void testFindConversionMappingForInterface() {
 
         Bar b = (Bar) o;
         assertEquals(value, b.getTitle() + ":" + b.getSomethingElse());
+
+        String value2 = "qwer:456";
+        Object o2 = converter.convertValue(ognlStackContext, 
action.getModel(), null, "supperBarObj", value2, Bar.class);
+        assertNotNull(o2);
+        assertTrue("class is: " + o.getClass(), o2 instanceof Bar);
+
+        Bar b2 = (Bar) o2;
+        assertEquals(value2, b2.getTitle() + ":" + b2.getSomethingElse());
     }
 
     public void testLocalizedDateConversion() throws Exception {
diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java 
b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
index beb886fb7..741a39678 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
@@ -582,7 +582,7 @@ public void testGetBeanMap() throws Exception {
         // just do some of the 15 tests
         Map beans = ognlUtil.getBeanMap(foo);
         assertNotNull(beans);
-        assertEquals(19, beans.size());
+        assertEquals(21, beans.size());
         assertEquals("Hello Santa", beans.get("title"));
         assertEquals(new Long("123"), beans.get("ALong"));
         assertEquals(new Integer("44"), beans.get("number"));
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlValueStackTest.java 
b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlValueStackTest.java
index 1ceb4132c..012122085 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlValueStackTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlValueStackTest.java
@@ -733,11 +733,24 @@ public void testSetNullList() {
         assertEquals("Cat One", ((Cat) foo.getCats().get(0)).getName());
         assertEquals("Cat Two", ((Cat) foo.getCats().get(1)).getName());
 
+        vs.setValue("annotatedCats[0].name", "Cat One By Annotation");
+        vs.setValue("annotatedCats[1].name", "Cat Two By Annotation");
+        assertNotNull(foo.getAnnotatedCats());
+        assertEquals(2, foo.getAnnotatedCats().size());
+        assertEquals("Cat One By Annotation", ((Cat) 
foo.getAnnotatedCats().get(0)).getName());
+        assertEquals("Cat Two By Annotation", ((Cat) 
foo.getAnnotatedCats().get(1)).getName());
+
         vs.setValue("cats[0].foo.cats[1].name", "Deep null cat");
         assertNotNull(((Cat) foo.getCats().get(0)).getFoo());
         assertNotNull(((Cat) foo.getCats().get(0)).getFoo().getCats());
         assertNotNull(((Cat) foo.getCats().get(0)).getFoo().getCats().get(1));
         assertEquals("Deep null cat", ((Cat) ((Cat) 
foo.getCats().get(0)).getFoo().getCats().get(1)).getName());
+
+        vs.setValue("annotatedCats[0].foo.annotatedCats[1].name", "Deep null 
cat by annotation");
+        assertNotNull(((Cat) foo.getAnnotatedCats().get(0)).getFoo());
+        assertNotNull(((Cat) 
foo.getAnnotatedCats().get(0)).getFoo().getAnnotatedCats());
+        assertNotNull(((Cat) 
foo.getAnnotatedCats().get(0)).getFoo().getAnnotatedCats().get(1));
+        assertEquals("Deep null cat by annotation", ((Cat) ((Cat) 
foo.getAnnotatedCats().get(0)).getFoo().getAnnotatedCats().get(1)).getName());
     }
 
     public void testSetMultiple() {
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/ognl/SetPropertiesTest.java 
b/core/src/test/java/com/opensymphony/xwork2/ognl/SetPropertiesTest.java
index c19895ff7..3f3aeced8 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ognl/SetPropertiesTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/SetPropertiesTest.java
@@ -244,6 +244,7 @@ public void 
doTestAddingAndModifyingCollectionWithObjects(Collection barColl) {
         Bar bar2 = new Bar();
         bar2.setId(new Long(22));
         barColl.add(bar2);
+        foo.setAnnotatedBarCollection(barColl);
         //try modifying bar1 and bar2
         //check the logs here to make sure
         //the Map is being created
@@ -262,13 +263,31 @@ public void 
doTestAddingAndModifyingCollectionWithObjects(Collection barColl) {
                 assertEquals(bar1Title, next.getTitle());
             }
         }
+        Bar bar3 = new Bar();
+        bar3.setId(new Long(33));
+        barColl.add(bar3);
+        Bar bar4 = new Bar();
+        bar4.setId(new Long(44));
+        barColl.add(bar4);
+        String bar1TitleByAnnotation = "The Phantom Menace By Annotation";
+        String bar2TitleByAnnotation = "The Clone Wars By Annotation";
+        vs.setValue("annotatedBarCollection(44).title", bar2TitleByAnnotation);
+        vs.setValue("annotatedBarCollection(33).title", bar1TitleByAnnotation);
+        for (Object aBarColl : barColl) {
+            Bar next = (Bar) aBarColl;
+            if (next.getId().intValue() == 44) {
+                assertEquals(bar2TitleByAnnotation, next.getTitle());
+            } else if (next.getId().intValue() == 33) {
+                assertEquals(bar1TitleByAnnotation, next.getTitle());
+            }
+        }
         //now test adding to a collection
         String bar3Title = "Revenge of the Sith";
         String bar4Title = "A New Hope";
         vs.setValue("barCollection.makeNew[4].title", bar4Title, true);
         vs.setValue("barCollection.makeNew[0].title", bar3Title, true);
 
-        assertEquals(4, barColl.size());
+        assertEquals(6, barColl.size());
 
         for (Object aBarColl : barColl) {
             Bar next = (Bar) aBarColl;
@@ -279,6 +298,24 @@ public void 
doTestAddingAndModifyingCollectionWithObjects(Collection barColl) {
             }
         }
 
+        //now test adding to a collection by annotation
+        String bar3TitleByAnnotation = "Revenge of the Sith By Annotation";
+        String bar4TitleByAnnotation = "A New Hope By Annotation";
+        vs.setValue("annotatedBarCollection.makeNew[5].title", 
bar4TitleByAnnotation, true);
+        vs.setValue("annotatedBarCollection.makeNew[1].title", 
bar3TitleByAnnotation, true);
+
+        assertEquals(8, barColl.size());
+
+        for (Object aBarColl : barColl) {
+            Bar next = (Bar) aBarColl;
+            if (next.getId() == null) {
+                assertNotNull(next.getTitle());
+                assertTrue(next.getTitle().equals(bar4TitleByAnnotation)
+                        || next.getTitle().equals(bar3TitleByAnnotation)
+                        || next.getTitle().equals(bar4Title)
+                        || next.getTitle().equals(bar3Title));
+            }
+        }
     }
     public void testAddingToCollectionBasedOnPermission() {
         final MockObjectTypeDeterminer determiner = new 
MockObjectTypeDeterminer(Long.class,Bar.class,"id",true);
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonAction.java 
b/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonAction.java
index e03a77d22..c651edcab 100644
--- 
a/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonAction.java
+++ 
b/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonAction.java
@@ -32,7 +32,7 @@
                                                
converterClass=AddressTypeConverter.class),
                @TypeConversion(type=ConversionType.APPLICATION,
                                                
key="com.opensymphony.xwork2.test.annotations.Person",
-                                               
converterClass=PersonTypeConverter.class)})
+                                               
converter="com.opensymphony.xwork2.test.annotations.PersonTypeConverter")})
 public class PersonAction {
        List<Person> users;
        private List<Address> address;
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/Foo.java 
b/core/src/test/java/com/opensymphony/xwork2/util/Foo.java
index afbd2db34..b14270a2e 100644
--- a/core/src/test/java/com/opensymphony/xwork2/util/Foo.java
+++ b/core/src/test/java/com/opensymphony/xwork2/util/Foo.java
@@ -18,6 +18,10 @@
  */
 package com.opensymphony.xwork2.util;
 
+import com.opensymphony.xwork2.conversion.annotations.ConversionRule;
+import com.opensymphony.xwork2.conversion.annotations.ConversionType;
+import com.opensymphony.xwork2.conversion.annotations.TypeConversion;
+
 import java.util.*;
 
 
@@ -34,9 +38,11 @@
     Date meeting;
     Foo child;
     List cats;
+    List annotatedCats;
     List moreCats;
     List strings;
     Collection barCollection;
+    Collection annotatedBarCollection;
     Map catMap;
     Map anotherCatMap;
     String title;
@@ -96,6 +102,15 @@ public List getCats() {
         return cats;
     }
 
+    public void setAnnotatedCats(List annotatedCats) {
+        this.annotatedCats = annotatedCats;
+    }
+
+    @TypeConversion(rule = ConversionRule.ELEMENT, converterClass = Cat.class)
+    public List getAnnotatedCats() {
+        return annotatedCats;
+    }
+
     public void setChild(Foo child) {
         this.child = child;
     }
@@ -154,6 +169,16 @@ public void setBarCollection(Collection barCollection) {
         this.barCollection = barCollection;
     }
 
+    @TypeConversion(rule = ConversionRule.KEY_PROPERTY, value = "id")
+    public void setAnnotatedBarCollection(Collection annotatedBarCollection) {
+        this.annotatedBarCollection = annotatedBarCollection;
+    }
+
+    @TypeConversion(rule = ConversionRule.ELEMENT, converter = 
"com.opensymphony.xwork2.util.Bar")
+    public Collection getAnnotatedBarCollection() {
+        return annotatedBarCollection;
+    }
+
     public void setPoints(long[] points) {
         this.points = points;
     }
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/MyBeanAction.java 
b/core/src/test/java/com/opensymphony/xwork2/util/MyBeanAction.java
index cabdbf891..aeac35609 100644
--- a/core/src/test/java/com/opensymphony/xwork2/util/MyBeanAction.java
+++ b/core/src/test/java/com/opensymphony/xwork2/util/MyBeanAction.java
@@ -19,6 +19,10 @@
 package com.opensymphony.xwork2.util;
 
 import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.conversion.annotations.Conversion;
+import com.opensymphony.xwork2.conversion.annotations.ConversionRule;
+import com.opensymphony.xwork2.conversion.annotations.ConversionType;
+import com.opensymphony.xwork2.conversion.annotations.TypeConversion;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -30,10 +34,19 @@
  *
  * @author Rainer Hermanns
  */
+@Conversion(
+        conversions= {
+                @TypeConversion(key = "KeyProperty_annotatedBeanMap", rule = 
ConversionRule.KEY_PROPERTY, value = "id"),
+                @TypeConversion(key = "Element_annotatedBeanMap", rule = 
ConversionRule.ELEMENT, converterClass = MyBean.class),
+                @TypeConversion(key = "KeyProperty_annotatedBeanList", rule = 
ConversionRule.KEY_PROPERTY, value = "id"),
+                @TypeConversion(key = "Element_annotatedBeanList", rule = 
ConversionRule.ELEMENT, converterClass = MyBean.class)
+        })
 public class MyBeanAction implements Action {
 
     private List beanList = new ArrayList();
     private Map beanMap = new HashMap();
+    private Map annotatedBeanMap = new HashMap();
+    private List annotatedBeanList = new ArrayList();
 
     public List getBeanList() {
         return beanList;
@@ -51,6 +64,24 @@ public void setBeanMap(Map beanMap) {
         this.beanMap = beanMap;
     }
 
+    public Map getAnnotatedBeanMap() {
+        return annotatedBeanMap;
+    }
+
+    @TypeConversion(rule = ConversionRule.KEY, converterClass = Long.class)
+    public void setAnnotatedBeanMap(Map annotatedBeanMap) {
+        this.annotatedBeanMap = annotatedBeanMap;
+    }
+
+    public List getAnnotatedBeanList() {
+        return annotatedBeanList;
+    }
+
+    @TypeConversion(rule = ConversionRule.CREATE_IF_NULL, value = "true")
+    public void setAnnotatedBeanList(List annotatedBeanList) {
+        this.annotatedBeanList = annotatedBeanList;
+    }
+
     public String execute() throws Exception {
         return SUCCESS;
     }
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/util/MyBeanActionTest.java 
b/core/src/test/java/com/opensymphony/xwork2/util/MyBeanActionTest.java
index ff4b55507..ab72a9f49 100644
--- a/core/src/test/java/com/opensymphony/xwork2/util/MyBeanActionTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/util/MyBeanActionTest.java
@@ -39,6 +39,9 @@ public void testIndexedList() {
         params.put("beanList(1234567890).name", "This is the bla bean");
         params.put("beanList(1234567891).name", "This is the 2nd bla bean");
 
+        params.put("annotatedBeanList(1234567890).name", "This is the bla bean 
by annotation");
+        params.put("annotatedBeanList(1234567891).name", "This is the 2nd bla 
bean by annotation");
+
         HashMap<String, Object> extraContext = new HashMap<>();
         extraContext.put(ActionContext.PARAMETERS, 
HttpParameters.create(params).build());
 
@@ -53,6 +56,15 @@ public void testIndexedList() {
             assertEquals(new Long(1234567890), 
Long.valueOf(proxy.getInvocation().getStack().findValue("beanList.get(0).id").toString()));
             assertEquals("This is the 2nd bla bean", 
proxy.getInvocation().getStack().findValue("beanList.get(1).name"));
             assertEquals(new Long(1234567891), 
Long.valueOf(proxy.getInvocation().getStack().findValue("beanList.get(1).id").toString()));
+
+            assertEquals(2, 
Integer.parseInt(proxy.getInvocation().getStack().findValue("annotatedBeanList.size").toString()));
+            assertEquals(MyBean.class.getName(), 
proxy.getInvocation().getStack().findValue("annotatedBeanList.get(0)").getClass().getName());
+            assertEquals(MyBean.class.getName(), 
proxy.getInvocation().getStack().findValue("annotatedBeanList.get(1)").getClass().getName());
+
+            assertEquals("This is the bla bean by annotation", 
proxy.getInvocation().getStack().findValue("annotatedBeanList.get(0).name"));
+            assertEquals(new Long(1234567890), 
Long.valueOf(proxy.getInvocation().getStack().findValue("annotatedBeanList.get(0).id").toString()));
+            assertEquals("This is the 2nd bla bean by annotation", 
proxy.getInvocation().getStack().findValue("annotatedBeanList.get(1).name"));
+            assertEquals(new Long(1234567891), 
Long.valueOf(proxy.getInvocation().getStack().findValue("annotatedBeanList.get(1).id").toString()));
         } catch (Exception e) {
             e.printStackTrace();
             fail();
@@ -67,6 +79,12 @@ public void testIndexedMap() {
         params.put("beanMap[1234567890].name", "This is the bla bean");
         params.put("beanMap[1234567891].name", "This is the 2nd bla bean");
 
+        params.put("annotatedBeanMap[1234567890].id", "1234567890");
+        params.put("annotatedBeanMap[1234567891].id", "1234567891");
+
+        params.put("annotatedBeanMap[1234567890].name", "This is the bla bean 
by annotation");
+        params.put("annotatedBeanMap[1234567891].name", "This is the 2nd bla 
bean by annotation");
+
         HashMap<String, Object> extraContext = new HashMap<>();
         extraContext.put(ActionContext.PARAMETERS, 
HttpParameters.create(params).build());
 
@@ -89,6 +107,21 @@ public void testIndexedMap() {
 
             assertEquals("1234567890", 
proxy.getInvocation().getStack().findValue("beanMap.get(1234567890L).id").toString());
             assertEquals("1234567891", 
proxy.getInvocation().getStack().findValue("beanMap.get(1234567891L).id").toString());
+
+            assertEquals(2, 
Integer.parseInt(proxy.getInvocation().getStack().findValue("annotatedBeanMap.size").toString()));
+
+            assertEquals(true, 
action.getAnnotatedBeanMap().containsKey(1234567890L));
+            assertEquals(true, 
action.getAnnotatedBeanMap().containsKey(1234567891L));
+
+
+            assertEquals(MyBean.class.getName(), 
proxy.getInvocation().getStack().findValue("annotatedBeanMap.get(1234567890L)").getClass().getName());
+            assertEquals(MyBean.class.getName(), 
proxy.getInvocation().getStack().findValue("annotatedBeanMap.get(1234567891L)").getClass().getName());
+
+            assertEquals("This is the bla bean by annotation", 
proxy.getInvocation().getStack().findValue("annotatedBeanMap.get(1234567890L).name"));
+            assertEquals("This is the 2nd bla bean by annotation", 
proxy.getInvocation().getStack().findValue("annotatedBeanMap.get(1234567891L).name"));
+
+            assertEquals("1234567890", 
proxy.getInvocation().getStack().findValue("annotatedBeanMap.get(1234567890L).id").toString());
+            assertEquals("1234567891", 
proxy.getInvocation().getStack().findValue("annotatedBeanMap.get(1234567891L).id").toString());
         } catch (Exception e) {
             e.printStackTrace();
             fail();


 

----------------------------------------------------------------
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:
[email protected]


> The converter() method of 
> com.opensymphony.xwork2.conversion.annotations.TypeConversion is now 
> deprecated. If this method is removed in some next release, it will forbid to 
> describe a converter by the name (id) of a Spring bean. 
> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: WW-4906
>                 URL: https://issues.apache.org/jira/browse/WW-4906
>             Project: Struts 2
>          Issue Type: Bug
>          Components: Core
>    Affects Versions: 2.5.14.1
>            Reporter: Christophe Deleray
>            Assignee: Yasser Zamani
>            Priority: Major
>             Fix For: 2.5.15
>
>         Attachments: Struts2Converter.zip
>
>
> Hi,
> I upgrade Struts2 from the 2.5.10.1 version to the 2.5.14.1 version, and 
> unfortunately I saw that the converter() method of the 
> com.opensymphony.xwork2.conversion.annotations.TypeConversion class got 
> deprecated.
> It is very useful when the value of the "converter" attribute corresponds to 
> a Spring-based bean.
> Is it a feature to be removed on some next release ? Can this feature be 
> un-deprecated ?
> Best regards,
> Christophe Deleray



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

Reply via email to