2015-05-01 18 views
8

Vấn đề

Khi tôi cố gắng để làm tổ một phần composite trong chính nó, với một số logic để kết thúc đệ quy vô hạn tôi nhận được một ngoại lệ stack overflow. Sự hiểu biết của tôi là <c:xxx> tags run at view build time vì vậy tôi đã không mong đợi để có một xây dựng xem vô hạn như tôi đoán đã được các trường hợp.Nested JSF Linh kiện composite dẫn đến một ngoại lệ Stack Overflow

Đây là thành phần hỗn simpleNestable.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:composite="http://java.sun.com/jsf/composite" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:em="http://xmlns.jcp.org/jsf/composite/emcomp" 

    xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"> 

    <h:head> 
     <title>This content will not be displayed</title> 
    </h:head> 
    <h:body> 
     <composite:interface> 
      <composite:attribute name="depth" required="true" type="java.lang.Integer"/> 
     </composite:interface> 

     <composite:implementation> 
      <c:if test="#{cc.attrs.depth lt 3}"> 
       #{cc.attrs.depth} 
       #{cc.attrs.depth+1} 
       <em:simpleNestable depth="#{cc.attrs.depth+1}" /> 

      </c:if> 

     </composite:implementation> 
    </h:body> 
</html> 

Đây là cách nó được sử dụng

<h:head> 
    <title>Facelet Title</title> 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
    <h:outputStylesheet name="./css/default.css"/> 
    <h:outputStylesheet name="./css/cssLayout.css"/> 
</h:head> 
<h:body>   
    <emcomp:simpleNestable depth="1"/> 

</h:body> 

Các Stack Overflow Exception

java.lang.StackOverflowError 
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109) 
    at javax.faces.component.UIComponentBase$AttributesMap.get(UIComponentBase.java:2407) 
    at com.sun.faces.el.CompositeComponentAttributesELResolver$ExpressionEvalMap.get(CompositeComponentAttributesELResolver.java:393) 
    at javax.el.MapELResolver.getValue(MapELResolver.java:199) 
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176) 
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203) 
    at com.sun.el.parser.AstValue.getValue(AstValue.java:140) 
    at com.sun.el.parser.AstValue.getValue(AstValue.java:204) 
    at com.sun.el.parser.AstPlus.getValue(AstPlus.java:60) 
    at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:226) 
    at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50) 
    at com.sun.faces.facelets.el.ContextualCompositeValueExpression.getValue(ContextualCompositeValueExpression.java:158) 
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109) 
    at javax.faces.component.UIComponentBase$AttributesMap.get(UIComponentBase.java:2407) 
    at com.sun.faces.el.CompositeComponentAttributesELResolver$ExpressionEvalMap.get(CompositeComponentAttributesELResolver.java:393) 
    at javax.el.MapELResolver.getValue(MapELResolver.java:199) 
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176) 
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203) 
    at com.sun.el.parser.AstValue.getValue(AstValue.java:140) 
    at com.sun.el.parser.AstValue.getValue(AstValue.java:204) 
    at com.sun.el.parser.AstPlus.getValue(AstPlus.java:60) 

Các Câu hỏi

Làm thế nào tôi có thể hợp tổ thành phần (hoặc tương tự) trong bản thân (đến độ sâu không được xác định trước) mà không nhận được một ngoại lệ stack overflow

Tại sao tôi muốn điều này

Tôi có dữ liệu lồng nhau tùy ý mà tôi muốn đại diện trong một collapsibleSubTable lồng nhau từ RichFaces, các lựa chọn thay thế cho cách tiếp cận của tôi rất được hoan nghênh

+0

@BalusC Tôi không hiểu, đây không phải là vấn đề java-ee? Không phải là một phần của java-ee? –

+0

Đó là JSF cụ thể. Q này không thú vị đối với những người dùng Java EE không sử dụng JSF. – BalusC

Trả lời

6

Sự cố nằm trong ngữ cảnh của #{cc} và tính trạng thái của thuộc tính tổng hợp. #{cc} trong bất kỳ thuộc tính nào của các tham chiếu tổng hợp lồng nhau chính nó thay vì cha mẹ. Thuộc tính là trạng thái có nghĩa là số #{cc} được đánh giá lại ở mọi trẻ, từ đó cuối cùng tham chiếu chính nó thay vì cha mẹ. Do đó tràn ngăn xếp. Nó đánh giá độ sâu của chính nó trong một vòng lặp vô hạn.

tôi lừa các statefulness của thuộc tính bằng cách làm cho nó không quốc tịch sử dụng một thành phần ủng hộ như sau đó ngay lập tức đánh giá nó và gán nó như là một tài sản thành phần:

@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; 
    } 

} 

Đó là được khai báo trong giao diện của componentType như sau :

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

và, trong việc thực hiện, bạn nên tham khảo trong thử nghiệm là tài sản quốc tịch và trong tài liệu tham khảo tổng hợp lồng một trong những phụ huynh (vì #{cc} trong thuộc tính của composite lồng nhau tham chiếu hỗn hợp lồng nhau tự):

<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> 

tôi chỉ thay đổi ý nghĩa của "chiều sâu" ở đây là theo chiều ngược lại để nó chỉ là khai báo từ khách hàng trên mà không cần phải chỉnh sửa nó trong thực hiện.Vì vậy, trong các khách hàng mà bạn có thể nói depth="#{3}" nếu bạn muốn 3 đứa con lồng nhau:

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

Lưu ý tầm quan trọng của nó là một biểu thức EL chứ không phải là một chữ. Nếu không, setValueExpression() trong thành phần sao lưu sẽ không được gọi.

+0

Với điều này, nó tuyên bố rằng "Các thuộc tính sau đây là bắt buộc, nhưng không có giá trị nào được cung cấp cho chúng: chiều sâu". Tôi có thể xem toàn bộ của bạn để xem cách bạn xác định chiều sâu thuộc tính không? –

+0

Ngoài ra chỉ cần kiểm tra: là 'cc' và' my': 'xmlns: cc =" http: // xmlns.jcp.org/jsf/composite' và 'xmlns: my =" http://xmlns.jcp .org/jsf/composite/emcomp' –

+0

Giao diện chỉ có thuộc tính độ sâu chính xác như bạn có. Các không gian tên thực sự là như vậy. Tôi chỉ chuẩn hóa chúng (để ngăn chặn độc giả tương lai gặp vấn đề tương tự khi nghĩ rằng đó là phong cách "ủng hộ" .. "Nhưng BalusC đã sử dụng nó như thế!" .vv: /). – BalusC

Các vấn đề liên quan