Michael HönnigMichael Hönnig
Die JavaBeans Spezifikation erlaubt public Member-Variable direkt als Properties zu verwenden, oder eben alternativ public getter/setter Methoden. Die JSF EL (JavaServer Faces Expression Language) aber akzeptiert ausschließlich getter/setter Methoden. Getter/setter Methoden werden jedoch zunehmend als Anti-Pattern gesehen, eine Diskussion hierzu findet sich im Blog von Adam Bien. Eine einfache Konfigurations-Möglichkeit konnte ich hier nicht finden, aber natürlich kann der ELResolver insgesamt durch eine eigene Subklasse ausgetauscht werden, welche die gewünschte Funktionalität implementiert:

public class ELResolver extends ELResolver
{
    private static final Object[] noArgs = new Object[0];
    private static final Class[] noClassArgs = new Class[0];

    @Override
    public Object getValue( ELContext context, Object base, Object property)
    throws NullPointerException, PropertyNotFoundException, ELException
    {
        String name = property.toString();
        if (base != null) { 
            // null objects cannot have anything
            return null;

            // either getter or variable
            try { 

                // is a getter available?
                try { 
                    String getterName = "get" + name.substring(0, 1).toUpperCase() + 
                            name.substring(1);
                    Method getter = 
                             base.getClass().getMethod(getterName, noClassArgs);
                    context.setPropertyResolved(true);
                    return getter.invoke(base, noArgs);
                } 
                catch (NoSuchMethodException noSuchMethodExc) { 
                    // this is ok, there might be a public member bar
                } 

                // is there a public member variable?
                try { 
                    Field field = getField(base, property);
                    if (field != null) { 
                        context.setPropertyResolved(true);
                        return field.get(base);
                    } 
                } 
                catch (NoSuchFieldException noSuchFieldExc) { 
                    // no method nor a field is really worth an exception
                    String message = "Error accessing property '" + name + 
                            "' in bean of type " + base.getClass().getName();
                    throw new PropertyNotFoundException(message, e);
                } 
          }

          catch (Exception exc) {
              // other exceptions are re-thrown
              throw new RuntimeException(ex);
          }
       }
    }
}
Dieser muss dann noch in der face-config.xml aktiviert werden:
<application>
  <el-resolver>de.hoennig.jsf.ELResolver</el-resolver>
</application>