Primefaces的treeTable中的java.lang.StackOverFlow

时间:2012-11-16 05:19:21

标签: 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}" />
    <p:column> ..... </p:column>
 <p/treeTable>

SkillManager:

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

}

LazySkillTreeNode:

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

}

LazyTreeNode:

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

}

一切正常,但是如果添加/删除元素(在所有这些操作之后我们多次调用方法 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>

其他问题我没有任何关于错误的信息。日志文件中没有信息。在server.log中没有任何内容。

我们使用:JSF(Mojarra 2.14),Primefaces 3.41,JBOSS 7。

1 个答案:

答案 0 :(得分:2)

最后错误是在Controller类中的方法:

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)”行中; 您必须通过第一个参数而不是实体对象传递错误消息。 出现错误是因为它是Skill类的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;
}

}

你可以在方法中看到

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

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