Index: src/java/com/opensymphony/xwork2/util/OgnlValueStack.java =================================================================== --- src/java/com/opensymphony/xwork2/util/OgnlValueStack.java (revision 1615) +++ src/java/com/opensymphony/xwork2/util/OgnlValueStack.java (working copy) @@ -4,14 +4,17 @@ */ package com.opensymphony.xwork2.util; +import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.DefaultTextProvider; import com.opensymphony.xwork2.XWorkException; import com.opensymphony.xwork2.inject.Inject; - +import ognl.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import ognl.*; + +import java.beans.PropertyDescriptor; import java.io.Serializable; +import java.lang.reflect.Method; import java.util.*; /** @@ -239,9 +242,43 @@ if (value != null) { return value; } else { + if (expr.contains("(") && expr.contains(")")) { + LOG.warn("Could not find method [" + expr + "]"); + } else { + // find objects with Action in them and inspect matching getters + Set availableProperties = new LinkedHashSet(); + for (Object o : root) { + if (o instanceof ActionSupport || o.getClass().getSimpleName().endsWith("Action")) { + PropertyDescriptor[] descriptors = OgnlUtil.getPropertyDescriptors(o); + for (PropertyDescriptor pd : descriptors) { + String name = pd.getDisplayName(); + if (expr.startsWith(name)) { + availableProperties.add(name); + if (expr.indexOf(".") > -1) { + Method[] methods = pd.getPropertyType().getDeclaredMethods(); + for (Method method : methods) { + if (method.getName().startsWith("get")) { + String propertyName = method.getName().substring(3); + if (propertyName.length() > 0) { + propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1); + availableProperties.add(pd.getDisplayName() + "." + propertyName); + // todo: look for another "." and traverse recursively + } + } + } + } + } + } + } + } + if (!availableProperties.contains(expr)) { + LOG.warn("Could not find property [" + expr + "]"); + } + } return findInContext(expr); } } catch (OgnlException e) { + LOG.warn("Could not find property [" + expr + "]"); return findInContext(expr); } catch (Exception e) { logLookupFailure(expr, e);