Uploaded image for project: 'Commons OGNL (Dormant)'
  1. Commons OGNL (Dormant)
  2. OGNL-238

OGNLRuntime doesn't handle parameterized method arguments correctly for a grandchild class of a generic class



    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 3.0
    • 4.0
    • Core Runtime
    • None
    • Windows 7 64bit, Java Runtime Environment 7


      Suppose there are classes as described below.
      Class Foo<T> is a generic class with a type parameter T.
      It has a property named "x" whose type is T; Foo has methods "T getX()" and "void setX(T x)".
      Class Bar is a direct derived class of Foo<Integer>.
      Class Baz is a direct derived class of Bar and class Qux is a direct derived class of Baz.
      In short, there is an inheritance tree like this: Foo<T> -> Bar -> Baz -> Qux.

      Static method ognl.Ognl.setValue(String expression, Object root, Object value) has an ability to resolve a type parameter of an argument of a method.
      But it does not work well for a derived class of a generic class.

      If you execute Ognl.setValue("tmp.x", root, "123") where "tmp" is an instance of class Bar, "123" is converted to an Integer and tmp's property X is set to an Integer.
      It is a natural behavior because Bar extends Foo<Integer> and tmp's property x should be an Integer.

      But, if tmp is an instance of class Baz or Qux, which are both derived classes of Bar, the conversion is never performed and tmp's property X is set to String "123".
      It seems that type parameter handling works only when the class is DIRECTLY derived from a generic class.

      Here is a test code.
      You will need to add ognl-3.0.6.jar and javassist-3.11.0.GA.jar to the classpath in order to execute the code. They are bundled in Struts2.3.15.1.

      import java.text.MessageFormat;
      import java.util.LinkedHashMap;
      import java.util.Map;
      import java.util.Map.Entry;

      import ognl.Ognl;

      class Foo<T> {

      private T m_x;

      public T getX()

      { return m_x; }

      public void setX(T x)

      { m_x = x; }


      class Bar extends Foo<Integer> {

      class Baz extends Bar {

      class Qux extends Baz {

      public class OgnlBugTest {

      public static void main(String[] args) {
      try {
      Map<String, Foo<?>> root = new LinkedHashMap<String, Foo<?>>();
      root.put("foo", new Foo<Short>());
      root.put("bar", new Bar());
      root.put("baz", new Baz());
      root.put("qux", new Qux());

      Ognl.setValue("foo.x", root, "1");
      Ognl.setValue("bar.x", root, "2");
      Ognl.setValue("baz.x", root, "3");
      Ognl.setValue("qux.x", root, "4");

      for (Entry<String, Foo<?>> entry : root.entrySet()) {






      )", entry.getKey(), entry.getValue().getX(), entry.getValue().getX().getClass()));
      } catch (Exception exception)

      { exception.printStackTrace(); }



        1. ognl238test.zip
          2 kB



            Unassigned Unassigned
            recyclebin5385@yahoo.co.jp recyclebin5385
            0 Vote for this issue
            2 Start watching this issue