gpt4 book ai didi

jsf-2 - JSF : how prevent stackoverflow due to recursion during build phase (despite rendered test)

转载 作者:行者123 更新时间:2023-12-01 10:00:45 24 4
gpt4 key购买 nike

很抱歉没有在专门的测试用例中抽象出这个问题,我希望真实项目中的示例足够简单来描述问题。

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

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

x Link_to_Element_by_ID

单击“Link_to_Element_by_ID”,它会显示完整 View 页面。

单击“x”图标(专家系统测试失败指示器),弹出带有专家系统摘要的 p:dialog(仅)。

因此 View 页面的专家系统部分被共享为一个复合组件。

但这可能会导致递归和 Stackoverflow,如果:

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

  2. 我包括其他元素 View 链接以及状态指示器(它们本身会启动一个专家系统摘要的 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>

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


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

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

(参见 instanceof check in EL expression language ,并注意基于 Class String 的类型测试解决方案不是很灵活,它不适用于子类或接口(interface)测试。)

同样,尝试用“渲染”来阻止调用是不够的,似乎类型测试在构建阶段就已经失败了。递归问题的解决方案也将为此提供解决方案。即使在 JSF2 中(最后)引入 instanceof(请在这里投票 http://java.net/jira/browse/JSP_SPEC_PUBLIC-113)如果仅用于“渲染”,也无济于事,

最佳答案

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

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

简短的回答是,自 Mojarra 2.1.18 以来,您可以在 @ViewScoped 的构建阶段使用 c:if 测试来控制递归。就我而言,这现在有效:

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

像往常一样,BalusC 对其他帖子的贡献包括:

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

JSF2 Viewscope validation issue

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

JSTL in JSF2 Facelets... makes sense?

What are the main disadvantages of 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 how upgrade to Mojarra 2.1.21 in Netbeans7.1 (just sub jsf-api.jar and jsf-impl.jar fails)

这对我的项目来说是一个很好的结果。如果没有 Stackoverflow 我该怎么办 :)

关于jsf-2 - JSF : how prevent stackoverflow due to recursion during build phase (despite rendered test),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16665705/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com