Jsf 2 Primefaces'中的java.lang.StackOverFlow;s树型

Jsf 2 Primefaces'中的java.lang.StackOverFlow;s树型,jsf-2,tree,primefaces,jboss7.x,stack-overflow,Jsf 2,Tree,Primefaces,Jboss7.x,Stack Overflow,我使用以下代码: JSF: <p:treeTable id="treeSkill" value="#{skillManager.rootSkill}" var="skill" selectionMode="single" widgetVar="skillsTreeTable" style="border: 0;"> <p:ajax event="expand" listener="#{skillManager.expandNodeListener

我使用以下代码:

JSF:

<p:treeTable id="treeSkill" value="#{skillManager.rootSkill}"
    var="skill" selectionMode="single" widgetVar="skillsTreeTable"
style="border: 0;">
    <p:ajax event="expand"
        listener="#{skillManager.expandNodeListener}" />
    <p:column> ..... </p:column>
 <p/treeTable>
@Named
@SessionScoped
public class SkillManager implements Serializable {
    private static final long serialVersionUID = 1L;

    private TreeNode rootSkill;

    public SkillManager() {
       initSkillTree();
    }

    public void expandNodeListener(NodeExpandEvent nee) {
       TreeNode treeNode = nee.getTreeNode();

       if (treeNode instanceof FetchChildren)
          ((FetchChildren) treeNode).fetchChildren();

       if (treeNode instanceof LazySkillTreeNode)
          ((LazySkillTreeNode) treeNode).fetchSubchildren();
    }

    private void initSkillTree() {
       rootSkill = new DefaultTreeNode("Root", null);
       Skill realRootSkill = HrDaoFactory.getInstance().getSkillDAO().getRootSkill();
       TreeNode realRootNode = new LazySkillTreeNode(realRootSkill, rootSkill);

       for (Skill skill : realRootSkill.getChildrensSkills()) {
           LazySkillTreeNode node = new LazySkillTreeNode(skill, realRootNode);
           node.fetchChildren();
       }

       RequestContext.getCurrentInstance().update("woCatalogTabView:skillTreeForm");
    }
public class LazySkillTreeNode extends LazyTreeNode implements FetchChildren {
    private static final long serialVersionUID = 8856168173751148652L;

    private boolean childrenFetched;

    public LazySkillTreeNode(Object data, TreeNode parent) {
       super(data, parent);
    }

    @Override
    public void fetchChildren() {
    if (childrenFetched)
        return;

    for (Skill skill : ((Skill) super.getData()).getChildrensSkills())
        new LazySkillTreeNode(skill, this);

    childrenFetched = true;
    }

}
public abstract class LazyTreeNode extends DefaultTreeNode {
    private static final long serialVersionUID = 8839307424434170537L;

    private boolean subChildrenFetched;

    public LazyTreeNode(Object data, TreeNode parent) {
        super(data, parent);
    }

    public void fetchSubchildren() {
    if (subChildrenFetched || isLeaf())
        return;

    List<TreeNode> treeNodeList = getChildren();

    for (TreeNode node : treeNodeList) {
        if (node instanceof FetchChildren)
        ((FetchChildren) node).fetchChildren();
    }

    subChildrenFetched = true;
    }

}
}

LazySkillTreeNode:

<p:treeTable id="treeSkill" value="#{skillManager.rootSkill}"
    var="skill" selectionMode="single" widgetVar="skillsTreeTable"
style="border: 0;">
    <p:ajax event="expand"
        listener="#{skillManager.expandNodeListener}" />
    <p:column> ..... </p:column>
 <p/treeTable>
@Named
@SessionScoped
public class SkillManager implements Serializable {
    private static final long serialVersionUID = 1L;

    private TreeNode rootSkill;

    public SkillManager() {
       initSkillTree();
    }

    public void expandNodeListener(NodeExpandEvent nee) {
       TreeNode treeNode = nee.getTreeNode();

       if (treeNode instanceof FetchChildren)
          ((FetchChildren) treeNode).fetchChildren();

       if (treeNode instanceof LazySkillTreeNode)
          ((LazySkillTreeNode) treeNode).fetchSubchildren();
    }

    private void initSkillTree() {
       rootSkill = new DefaultTreeNode("Root", null);
       Skill realRootSkill = HrDaoFactory.getInstance().getSkillDAO().getRootSkill();
       TreeNode realRootNode = new LazySkillTreeNode(realRootSkill, rootSkill);

       for (Skill skill : realRootSkill.getChildrensSkills()) {
           LazySkillTreeNode node = new LazySkillTreeNode(skill, realRootNode);
           node.fetchChildren();
       }

       RequestContext.getCurrentInstance().update("woCatalogTabView:skillTreeForm");
    }
public class LazySkillTreeNode extends LazyTreeNode implements FetchChildren {
    private static final long serialVersionUID = 8856168173751148652L;

    private boolean childrenFetched;

    public LazySkillTreeNode(Object data, TreeNode parent) {
       super(data, parent);
    }

    @Override
    public void fetchChildren() {
    if (childrenFetched)
        return;

    for (Skill skill : ((Skill) super.getData()).getChildrensSkills())
        new LazySkillTreeNode(skill, this);

    childrenFetched = true;
    }

}
public abstract class LazyTreeNode extends DefaultTreeNode {
    private static final long serialVersionUID = 8839307424434170537L;

    private boolean subChildrenFetched;

    public LazyTreeNode(Object data, TreeNode parent) {
        super(data, parent);
    }

    public void fetchSubchildren() {
    if (subChildrenFetched || isLeaf())
        return;

    List<TreeNode> treeNodeList = getChildren();

    for (TreeNode node : treeNodeList) {
        if (node instanceof FetchChildren)
        ((FetchChildren) node).fetchChildren();
    }

    subChildrenFetched = true;
    }

}
LazyTreeNode:

<p:treeTable id="treeSkill" value="#{skillManager.rootSkill}"
    var="skill" selectionMode="single" widgetVar="skillsTreeTable"
style="border: 0;">
    <p:ajax event="expand"
        listener="#{skillManager.expandNodeListener}" />
    <p:column> ..... </p:column>
 <p/treeTable>
@Named
@SessionScoped
public class SkillManager implements Serializable {
    private static final long serialVersionUID = 1L;

    private TreeNode rootSkill;

    public SkillManager() {
       initSkillTree();
    }

    public void expandNodeListener(NodeExpandEvent nee) {
       TreeNode treeNode = nee.getTreeNode();

       if (treeNode instanceof FetchChildren)
          ((FetchChildren) treeNode).fetchChildren();

       if (treeNode instanceof LazySkillTreeNode)
          ((LazySkillTreeNode) treeNode).fetchSubchildren();
    }

    private void initSkillTree() {
       rootSkill = new DefaultTreeNode("Root", null);
       Skill realRootSkill = HrDaoFactory.getInstance().getSkillDAO().getRootSkill();
       TreeNode realRootNode = new LazySkillTreeNode(realRootSkill, rootSkill);

       for (Skill skill : realRootSkill.getChildrensSkills()) {
           LazySkillTreeNode node = new LazySkillTreeNode(skill, realRootNode);
           node.fetchChildren();
       }

       RequestContext.getCurrentInstance().update("woCatalogTabView:skillTreeForm");
    }
public class LazySkillTreeNode extends LazyTreeNode implements FetchChildren {
    private static final long serialVersionUID = 8856168173751148652L;

    private boolean childrenFetched;

    public LazySkillTreeNode(Object data, TreeNode parent) {
       super(data, parent);
    }

    @Override
    public void fetchChildren() {
    if (childrenFetched)
        return;

    for (Skill skill : ((Skill) super.getData()).getChildrensSkills())
        new LazySkillTreeNode(skill, this);

    childrenFetched = true;
    }

}
public abstract class LazyTreeNode extends DefaultTreeNode {
    private static final long serialVersionUID = 8839307424434170537L;

    private boolean subChildrenFetched;

    public LazyTreeNode(Object data, TreeNode parent) {
        super(data, parent);
    }

    public void fetchSubchildren() {
    if (subChildrenFetched || isLeaf())
        return;

    List<TreeNode> treeNodeList = getChildren();

    for (TreeNode node : treeNodeList) {
        if (node instanceof FetchChildren)
        ((FetchChildren) node).fetchChildren();
    }

    subChildrenFetched = true;
    }

}
公共抽象类LazyTreeNode扩展了DefaultTreeNode{
私有静态最终长serialVersionUID=883930742434170537L;
私有布尔子类获取;
公共LazyTreeNode(对象数据,TreeNode父级){
超级(数据、父级);
}
公共子项(){
if(子项获取的| | isLeaf())
返回;
List treeNodeList=getChildren();
for(TreeNode节点:treeNodeList){
if(FetchChildren的节点实例)
((FetchChildren)节点);
}
subChildrenFetched=true;
}
}
一切正常,但如果添加/删除元素(在所有这些操作之后,我们调用方法initSkillTree()来重建树)很多次,或者如果有2个或更多用户开始这样做,我们开始从服务器收到以下字符串的响应:

<?xml version='1.0' encoding='UTF-8'?>
<partial-response><error><error-name>class java.lang.StackOverflowError</error-name><error-message><![CDATA[]]></error-message></error></partial-response>

类java.lang.StackOverflowerr
其他问题,我没有任何关于错误的信息。日志文件中没有信息。在server.log中,不向任何对象记录任何内容


我们使用:JSF(Mojarra 2.14)、Primefaces 3.41、JBOSS 7.

,最终错误出现在控制器类中,其中方法:

public void addOrUpdateSkill(Skill skill) {
Session session = null;
try {
    session = HibernateUtil.getCurrentSession();
    session.beginTransaction();
    session.saveOrUpdate(skill);
    session.getTransaction().commit();
    evictAllSkillsFromSession();
} catch (Throwable e) {
    logger.fatal(skill, e);
    if (session.getTransaction() != null && session.getTransaction().isActive())
    session.getTransaction().rollback();
    throw new RuntimeException(e);
}
}
堆栈跟踪出现在“logger.fatal(skill,e);”行中 必须通过第一个参数而不是实体对象传递错误消息。 出现错误,因为它是技能类的toString()方法实现:

@Entity
@Table(name = "SKILLS", schema = AppData.HR_SCHEMA)
public class Skill implements Serializable {
private static final long serialVersionUID = -2728239519286686549L;

@Id
@SequenceGenerator(name = "SKILLS_ID_GENERATOR", sequenceName = AppData.HR_SCHEMA + ".SKILLS_ID_SEQ")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SKILLS_ID_GENERATOR")
private BigDecimal id;

@Column(name = "NAME_ENG")
private String nameEng;

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "UPDATED_AT")
private Date updatedAt;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "UPDATED_BY", referencedColumnName = "USER_ID")
private User updatedBy;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PARENT_ID")
private Skill parentSkill;

@OneToMany(mappedBy = "parentSkill", fetch = FetchType.LAZY, orphanRemoval = true)
private List<Skill> childrensSkills;

@Column(name = "DESCRIPTION")
private String description;

@OneToMany(orphanRemoval = true, mappedBy = "skill")
private List<SkillJoinedAction> skillJoinedActions;

@OneToMany(orphanRemoval = true, mappedBy = "skill")
private List<SkillJoinedEmployee> skillJoinedEmployees;

public Skill() {
}

public Skill(String nameEng, User updateBy, String description) {
this.nameEng = nameEng;
this.updatedBy = updateBy;
this.updatedAt = new Date();
this.setDescription(description);
}

public BigDecimal getId() {
return id;
}

public void setId(BigDecimal id) {
this.id = id;
}

public String getNameEng() {
return this.nameEng;
}

public void setNameEng(String nameEng) {
this.nameEng = nameEng;
}

public Date getUpdatedAt() {
return this.updatedAt;
}

public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}

public User getUpdatedBy() {
return updatedBy;
}

public void setUpdatedBy(User updatedBy) {
this.updatedBy = updatedBy;
}

public List<Skill> getChildrensSkills() {
return childrensSkills;
}

public void setChildrensSkills(List<Skill> childrensSkills) {
this.childrensSkills = childrensSkills;
}

public Skill getParentSkill() {
return parentSkill;
}

public void setParentSkill(Skill parentSkill) {
this.parentSkill = parentSkill;
}

@Override
public String toString() {
return "Skill [id=" + id + ", nameEng=" + nameEng + ", updatedAt=" + updatedAt + ", updatedBy=" + updatedBy + ", parentSkill="
    + parentSkill + ", childrensSkills=" + childrensSkills + "]";
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public List<SkillJoinedAction> getSkillJoinedActions() {
return skillJoinedActions;
}

public void setSkillJoinedActions(List<SkillJoinedAction> skillJoinedActions) {
this.skillJoinedActions = skillJoinedActions;
}

public List<SkillJoinedEmployee> getSkillJoinedEmployees() {
return skillJoinedEmployees;
}

public void setSkillJoinedEmployees(List<SkillJoinedEmployee> skillJoinedEmployees) {
this.skillJoinedEmployees = skillJoinedEmployees;
}

在parentSkill上被称为方法toString(),而parentSkill在childrensSkills上又调用了方法toString()。。。无限递归。

正如您所注意到的,您没有任何堆栈跟踪。也许您可以跟踪直到引发异常以查看它发生的位置?如果我对每个请求都进行调试,这是可能的吗?或者,如果有什么好方法可以找到错误发生的地方呢?在日志文件中找不到stacktrace是没有意义的,我是一个Tomcat的家伙,可能在其他地方有日志文件……是的。如果有人建议如何接收有关此错误的更多信息,这将是一件好事。我认为此链接可以帮助您:在Tomcat中,我有一个文件catalina.out,其中基本上包含来自服务器的stdout/stderr。