Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java p:dataTable中的commandButton单击会导致@ViewScoped beanre@Produced应用程序调用后 观点: 制作人_Java_Jsf_Glassfish_Cdi_View Scope - Fatal编程技术网

Java p:dataTable中的commandButton单击会导致@ViewScoped beanre@Produced应用程序调用后 观点: 制作人

Java p:dataTable中的commandButton单击会导致@ViewScoped beanre@Produced应用程序调用后 观点: 制作人,java,jsf,glassfish,cdi,view-scope,Java,Jsf,Glassfish,Cdi,View Scope,(使用所述的@ViewScopedCDI注释) 表外: <h:inputHidden id="{selectedDataId}"binding="#{selectedDataId}"/> <p:commandButton type="submit" id="callMethod" label="Hidden button" action="#{controller.method

(使用所述的
@ViewScoped
CDI注释)

表外:

<h:inputHidden id="{selectedDataId}"binding="#{selectedDataId}"/>
<p:commandButton type="submit"
                 id="callMethod"
                 label="Hidden button"
                 action="#{controller.method(selectedDataId.value)}"/>

最后它工作了,但我无法找出是什么导致first&base方法重新初始化视图范围的bean。查看堆栈跟踪(见下文),它似乎正在重建行

问题: 关于这个问题,有人有什么解释吗?也许有什么需要注意的

堆栈跟踪 其中:
getPipelinecheckSearchResults
是用于检索支持表的列表的调用,这会导致调用生产者

我已经看过了: 我阅读了以下文章/问题,但没有更好地理解上述(第一个)解决方案为何如此有效


除非我理解不正确,否则您使用的bean的作用域是视图(Seam 3、CODI或您自己编写的自定义作用域)。只要JSF生命周期在同一个视图上运行(这是一个正确的假设),您就可以了,但是当您更改视图id时,您会惊讶地发现您得到了视图范围bean的一个新实例??视图范围的全部目的是在JSF中保持相同的视图状态,只要您告诉JSF转到不同的视图id,它就会创建一个新的视图状态。在我看来,您实际上在寻找的是对话范围。

我找到了一些jsf/primefaces/ee api/glassfish等的源代码来调试该行为,下面是答案:

简言之 如果
组件
  • 触发导致重定向的操作(
    controller.method
  • 并放置在
    数据表中
  • datatable
    基于
    @ViewScoped
    bean生成其行
然后:
  • 调用
    controller.method
    后,将重新生成
    datatable
    所依赖的
    @ViewScoped
    bean(当然还有它的所有依赖项)
测试:在JSF的版本
2.1.7
中。 查看
2.1.19
的源代码,我希望在那里也能看到相同的行为

细节 对于那些在孤独的夏夜大声呼喊的人,他们会问:“为什么?”

导致这种行为的“事件”链(参考来源):
  • 用户单击表行内的按钮
  • 将数据
    POST
    ed发送到服务器
  • 第1-4阶段按计划进行
  • 应用程序调用
  • 点击事件由JSF接收重要提示:引用按钮的单击事件包装在一个事件中,该事件包含有关表的信息和单击发生的行号。为简单起见:
    rowEvent&clickEvent
  • 事件在组件树中“广播”
  • javax.faces.UIData
    org.primefaces.component.datatable.datatablebacking
    p:datatable
    的祖父母开始处理事件@
  • broadcast
    方法首先保存最后选定行的索引
  • 然后它选择由
    rowEvent
  • 在子
    UIComponent
    上调度
    clickEvent
    ,在本例中是在
    按钮上调度
    
    
  • 一切都很好,事件开始由
  • 这反过来调用
    controller.method
    ,它返回一个重定向
    String
    ,事情开始走下坡路
  • 在方法的末尾,
    重定向字符串
  • 这一次看到我们将要重定向时,会快速清除
    ViewMap
    ,在
    179行删除所有
    @ViewScoped
    bean。如果我们考虑一下,这是合乎逻辑的,因为我们正在走出困境
  • 回到
    UIData.broadcast
    • 广播了内部事件
    • 不知道某个内部事件导致重定向,它所做的一切都将被扔到垃圾堆中(因为
      302
    • 作为最后一个操作,尝试选择在步骤
      4.3.1
  • 当然,要选择一行,它需要知道它的数据,这就是重新生成表所需的
    @ViewScoped
    bean的地方
  • 结局

    通知
    虽然我还没有测试过,但我希望有相同的行为
    h:datatable
    p:accordionPanel
    p:carousel
    p:galleria
    p:dataGrid
    等等。简而言之,每个组件都是
    UIData
    的子类,并且不提供
    重定向
    感知
    广播方法。

    ,我想我最近观察到了一个类似的行为。您是否尝试从commandButton action调用myBean的方法而不是控制器?您是否阅读了本文1。尝试将方法调离
    myBean
    。同样的问题。(尽管我不会将逻辑放入模型中,因为它们应该是哑的)。2.是的,请阅读它,但它指的是
    actionListener
    ,在我的例子中,re
    @Produc
    是在应用程序调用之后,因此
    action
    找到了正确的方向使用的
    @ViewScope
    是[此处描述的][1][1]另一方面:如果您检查上述场景,问题是在发送到浏览器的实际重定向之前调用了生产者(在步骤2.4和3之间。因此,我们仍然处于
    POST
    请求中,该请求源于单击,并且成功地使用了步骤1.1中生成的
    @viewscoped
    bean。+我知道,一旦离开页面,或者在客户端丢失或未使用正确的
    ViewState
    id,将导致丢失所有
    @视窗
    
    @ApplicationScoped
    public class Controller {
       public String method(final Long dataId) {
            /* Do business */
            return URL_WITH_REDIRECT;
       }
    }
    
    @ApplicationScoped
    public class Producer {
       @Named @ViewScoped @Producer
       public MyBean getMyBean() {
            final MyBean bean = new MyBean();
            bean.list = new ArrayList<Data>(); // where Data has a Long id field
            /* Do business and populate list */
            return bean;
       }
    }
    
    onclick="$('input[id*=selectedDataId]').val('#{data.id}'); $('button[id*=callMethod]').trigger('click');"
    
    <h:inputHidden id="{selectedDataId}"binding="#{selectedDataId}"/>
    <p:commandButton type="submit"
                     id="callMethod"
                     label="Hidden button"
                     action="#{controller.method(selectedDataId.value)}"/>