嵌套 JSF 复合组件导致堆栈溢出异常

2024-03-10

问题

当我尝试将复合组件嵌套在其自身中,并使用一些逻辑来结束无限递归时,我收到堆栈溢出异常。我的理解是<c:xxx>标签在视图构建时运行 https://stackoverflow.com/a/3343681/2187042所以我没想到会像我想象的那样构建无限的视图。

这是复合组件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>

这是它的使用方式

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

堆栈溢出异常

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)

问题

如何在不接收堆栈溢出异常的情况下将复合组件(或类似组件)嵌套在自身内部(达到非预定义的深度)

为什么我想要这个

我有任意嵌套的数据,我想在 RichFaces 的嵌套 collapsibleSubTable 中表示,非常欢迎我的方法的替代方案


问题出在以下背景下#{cc}以及复合属性的状态性。这#{cc}在嵌套复合引用的任何属性中itself而不是父母。该属性是有状态的意味着#{cc}对每个孩子进行重新评估,最终参考itself而不是父母。因此堆栈溢出。它在无限循环中评估自身的深度。

我通过使用支持组件使其无状态来欺骗属性的有状态性,如下所示,该组件立即评估它并将其分配为组件属性:

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

并且,在实现中,您应该在测试中引用无状态属性,并在嵌套复合引用中引用父级属性(因为#{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()在支持组件中不会被调用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌套 JSF 复合组件导致堆栈溢出异常 的相关文章

随机推荐

  • 使用 Node 的 Google API 批量请求

    我注意到 Google 最近从他们的 Node 客户端删除了批量请求 https github com google google api nodejs client blob 0db674b7d3a04cf65e223f876cf7b3f
  • 使用专用网络从 Google Compute Engine 访问 Google Cloud SQL

    是否可以使用专用网络从 Google Compute Engine 访问 Google Cloud SQL Google Cloud SQL 似乎看到了 Google Compute Engine 实例的公共网络 IP 并且 Web 控制台
  • 在 React JS 中使用颜色控制时的警告

    我将 React JS 与 Babel 和 Webpack 一起使用 一切都与我的其他脚本 甚至使用颜色模块的脚本 一起正常工作 但是 我的脚本之一给了我以下错误 指定的值 不符合要求的格式 这 格式为 rrggbb 其中 rr gg bb
  • 无法更新 Xamarin for Visual Studio

    我最近不得不重新安装我的电脑 我重新安装了VS2015 Community 然后我从 www xamarin com download 安装了 Xamarin 每当我打开 Visual Studio 时都会收到以下通知 尽管当我点击它时什么
  • remove() 方法太慢

    我在读取内存痕迹时遇到问题 我已阅读它并将页面及其参考保存在地图上 地图结构 Map
  • 排序比较计数器

    我有这段代码 可以对填充有随机数的数组进行排序 并计算完成排序所需的数字比较 我正在使用排序方法选择冒泡和合并排序 我有选择和气泡的计数器 但没有合并的计数器 我不知道把它放在哪里 这可能是一个简单的答案 但我就是无法让它发挥作用 Code
  • 使用 Winforms 应用程序部署 SQL Server 数据库

    我创建了一个基于 SQL DB 的 winforms 应用程序 我想将其部署在客户端计算机上 该程序是单用户桌面应用程序 意见于this https stackoverflow com questions 1813241 how to de
  • GitHub 从之前的提交中分叉了一个存储库

    我在 GitHub 上找到了一个存储库 我想分叉 但不是当前版本 我想分叉该存储库 因为它有相当多的提交回来 这可能吗 该存储库尚未标记任何版本 因此我不确定如何执行此操作 显然 我可以复制该提交中的代码 但我更愿意分叉 因为这样我就可以将
  • HBase 上的 Thrift 有性能基准吗?

    我有一个可以将大量数据写入 hbase 的系统 系统是用c 编写的 发现hbase有其他语言的thrift接口 我的问题是 HBase 上的 Thrift 有性能基准吗 与java原生api相比 最劣势是什么 我推荐最近关于这个主题的两篇博
  • PS 脚本正在导出空的 CSV

    我花了很长时间试图理解为什么这个脚本没有按预期工作 这是一个简单的脚本 我尝试在其中导入 CSV 选择我想要的几列 然后导出 CSV 并复制自身 基本上 我们已经存档了数据 由于内存大小限制 我只需要从另一个项目中获取几列 这个脚本非常简单
  • 在 Android Studio 上将模块或项目导入为库

    我想在我的动态壁纸项目中使用 HoloEverywhere HE Preferences AddOn 该项目即将完成 我只需要它从 android 2 3 到 4 4 看起来相同 所以我继续按照指南从 GitHub 获取 HE 在 Demo
  • 水豚无法使用 action_cable

    我正在使用带有操作电缆的 Rails 5 beta 3 集成在开发中运行良好 但是当我尝试通过水豚运行功能测试时 它似乎没有命中通道操作 我正在使用 Portergeist 并将 puma 配置为水豚的服务器 我还使用 es5 shim 和
  • 在 Windows 上调试时 stderr 去了哪里?

    当尝试在 Windows 上调试程序时 我似乎无法找到推送到 stderr 的输出的去向 如何获取 stderr 输出 是否可以更改调试器级别设置 MSVC 9 以将 stderr 重定向到 UI 的某些部分 更新 我还没有研究过TRACE
  • 在 Android 类相机中将自动对焦放在哪里

    我正在尝试使用自动对焦 我不知道在哪里放置自动对焦 有人知道如何实现自动对焦吗 预习班 package com marakana import java io IOException import android content Conte
  • 使用 Auth 获取数据透视表中用户的角色

    我有以下数据库结构 使用数据透视表连接用户和角色表 用户表包含所有信息 例如电子邮件和密码 而角色表定义不同的角色 角色表 1 gt 管理员 2 gt 编码器 3 gt 推销员 4 gt 技术 现在角色被定义为多对多 因为有一些编码器也被分
  • 从哪里可以获得 libpq 源代码?

    我想编写使用 Postgresql 作为 DBMS 的应用程序 要编写客户端应用程序 我需要 libpq 库和头文件吗 如果是的话我会在哪里获得 libpq 库和头文件 Libpq 包含在完整的 PostgreSQL 源代码中 您可以只使用
  • Java NIO ByteBuffer,翻转后写入

    我是 Java ByteBuffers 的新手 想知道翻转后写入 ByteBuffer 的正确方法是什么 在我的用例中 我将一个输出缓冲区写入套接字 outBuffer flip Non blocking SocketChannel int
  • 使用不带 src 属性的 vuejs 在 iframe 中渲染组件

    我想在这个 iframe 中渲染组件 是否有在 iframe 中创建 html 元素或渲染组件的选项 new Vue el frame store store router router render component 对我来说最简单的方
  • 本地化 Angular Material 日期选择器中的日期值

    我正在使用 Angular Material 日期选择器 我的问题是 当我向 Web Api 控制器发送日期时 我得到的日期小于我在表单中选择的日期 我认为这是因为日期值没有本地化 我想知道的是如何localize the date in
  • 嵌套 JSF 复合组件导致堆栈溢出异常

    问题 当我尝试将复合组件嵌套在其自身中 并使用一些逻辑来结束无限递归时 我收到堆栈溢出异常 我的理解是