Commits

Anonymous committed 98bf282

Better error messages for bad bean properties (mismatched getters and setters) etc.

git-svn-id: http://svn.opensymphony.com/svn/xwork/trunk@143e221344d-f017-0410-9bd5-d282ab1896d7

Comments (0)

Files changed (2)

src/java/com/opensymphony/xwork/util/CompoundRootAccessor.java

 package com.opensymphony.xwork.util;
 
 import ognl.*;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import java.beans.IntrospectionException;
+
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.HashMap;
-import java.util.Arrays;
 
 
 /**
     //~ Static fields/initializers /////////////////////////////////////////////
 
     private final static Log log = LogFactory.getLog(CompoundRootAccessor.class);
+    private static Map invalidMethods = new HashMap();
 
     //~ Methods ////////////////////////////////////////////////////////////////
 
-    private static Map invalidMethods = new HashMap();
-
     public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException {
         CompoundRoot root = (CompoundRoot) target;
         OgnlContext ognlContext = (OgnlContext) context;
             } catch (IntrospectionException e) {
             }
         }
+
+        final String msg = "No object in the CompoundRoot has a property named '" + name + "'.";
+        log.error(msg);
+        throw new RuntimeException(msg);
     }
 
     public Object getProperty(Map context, Object target, Object name) throws OgnlException {
             Class[] argTypes = getArgTypes(objects);
 
             CompoundRootAccessor.MethodCall mc = null;
+
             if (argTypes != null) {
                 mc = new CompoundRootAccessor.MethodCall(clazz, name, argTypes);
             }
 
-            if (argTypes == null || !invalidMethods.containsKey(mc)) {
+            if ((argTypes == null) || !invalidMethods.containsKey(mc)) {
                 try {
                     Object value = OgnlRuntime.callMethod((OgnlContext) context, o, name, name, objects);
 
                 } catch (OgnlException e) {
                     // try the next one
                     Throwable reason = e.getReason();
-                    if (mc != null && reason != null && reason.getClass() == NoSuchMethodException.class) {
+
+                    if ((mc != null) && (reason != null) && (reason.getClass() == NoSuchMethodException.class)) {
                         invalidMethods.put(mc, Boolean.TRUE);
                     } else if (reason != null) {
                         throw new MethodFailedException(o, name, e.getReason());
         return null;
     }
 
-    private Class[] getArgTypes(Object[] args) {
-        if (args == null) {
-            return new Class[0];
-        }
-
-        Class[] classes = new Class[args.length];
-        for (int i = 0; i < args.length; i++) {
-            Object arg = args[i];
-            classes[i] = (arg != null) ? arg.getClass() : Object.class;
-        }
-
-        return classes;
-    }
-
     public Object callStaticMethod(Map transientVars, Class aClass, String s, Object[] objects) throws MethodFailedException {
         return null;
     }
         return Thread.currentThread().getContextClassLoader().loadClass(className);
     }
 
+    private Class[] getArgTypes(Object[] args) {
+        if (args == null) {
+            return new Class[0];
+        }
+
+        Class[] classes = new Class[args.length];
+
+        for (int i = 0; i < args.length; i++) {
+            Object arg = args[i];
+            classes[i] = (arg != null) ? arg.getClass() : Object.class;
+        }
+
+        return classes;
+    }
+
+    //~ Inner Classes //////////////////////////////////////////////////////////
+
     static class MethodCall {
         Class clazz;
         String name;
             }
         }
 
-        public int hashCode() {
-            return hash;
-        }
-
         public boolean equals(Object obj) {
             MethodCall mc = (CompoundRootAccessor.MethodCall) obj;
+
             return (mc.clazz.equals(clazz) && mc.name.equals(name) && Arrays.equals(mc.args, args));
         }
+
+        public int hashCode() {
+            return hash;
+        }
     }
 }

src/java/com/opensymphony/xwork/util/OgnlUtil.java

     //~ Methods ////////////////////////////////////////////////////////////////
 
     /**
-     * Sets the object's properties using the default type converter.
-     *
-     * @param props the properties being set
-     * @param o the object
-     * @param context the action context
-     */
+ * Sets the object's properties using the default type converter.
+ *
+ * @param props the properties being set
+ * @param o the object
+ * @param context the action context
+ */
     public static void setProperties(Map props, Object o, Map context) {
         if (props == null) {
             return;
     }
 
     /**
-     * Sets the properties on the object using the default context
-     * @param properties
-     * @param o
-     */
+ * Sets the properties on the object using the default context
+ * @param properties
+ * @param o
+ */
     public static void setProperties(Map properties, Object o) {
         Map context = Ognl.createDefaultContext(o);
         setProperties(properties, o, context);
     }
 
     /**
-     * Sets the named property to the supplied value on the Object
-     * @param name the name of the property to be set
-     * @param value the value to set into the named property
-     * @param o the object upon which to set the property
-     * @param context the context which may include the TypeConverter
-     */
+ * Sets the named property to the supplied value on the Object
+ * @param name the name of the property to be set
+ * @param value the value to set into the named property
+ * @param o the object upon which to set the property
+ * @param context the context which may include the TypeConverter
+ */
     public static void setProperty(String name, Object value, Object o, Map context) {
         Ognl.setTypeConverter(context, XWorkConverter.getInstance());
 
     }
 
     /**
-     * Copies the properties in the object "from" and sets them in the object "to"
-     * using specified type converter, or {@link com.opensymphony.xwork.util.XWorkConverter} if none is specified.
-     *
-     * @param from the source object
-     * @param to the target object
-     * @param context the action context we're running under
-     */
+ * Copies the properties in the object "from" and sets them in the object "to"
+ * using specified type converter, or {@link com.opensymphony.xwork.util.XWorkConverter} if none is specified.
+ *
+ * @param from the source object
+ * @param to the target object
+ * @param context the action context we're running under
+ */
     public static void copy(Object from, Object to, Map context) {
         Map contextFrom = Ognl.createDefaultContext(from);
         Ognl.setTypeConverter(contextFrom, XWorkConverter.getInstance());
         try {
             Ognl.setValue(compile(name), context, o, value);
         } catch (OgnlException e) {
-            // ignore, this happens a lot
+            Throwable reason = e.getReason();
+            String msg = "Caught OgnlException while setting property '" + name + "' on type '" + o.getClass().getName() + "'.";
+
+            if (reason != null) {
+                log.warn(msg, reason);
+            } else {
+                //this happens a lot more often
+                log.debug(msg, e);
+            }
         }
     }
 }