3

我使用这段代码:

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

}

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

4

1 回答 1

2

最后错误出现在 Controller 类 where 方法中:

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(),而 parentSkill 上又调用 toString() ...无限递归。

于 2012-11-26T11:27:00.077 回答