Вопрос по el, jsf-2, java – вложение строк выражения JSF

4

Я хочу добиться этого, используя динамические параметры для выражений значений:

<h:dataTable value="#{someBean.someValue}" var="field">
    <h:column>#{anotherBean[field]}</h:column>
</h:dataTable>

гдеfield является'user.name' или же'location.address.zip' или же...

Является ли это возможным?

Обратите внимание, что это простой пример, который мне интересенValueExpression не вdataTable составная часть.

UPDATE Теперь вопрос: как заменить стандартный BeanELResolver?

смотря в ELUtils:

    ...
    composite.addRootELResolver(IMPLICIT_RESOLVER);
    composite.add(FLASH_RESOLVER);
    composite.addPropertyELResolver(COMPOSITE_COMPONENT_ATTRIBUTES_EL_RESOLVER);
    addELResolvers(composite, associate.getELResolversFromFacesConfig());
    addVariableResolvers(composite, FacesCompositeELResolver.ELResolverChainType.Faces,
            associate);
    addPropertyResolvers(composite, associate);
    composite.add(associate.getApplicationELResolvers());
    composite.addRootELResolver(MANAGED_BEAN_RESOLVER);
    composite.addPropertyELResolver(RESOURCE_RESOLVER);
    composite.addPropertyELResolver(BUNDLE_RESOLVER);
    ...

но я еще не полностью понимаю цепочку резольвера ... так что я пойду изучать :)

UPDATE 2

этот код работает;)

public class ExtendedBeanELResolver extends BeanELResolver
{
    @Override
    public Object getValue(ELContext context, Object base, Object property) throws NullPointerException, PropertyNotFoundException, ELException
    {
        try
        {
            return super.getValue(context, base, property);
        }
        catch(PropertyNotFoundException e)
        {
            try
            {
                Object value = base;

                for(String part : property.toString().split("\\."))
                {
                    value = super.getValue(context, value, part);
                }

                return value;
            }
            catch(PropertyNotFoundException e1)
            {
                context.setPropertyResolved(false);
            }
        }

        return null;
    }
}
нет, я говорю правильно:public List<String> getSomeValue() { ... } Michele Mariotti

Ваш Ответ

2   ответа
9

Это по умолчанию не поддерживается. Вам нужен кастомELResolver Вот. Проще всего продлить существующийBeanELResolver.

Вот пример запуска:

public class ExtendedBeanELResolver extends BeanELResolver {

    @Override
    public Object getValue(ELContext context, Object base, Object property)
        throws NullPointerException, PropertyNotFoundException, ELException
    {
        if (property == null || base == null || base instanceof ResourceBundle || base instanceof Map || base instanceof Collection) {
            return null;
        }

        String propertyString = property.toString();

        if (propertyString.contains(".")) {
            Object value = base;

            for (String propertyPart : propertyString.split("\\.")) {
                value = super.getValue(context, value, propertyPart);
            }

            return value;
        }
        else {
            return super.getValue(context, base, property);
        }
    }

}

Чтобы запустить его, зарегистрируйте его следующим образом вfaces-config.xml:

<application>
    <el-resolver>com.example.ExtendedBeanELResolver</el-resolver>
</application>
упс, я был не прав. он не переопределяет, но вставляется раньше. см обновление вопроса. Michele Mariotti
Какую именно проблему это вызвало у вас? Изменение должно быть прозрачным, поскольку оно последовательно делегирует супер.
Однако объявив это вfaces-config.xml переопределяет значение по умолчаниюCompositeELResolver, как заменить стандартBeanELResolver вCompositeELResolver.elResolvers? Michele Mariotti
причиныPropertyNotFoundException пытаюсь прочитать пачки свойств. Однако Док утверждаетBecause this resolver handles base objects of any type, it should be placed near the end of a composite resolver. Otherwise, it will claim to have resolved a property before any resolvers that come after it get a chance to test if they can do so as well. так что я решил эту ловлюPropertyNotFoundException и настройкаcontext.setPropertyResolved(false); Michele Mariotti
это именно то, что я искал, чтобы решить эту и некоторые другие мелочи. спасибо @BalusC, вы экономите мне столько времени, что заслуживаете часть моей зарплаты;) Michele Mariotti
2

Работа над этой темой очень интересная, но не полная.

В случае, если вы передаете значение в составной компонент, который установлен в этом компоненте, он не работает.

Пример :

<composite:interface>
    <composite:attribute name="value" type="java.lang.Boolean" required="true"  />
</composite:interface>
<composite:implementation>
        <h:inputText id="inputValue" value="#{cc.attrs.value}" 
        </h:inputText>
</composite:implementation>

С ExtendedBeanElResolver он выдает исключение PropertyNotFoundException, когда я устанавливаю значение.

Итак, я трачу несколько часов, чтобы найти решение, и вот рабочее решение, чтобы иметь возможность использовать ExtendedBeanElResolver с возможностью устанавливать значения внутри составных компонентов:

public class ExtendedBeanELResolver extends BeanELResolver {

    private static final String PRIMEFACES_RESOURCE_PREFIX = "primefaces:";
    private static final String RESOURCES_HANDLER = "class org.omnifaces.resourcehandler.GraphicResourceHandler";
    private static final String PRIMEFACES_EXT_RESOURCES_HANDLER = "class org.primefaces.extensions.application.PrimeFacesExtensionsResourceHandler";

    @Override
    public Object getValue(ELContext context, Object base, Object property) {

            if (property == null || base == null || base instanceof ResourceBundle || base instanceof Map || base instanceof Collection
                    || property.toString().startsWith(PRIMEFACES_RESOURCE_PREFIX) || base.getClass().toString().equals(RESOURCES_HANDLER)
                    || base.getClass().toString().equals(PRIMEFACES_EXT_RESOURCES_HANDLER)) {
                return null;
            }
            String propertyString = property.toString();
            if (propertyString.contains(".")) {
                Object value = base;

                for (String propertyPart : propertyString.split("\\.")) {
                    value = super.getValue(context, value, propertyPart);
                }

                return value;
            } else {
                Object v = super.getValue(context, base, property);
               return v;
            }
    }

    @Override
    public void setValue(ELContext context, Object base, Object property, Object val) {
        if (base != null && !(base instanceof ResourceBundle) && !(base instanceof Map) && !(base instanceof Collection))
            super.setValue(context, base, property, val);
    }
}

(Я добавил часть «setValue»).

И теперь это работает. Не стесняйтесь дать мне свой отзыв, так как это мой первый пост на этом сайте!

Похожие вопросы