JSF表单未正确处理

时间:2015-06-25 21:59:23

标签: forms jsf jsf-2

我在JSF问题上被封锁了几天。

我有一个网络应用程序,我可以从数据库数据中动态创建页面内容。每个页面都有几个部分,其中包含一个带有h:commandButton(或一组按钮)的表单。 某些表单正常工作,表单操作方法按预期启动。但是其他一些形式不起作用 - 动作方法根本没有被调用。 我不知道为什么: - (

我知道这个回复:action method is not called in JSF列出了必须满足的条件,我相信这里的一切都很好,但它根本不适用于某些形式...... 一些要点:

  • 问题是100%可重复的
  • 同一件XHTML用于成功和不成功的请求
  • 为所有表单调用相同的操作方法(在同一个bean中)
  • 两种情况下控制台输出都不同
  • ... RESTORE_VIEW阶段是相同的(我的代码日志似乎相等)
  • ... APPLY_REQUEST以及其他几个阶段因错误的情况而为空(仅执行最终的RENDER_RESPONSE阶段
  • ... APPLY_REQUEST并且以下阶段对于正确的阶段不为空
  • (使用ui:debug)Scoped变量/ Request参数仅包含通过f:param传递给成功案例的vallues
  • Scoped变量/请求参数也包含formid,formid:action_name和UNsuccessfull案例的输入框内容
  • 控制台在任何情况下都绝对没有例外
  • 正确的请求返回HTTP代码302,然后是另一个带有目标参数的GET请求(作为action方法中的build)
  • 错误的请求直接返回200(并且不调用任何操作)
  • 当JSF调试打开时(javax.faces.level = ALL,com.sun.faces.level = ALL)仍然没有显示异常,我只看到几个“javax.faces.component.UIComponentBase getRenderer” \ n精简:没有渲染器类型的组件j_idt171“消息和一个”com.sun.faces.facelets.util.DevTools writeAttributes FINEST:错误写出属性“后跟NullPointerException - 在RENDER_RESPONSE阶段

所以很可能恢复视图存在问题,但我不知道为什么。相同的XHTML块为(成功和不成功)情况(在c:forEach循环中)生成表单和命令按钮。

但奇怪的是,在错误的情况下,参数在正确的情况下也是不同的......

任何人都可以告诉我一些方向/我应该寻找的地方吗? 非常感谢提前!

编辑:一些代码......

这是XHTML(不必要的代码顺序切割)

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
template="/templates/base.xhtml">

<ui:define name="title">IS runtime</ui:define>

<ui:define name="menu">
    <h:link value="Home" outcome="/index" /> | <h:link value="IS home"
        outcome="/runtime">
        <f:param name="env" value="#{param.env}" />
    </h:link>
</ui:define>

<ui:define name="content">
    <c:forEach var="pv" items="#{runtimeBean.pageViews}">
        <div id="view_#{runtimeBean.ISViews[pv.view].code}"
            class="view_#{runtimeBean.ISViews[pv.view].code}">
            <h2>#{runtimeBean.ISViews[pv.view].code}</h2>
            <h:form id="form_#{runtimeBean.ISViews[pv.view].code}">
                <h:messages />
                <c:if
                    test="#{runtimeBean.getEnvView(pv.view).type == 'RECORD_DETAIL'}">
                    <c:forEach var="item" items="#{runtimeBean.getViewItems(pv.view)}">
                        <h:outputText value="#{item.sqlColumn}" />:
                        <ui:fragment rendered="#{item.type == 'INPUT_FIELD'}">
                            <h:inputText id="#{item.sqlColumn}"
                                value="#{runtimeBean.sqlData0[item.sqlColumn]}" />
                        </ui:fragment>
                        <ui:fragment rendered="#{item.type == 'READ_ONLY'}">
                            <h:outputText value="#{runtimeBean.sqlData0[item.sqlColumn]}" />
                        </ui:fragment>
                        <br />
                    </c:forEach>
                </c:if>
                <c:forEach var="action"
                    items="#{runtimeBean.getViewActions(pv.view, 'BOTTOM_LEFT')}">
                    <h:commandButton id="action_BL_#{action.code}"
                        value="#{action.code}" action="#{runtimeBean.doPageAction}">
                        <f:param name="env" value="#{param.env}" />
                        <f:param name="view" value="#{pv.view}" />
                        <f:param name="action" value="#{action.id}" />
                        <c:forEach var="actionParam"
                            items="#{runtimeBean.getActionParams(pv.view)}">
                            <f:param name="#{actionParam}" value="#{param[actionParam]}" />
                        </c:forEach>
                    </h:commandButton>
                </c:forEach>
            </h:form>
        </div>
    </c:forEach>
    <ui:debug hotkey="z"
        rendered="#{facesContext.application.projectStage == 'Development'}" />
</ui:define>
</ui:composition>

这是正确处理的操作的范围变量/请求参数:

Name    Value
env     5
id      22
page    3

在正确的操作之后,下一页包含传递的参数:

  

http://localhost:8080/metais/runtime.jsf?env=5&page=3&id=22

和错误操作相同:

Name    Value
action  3
env     5
form_prj_detail form_prj_detail
form_prj_detail:action_BL_delete    form_prj_detail:action_BL_delete
form_prj_detail:name    p5
id      22
view    3

在错误的情况下,下一页不显示参数。很简单:

  

http://localhost:8080/metais/runtime.jsf

在这两种情况下,参数都已在HTTP(POST)请求中传递。在我看来,这更像是JSF库中javascript部分的一个问题...

EDIT2: 我在调查问题方面取得了一些进展,我发现了以下内容: 页面是动态生成的,包括表单。它们是根据传递给页面的参数生成的。 但是,在应用表单数据时,它们将应用于使用缺少参数构建的页面。如果特定表单不存在于使用此参数呈现的同一页面上,则JSF不会知道表单实例,因此其值不会应用,并且页面处理链的其余部分无效。 使用不同的单词:如果我将有问题的表单添加到“默认页面”(缺少页面参数),表单也会从不同的页面处理(相同的XHTML,但不同的参数,导致在页面上显示不同的表单)。 因此,出于某种原因,在恢复页面或应用表单数据时,并非所有页面参数都用于恢复视图。 ......我做了一小步,但仍然没有解决方案,我很沮丧: - ((

BR,  拉达

1 个答案:

答案 0 :(得分:0)

所以,最后我明白了这个问题。

如果服务器在可以设置任何表单值之前以及可以执行表单操作之前重建提交的页面,则问题出现在“还原视图”阶段。

关键是页面没有从内部JSF视图状态恢复,但它被恢复为“新”页面 - 并使用用于构建原始页面的参数。

我的应用。动态创建表单,具体页面内容取决于页面参数(在HTTP GET消息中设置),然后从DB读取数据。按下命令按钮会构建一个请求,其中包含执行操作所需的参数 - 但这与重建原始/上一页所需的参数(我不关心它)不匹配。

这意味着“还原”视图正在重建与按下命令按钮的页面不同的页面。这意味着重建的表单与原始页面表单不匹配。这最终意味着它们无法匹配,因此后续生命周期步骤不成功,也无法调用任何动作方法。

所以......这是我对JSF原则的误解,或者是JSF设计问题。 我只是希望恢复视图必须隐式自动执行......

欢迎评论!

BR,  拉达