StackOverflowError в рекурсии композитных компонентов JSF [дубликат]

Суть в том, что слово reference в выражении «передать по ссылке» означает нечто совершенно отличное от обычного значения слова reference в Java.

Обычно в Java ссылка означает ссылку на объект . Но технические термины проходят по ссылке / значению из теории языка программирования, говорят о ссылке на ячейку памяти, в которой хранится переменная , что является чем-то совершенно другим.

9
задан Community 23 May 2017 в 11:53
поделиться

1 ответ

Проблема заключалась в контексте #{cc} и состоятельности составного атрибута. #{cc} в любом атрибуте вложенных композитных ссылок непосредственно вместо родителя. Атрибут, являющийся stateful, означает, что #{cc} был переоценен в каждом дочернем элементе, который, в свою очередь, в конечном итоге ссылается на себя вместо родителя. Следовательно, переполнение стека. Он оценивает глубину самого себя в бесконечном цикле.

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

@FacesComponent("treeComposite")
public class TreeComposite extends UINamingContainer {

    private Integer depth;

    @Override
    public void setValueExpression(String name, ValueExpression binding) {
        if ("depth".equals(name)) {
            setDepth((Integer) binding.getValue(getFacesContext().getELContext()));
        }
        else {
            super.setValueExpression(name, binding);
        }
    }

    public Integer getDepth() {
        return depth;
    }

    public void setDepth(Integer depth) {
        this.depth = depth;
    }

}

, который должен быть объявлен в интерфейсе componentType, как показано ниже:

<cc:interface componentType="treeComposite">
    <cc:attribute name="depth" type="java.lang.Integer" />
</cc:interface>

И в реализации вы должны в тестовой ссылке использовать свойство stateless и вложенную составную ссылку один из родительских (поскольку #{cc} в атрибуте вложенного композита ссылается на сам вложенный композит):

<cc:implementation>
    <br />We're at depth #{cc.depth}.
    <c:if test="#{cc.depth gt 0}">
        <my:tree depth="#{cc.parent.depth - 1}" />
    </c:if>
</cc:implementation>

Я только изменил значение «глубина» здесь, чтобы быть наоборот так что он просто декларативный от клиента без необходимости редактировать его в реализации. Итак, в клиенте вы должны сказать depth="#{3}", если хотите 3 вложенных дочерних элемента:

<my:tree depth="#{3}" />

Обратите внимание на важность того, что это выражение EL, а не буквальное. В противном случае setValueExpression() в компоненте подложки не будет вызываться.

7
ответ дан BalusC 20 August 2018 в 09:50
поделиться
  • 1
    – Richard Tingle 1 May 2015 в 15:29
  • 2
    Также просто проверьте: ваши cc и my: xmlns:cc="http://xmlns.jcp.org/jsf/composite и xmlns:my="http://xmlns.jcp.org/jsf/composite/emcomp – Richard Tingle 1 May 2015 в 15:30
  • 3
    Интерфейс имеет только атрибут глубины точно так же, как и у вас. Пространства имен действительно такие. Я просто канонизировал их (чтобы будущие читатели не имели такую ​​же проблему, чтобы думать, что это «защищенный» стиль. «Но BalusC использовал это так» и т. Д.: /). – BalusC 1 May 2015 в 15:34
  • 4
    – Karl Richter 4 May 2018 в 14:08
Другие вопросы по тегам:

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