ValueExpression:如何获取基础对象?

时间:2012-09-11 07:38:25

标签: jsf-2 el

@FacesValidator("uniqueValidator")
public class UniqueValidator implements Validator
{
    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException
    {
        if(context == null)
        {
            throw new NullPointerException();
        }
        if(component == null)
        {
            throw new NullPointerException();
        }

        ValueExpression valueExpression = component.getValueExpression("value");
        if(valueExpression == null)
        {
            return;
        }

        ValueReference valueReference = valueExpression.getValueReference(context.getELContext());
        if(valueReference == null)
        {
            return;
        }

        Object base = valueReference.getBase();
        Object property = valueReference.getProperty();

        Tracer.out(base, property);

        .....
    }
}

ValueReference 始终为空。

出了什么问题?

2 个答案:

答案 0 :(得分:3)

谢谢BeanValidator:)

public class ValueExpressionAnalyzer
{
    public static ValueReference getReference(ELContext elContext, ValueExpression expression)
    {
        InterceptingResolver resolver = new InterceptingResolver(elContext.getELResolver());

        try
        {
            expression.setValue(new InterceptingContext(elContext, resolver), null);
        }
        catch(ELException ele)
        {
            return null;
        }

        ValueReference reference = resolver.getValueReference();
        if(reference != null)
        {
            Object base = reference.getBase();
            if(base instanceof CompositeComponentExpressionHolder)
            {
                ValueExpression ve = ((CompositeComponentExpressionHolder) base).getExpression((String) reference.getProperty());
                if(ve != null)
                {
                    reference = getReference(elContext, ve);
                }
            }
        }
        return reference;
    }

    private static class InterceptingContext extends ELContext
    {
        private final ELContext context;
        private final ELResolver resolver;

        public InterceptingContext(ELContext context, ELResolver resolver)
        {
            this.context = context;
            this.resolver = resolver;
        }

        // punch in our new ELResolver
        @Override
        public ELResolver getELResolver()
        {
            return resolver;
        }

        // The rest of the methods simply delegate to the existing context

        @Override
        public Object getContext(Class key)
        {
            return context.getContext(key);
        }

        @Override
        public Locale getLocale()
        {
            return context.getLocale();
        }

        @Override
        public boolean isPropertyResolved()
        {
            return context.isPropertyResolved();
        }

        @Override
        public void putContext(Class key, Object contextObject)
        {
            context.putContext(key, contextObject);
        }

        @Override
        public void setLocale(Locale locale)
        {
            context.setLocale(locale);
        }

        @Override
        public void setPropertyResolved(boolean resolved)
        {
            context.setPropertyResolved(resolved);
        }

        @Override
        public FunctionMapper getFunctionMapper()
        {
            return context.getFunctionMapper();
        }

        @Override
        public VariableMapper getVariableMapper()
        {
            return context.getVariableMapper();
        }
    }

    private static class InterceptingResolver extends ELResolver
    {
        private final ELResolver delegate;
        private ValueReference valueReference;

        public InterceptingResolver(ELResolver delegate)
        {
            this.delegate = delegate;
        }

        public ValueReference getValueReference()
        {
            return valueReference;
        }

        // Capture the base and property rather than write the value
        @Override
        public void setValue(ELContext context, Object base, Object property, Object value)
        {
            if(base != null && property != null)
            {
                context.setPropertyResolved(true);
                valueReference = new ValueReference(base, property.toString());
            }
        }

        // The rest of the methods simply delegate to the existing context

        @Override
        public Object getValue(ELContext context, Object base, Object property)
        {
            return delegate.getValue(context, base, property);
        }

        @Override
        public Class<?> getType(ELContext context, Object base, Object property)
        {
            return delegate.getType(context, base, property);
        }

        @Override
        public boolean isReadOnly(ELContext context, Object base, Object property)
        {
            return delegate.isReadOnly(context, base, property);
        }

        @Override
        public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base)
        {
            return delegate.getFeatureDescriptors(context, base);
        }

        @Override
        public Class<?> getCommonPropertyType(ELContext context, Object base)
        {
            return delegate.getCommonPropertyType(context, base);
        }

    }
}

答案 1 :(得分:0)

看看 Omnifaces ExpressionInspector。似乎在 JSF 2.x 中它没有实现并且总是返回 null。

https://showcase.omnifaces.org/el/ExpressionInspector