JSF:如何防止构建阶段由于递归而导致的堆栈溢出(尽管进行了渲染测试)

2023-12-02

对于没有在专用测试用例中抽象这个问题表示歉意,我希望来自真实项目的示例足够简单来描述问题。

我有一个 JavaEE/JPA2/JSF Web 应用程序,其中每个 @Entity 元素(或子类)都有一个模板化 view.xhtml 页面和一个标准链接生成器复合组件 util:view_link.xhtml,以数据库 ID 作为参数作为 GET 调用。每个视图页面的一部分(仅)代表专家系统摘要;该部分可以抽象为复合组件,以包含在视图页面或其他地方。

我引入了一个 Primefaces p:dialog 模式弹出窗口,用于在单击视图链接旁边显示的小状态图标时显示专家系统摘要部分(以及任何其他诊断)。如果让状态图标用 x 表示,它看起来像这样:

x 按 ID 链接到元素

单击“Link_to_Element_by_ID”,将显示完整视图页面。

单击“x”图标(专家系统测试失败指示器),会弹出 p:dialog,其中包含专家系统摘要(仅)。

因此,视图页面的专家系统部分作为复合组件共享。

但如果出现以下情况,这可能会导致递归和 Stackoverflow:

  1. 弹出的 p:dialog 专家系统摘要显示正在检查的元素的状态图标指示器。

  2. 我添加了其他元素视图链接以及状态指示器(它们本身会启动一个 p:dialog 以获取专家系统摘要)。

我尝试过使用递归阻止属性“preventRecursionOnDialog”来使用渲染测试,但它失败了,显然是因为递归是在构建阶段发生的。

问:如何使用测试变量阻止可能的递归?

另外,我尝试过 c:if 测试而不是 JSF“渲染”测试,但似乎测试的变量在 @ViewScoped 下不可用。

例如,对于 Activity 元素,其中 util_primefaces:dialog_summary 只是 p:dialog 的自定义封装。

来自 util:status_activity.xhtml:

     <composite:attribute 
        name="activity"
        required="true"
        type="com.example.entity.Activity"
      />
    <composite:attribute
        name="preventRecursionOnDialog"
        required="false"
        default="false"
        type="java.lang.Boolean"
        />
</composite:interface>

<composite:implementation> 
    <util_primefaces:dialog_summary 
        header="Expert system summary report"
        rendered="#{not cc.attrs.preventRecursionOnDialog}"
        element="#{cc.attrs.activity}">

        <!-- causes StackOverflowError -->

        <util:warn_insufficient_subactivities 
            activityContainer="#{cc.attrs.activity}"
            humanTypeDescription="composite activity"
            preventRecursionOnDialog="true"
            />

        <util:expertsystem_activity activity="#{cc.attrs.activity}"/>

    </util_primefaces:dialog_summary>
    ..
    <span 
        onclick="#{not cc.attrs.preventRecursionOnDialog ? ('dialog'.concat(cc.attrs.activity.id).concat('.show();')) : ''}" 
        style="float:left;" 
        class="icon-completed-#{cc.attrs.activity.acceptedEffective}-small"
        title=".."
        >&nbsp;</span>

util:warn_insufficient_subactivities(显示复合活动的哪些子活动尚未通过专家系统测试)可能会导致递归:

    <cc:interface>
    <cc:attribute name="activityContainer" required="true" type="com.example.entity.IActivityContainer"/>
    <cc:attribute name="humanTypeDescription" required="true" type="java.lang.String"/>
    <cc:attribute
        name="preventRecursionOnDialog"
        required="false"
        default="false"
        type="java.lang.Boolean"
        /> 
</cc:interface> 

<cc:implementation>     
    <h:panelGroup 
        rendered="#{not cc.attrs.activityContainer.sufficientSubActivitiesAccepted}">
        <util:warn_box 
            message=".."
            >
            <!-- CAUTION: can cause Stackoverflow when list included in expertsystem p:dialog popup -->
            <util:list_activity_compact 
                list="#{cc.attrs.activityContainer.activities}" 
                preventRecursionOnDialog="#{cc.attrs.preventRecursionOnDialog}"
                rendered="#{not cc.attrs.preventRecursionOnDialog}"
                />                
        </util:warn_box>

util:list_activity_compact 显示一个带有状态图标指示器的列表(它反过来可以提供一个带有专家系统摘要的弹出 p:dialog,并且可以递归)和 util:view_link:

    <cc:interface>

    <cc:attribute 
        name="list" required="true" type="java.util.List"
        />

    <cc:attribute
        name="preventRecursionOnDialog"
        required="false"
        default="false"
        type="java.lang.Boolean"
        />

</cc:interface>

<cc:implementation>
    <h:panelGroup display="block">
        <ul class="view-field-list-medium">
            <ui:repeat var="a" value="#{cc.attrs.list}">
                <li class="view-field-list">
                    <util:status_activity 
                        activity="#{a}" 
                        preventRecursionOnDialog="#{cc.attrs.preventRecursionOnDialog}"/> 
                    <util:view_link element="#{a}"/>
                </li>
            </ui:repeat>
        </ul>
    </h:panelGroup>
</cc:implementation>

问题的要点是渲染的测试=“#{not cc.attrs.preventRecursionOnDialog}”不足以阻止递归,即使未渲染将递归的部分(被渲染的测试阻止),似乎在 JSF 构建阶段,递归仍然可能发生。


顺便说一句,当我只想在类型选择的子集中渲染绑定到类型的特定复合组件时,我经常遇到类似的问题;在“渲染”中执行类型测试不足以防止类型错误。想象一下,“值”可能是包括 Activity 在内的许多 Element 子类之一,但只想显示 Activity 的以下复合组件部分:

        <util:component_for_Activity_only 
            activity="#{cc.attrs.value}"
            rendered="#{cc.attrs.value['class'].simpleName=='Activity'}"
            />

(cf. EL表达式语言中的instanceof检查,并注意基于类字符串的类型测试解决方案不是很灵活,它不适用于子类或接口测试。)

同样,尝试使用“渲染”来阻止调用是不够的,似乎类型测试在构建阶段就已经失败了。递归问题的解决方案也可以解决这个问题。甚至JSF2中(终于)引入了instanceof(请在这里投票http://java.net/jira/browse/JSP_SPEC_PUBLIC-113) 如果仅用于“渲染”,则不会有帮助,


经过进一步研究和试验回答自己的问题。

首先,感谢meron,您的回答并没有完全回答我的问题,但让我走上了正确的道路。

简而言之,自 Mojarra 2.1.18 起,您可以在 @ViewScoped 的构建阶段使用 c:if 测试来控制递归。就我而言,现在可以使用:

        <c:if test="#{not cc.attrs.preventRecursionOnDialog}">

与往常一样,我通过 BalusC 对其他帖子的贡献得到了这个答案(需要升级到 Mojarra >= 2.1.18 以及关于改进 @ViewScoped 中 JSTL 标签库处理的解释),其中包括:

https://java.net/jira/browse/JAVASERVERFACES-1492

JSF2 Viewscope 验证问题

http://balusc.blogspot.com.au/2010/06/benefits-and-pitfalls-of-viewscoped.html

JSF2 Facelets 中的 JSTL...有意义吗?

Java Server Faces 2.0 的主要缺点是什么?

我认为这件事对于任何与 JSF 合作的人来说都极其重要!在 @ViewScoped 中轻松控制构建内容(而不是渲染内容)的能力解决了许多问题并开启了许多可能性,我建议任何认真使用 JSF 的人花时间阅读 BalusC 在以上链接。

BalusC,如果您读到本文,请知道您是 JavaServer Faces 和 Enterprise Java 的真正英雄。我谨代表每一位 JSF 爱好者感谢您。

感谢 Ed Burns 和 Ted Goddard 在报告和解决此问题方面所做的出色工作:https://java.net/jira/browse/JAVASERVERFACES-1492这是 JSF2 的重大改进。

最后,我不得不使用一个肮脏的技巧在 NetBeans7.1+Glassfish3.1.1 上安装 Mojarra 2.1.21(由于第 3 方不兼容而需要),如下所述:JSF如何在Netbeans7.1中升级到Mojarra 2.1.21(只是子jsf-api.jar和jsf-impl.jar失败)

这对我的项目来说是一个很好的结果。如果没有 Stackoverflow 我会做什么:)

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

JSF:如何防止构建阶段由于递归而导致的堆栈溢出(尽管进行了渲染测试) 的相关文章

随机推荐

  • $_SERVER['REMOTE_ADDR'] 的问题

    我使用 SERVER REMOTE ADDR 它返回客户端 ip 地址 用户查看当前页面的 IP 地址 但现在 和相同的代码 它返回主机 ip 地址 我用 ip 位置检查了 ip 地址 问题是主机还是什么 感谢你 您应该查询HTTP X F
  • 体积的imfilter速度

    我正在研究一种算法 该算法需要过滤 3D 矩阵 非稀疏 512 3 来查找边缘 我只想找到每个切片中的边缘 所以我一直在执行以下操作 2D loop appaoch x y ndgrid floor 3 sigma ceil 3 sigma
  • APK 签名错误:无法从密钥库读取密钥

    我正在 intellij 和 gradle 下开发 Android 应用程序 并使用以下方式生成密钥库文件 keytool genkey v keystore my release key keystore alias alias name
  • 是什么意思[重复]

    这个问题在这里已经有答案了 这是代码 def my func f arg return f arg print lambda x 2 x x 5 gt gt gt
  • 控制笔记本相关表达式的 Rasterize[] 宽度

    Update向导先生的答案给出了像素完美的结果 但它仅适用于 Windows 并且会破坏剪贴板内容 我的答案应该适用于任何平台 但不太精确 例如它省略了输入 输出标签 但它确实允许设置光栅化宽度 这个问题我当时就出现了尝试为图像上传器制作预
  • WebStorm:如何美化 JavaScript 文件中引号中的 HTML

    我的中有以下块app component ts file Component selector my app template h1 title h1 h2 My Heroes h2 ul class heroes li li ul h2
  • 打开目录对话框

    我希望用户选择一个目录 用于保存我将生成的文件 我知道在 WPF 中我应该使用OpenFileDialog来自 Win32 但不幸的是 该对话框需要选择文件 如果我只是单击 确定 而不选择文件 它就会保持打开状态 我可以通过让用户选择一个文
  • 通过代码模拟触摸控制

    我正在尝试使用头部手势来浏览我的 Google Glass 应用程序 我能够识别头部姿势 例如向右看 向左看和向上看 他们每个人都有自己的方法来识别该手势时该怎么做 现在我需要在每个方法中模拟相应的触摸手势 所以它会认为我正在向左或向右滑动
  • C#:更改按钮背景颜色没有效果

    我在 Windows 窗体中使用 C 按钮时遇到问题 我以编程方式创建了许多按钮 然后将它们添加到表单中 有趣的是 除了修改按钮之外 对这些按钮 位置和大小 的每次修改BackColor很容易被执行 只有按钮的颜色保持不变 代码看起来像这样
  • Flash AS3 - 如何设置高质量录音

    目前 我正在使用 mic rate 100 这仅提供 63kbps Flash AS3 是否可以将比特率设置为高于 63kbps From the docs 可接受的值为 5 8 11 22 和 44 所以输入其中之一 根据文档 它的测量单
  • 如果没有父窗口,则无法在 PyQt 中创建新窗口

    我开始使用 PyQt 在 Python 中编写一个简单的文本编辑器 然后遇到了这个问题 对于 新文档 按钮 我想打开一个新的空文本编辑器 无论第一个窗口发生什么情况 它都会保持打开状态 问题是我让它显示窗口的唯一方法是发送self作为参数
  • 在经典的asp中读取csv文件。问题:列值被截断最多 300 个字符

    我有一个页面可以上传 csv 文件并保存到数据库中的表中 我正在使用下面的连接字符串来读取 csv 文件 set connection Server CreateObject ADODB Connection connection Open
  • 计算向量中零和一的百分比?

    我已经使用以下代码获得了矢量以及零和一的数量 u 1 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 transitions find u u 2 end u end 1 value u tr
  • Windows Phone 7 - 来电屏幕

    有没有办法在接到电话时将数据添加到来电屏幕 如果可能的话 我希望能够向该屏幕添加文本 Update 如果当前无法向该屏幕添加文本 是否有办法根据来电触发代码 您可以执行与来电相关的任何操作的唯一方法是通过 Obscured 事件得知此情况已
  • iOS 7 iPad Safari 横向innerHeight/outerHeight 布局问题

    我们发现 iOS 7 中 Safari 上高度为 100 的 Web 应用程序存在问题 似乎 window innerHeight 672px 与 window outerHeight 692px 不匹配 但仅限于横向模式 最终发生的情况是
  • filepicker.io Javascript API 调用导致不安全的 javascript 错误

    我目前正在使用 AngularJS 我想从我的上传控制器调用 filePicker pickAndStore 对 filepicker io API 函数的任何调用都会导致 不安全的 Javascript 尝试 错误 请求访问的帧具有 ht
  • SecurityError:操作不安全。使用 Htmlcanvas [重复]

    这个问题在这里已经有答案了 尝试转换图像我drag并将我的画布元素放入 PNG 或 Jpeg 照片中 有点类似于 Polyvore 的情绪板概念 这样我就可以在一张 PNG 或 Jpeg 照片中一次性查看放置在画布上的所有图像 这样我就可以
  • 在Javascript中实现优先级队列的有效方法?

    优先级队列对于每个条目都有一个优先级值和数据 因此 当向队列添加新元素时 如果它具有比集合中已有元素更高的优先级值 它就会冒泡到表面 当调用 pop 时 我们会获取具有最高优先级的元素的数据 在 Javascript 中 这种优先级队列的有
  • 使用未定义的 webpack 类捆绑 js 文件

    我将以下文件内容捆绑在一起 a js class BaseC doIt console log this class A extends BaseC b js class B extends BaseC var b new B b doIt
  • JSF:如何防止构建阶段由于递归而导致的堆栈溢出(尽管进行了渲染测试)

    对于没有在专用测试用例中抽象这个问题表示歉意 我希望来自真实项目的示例足够简单来描述问题 我有一个 JavaEE JPA2 JSF Web 应用程序 其中每个 Entity 元素 或子类 都有一个模板化 view xhtml 页面和一个标准