Суть в том, что слово reference в выражении «передать по ссылке» означает нечто совершенно отличное от обычного значения слова reference в Java.
Обычно в Java ссылка означает ссылку на объект . Но технические термины проходят по ссылке / значению из теории языка программирования, говорят о ссылке на ячейку памяти, в которой хранится переменная , что является чем-то совершенно другим.
Проблема заключалась в контексте #{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()
в компоненте подложки не будет вызываться.
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