Программно получить значение выражения параметра facelets (переменная) - PullRequest
2 голосов
/ 15 декабря 2011

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

ELContext elCtx = facesContext.getELContext();
ExpressionFactory exprFac = facesContext.getApplication().getExpressionFactory();
MyProperty myProperty = (MyProperty) exprFac.createValueExpression(elCtx, "#{somebean.someattr.someproperty}", MyProperty.class).getValue(elCtx);

Я использую код из своего пользовательского конвертера для чтения дополнительных параметров конвертации из контекста.

Код работает правильно, если #{somebean} определен как обычный компонент поддержки в контексте JSF.

Facelets позволяют создавать «ярлыки» для выражений JSF. Пример:

<ui:param name="shortcut" value="#{somebean.someattr.someproperty}" />
<div>#{somebean.someattr.someproperty} equals #{shortcut}</div>

В этом случае оба значения #{somebean.someattr.someproperty} и #{shortcut} имеют одинаковое значение.

Однако эти «горячие» имена недоступны с помощью кода Java выше. Например:

MyProperty myProperty1 = (MyProperty) exprFac.createValueExpression(elCtx, "#{somebean.someattr.someproperty}", MyProperty.class).getValue(elCtx);
// myProperty1 has expected value

MyProperty myProperty2 = (MyProperty) exprFac.createValueExpression(elCtx, "#{shortcut}", MyProperty.class).getValue(elCtx);
// myProperty2 is null

Есть ли способ получить доступ к контексту Facelets и прочитать значения параметров 'ярлыка', определенные на текущей странице JSF?

Ответы [ 3 ]

3 голосов
/ 14 февраля 2012

У меня была такая же проблема, и я выбрал следующий подход:

/**
     * Führt eine Expression im aktuellen Faces EL Context 
     * UND im Facelets El Context aus.
     * 
     * @param facesContext
     * @param expression
     * @return object
     */
    private static Object executeExpressionInUIContext (final FacesContext facesContext, final String expression) {
        final ELContext elContext = facesContext.getELContext();
        final Application application = facesContext.getApplication();

        Object result = executeExpressionInElContext(application, elContext, expression);
        if (null == result) {
            FaceletContext faceletElContext = (FaceletContext) FacesContext.getCurrentInstance().getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
            result = executeExpressionInElContext(application, faceletElContext, expression);
        }
        return result;
    }

    private static Object executeExpressionInElContext (Application application, ELContext elContext, String expression) {
        ExpressionFactory expressionFactory = application.getExpressionFactory();
        ValueExpression exp = expressionFactory.createValueExpression(elContext, expression, Object.class);
        return exp.getValue(elContext);
    }

"ui: param" является частью технологии обработки представлений Facelet. Facelets расширяет JSF. Обе технологии используют свой собственный Context при хранении переменных. Рядом с контекстом Faces El есть контекст Facelet El (FaceletContext).

Заявленный метод оценивает выражения в обоих контекстах. Имейте в виду, что это не будет работать, если два значения хранятся под одним именем в каждом контексте.

1 голос
/ 16 декабря 2011

Похоже, что ярлыки фейслета не существуют в контексте, где я пытаюсь получить к ним доступ.

Я сделал следующий обходной путь: На странице JSF, где размещен мой элемент ввода, я добавил <f:param> элемент как дочерний элемент ввода с моим конвертером.

<h:inputText id="myid" value="#{action.myinput}">
     <f:converter converterId="myConverter" />
     <f:param name="converterParameters" shortcut="#{somebean.someattr.someproperty}"/>
</h:inputText>

Затем в конвертере я могу найти элемент UIParam как один из входных дочерних элементов и прочитать мои ярлыки из него.

public Object getAsObject(FacesContext context, UIComponent component, String value) {

    MyProperty myProperty = null;
    try {
        for (final UIComponent child : component.getChildren()) {
            if ("converterParameters".equals(child.getAttributes().get("name"))) {
                final ELContext elCtx = context.getELContext();
                myProperty = (MyProperty) child.getValueExpression("shortcut").getValue(elCtx);
                break;
            }
        }
        if (myProperty == null) {
            throw new NullPointerException("My property is undefined.");
        }
    } catch (Exception e) {
        LOG.error("Cannot convert " + value + ".  Use <f:param name=\"converterParameters\" "
                + "shortcut=\"#{here.comes.shortcut}\"/> for your input element. ", e);
        throw new ConverterException("Cannot initialize converter.", e);
    }
//...
}
0 голосов
/ 16 ноября 2012

Отображение ui:param не сохраняется в контексте, оно находится в VariableMapper каждого отдельного ValueExpression.Поэтому, если вам нужно создать ValueExpression программно, используя другой ValueExpression varMapper, вы можете сделать что-то вроде этого:

VariableMapper varMapper = new DefaultVariableMapper();
varMapper.setVariable(mappingName, component.getValueExpression(mappedAttributeName));
return new ValueExpressionImpl(expression, null, null, varMapper, expectedType);
...