You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RequestScoped Bean使用required或@NotNull导致viewParam丢失的问题

解决JSF表单验证失败时丢失viewParam主键的问题

问题根源

当你给<p:inputText>设置required="true"或者用@NotNull注解时,一旦必填字段为空触发验证失败,页面会回发,但你的termsid这个viewParam参数并没有被包含在表单的POST请求里。因为你的Bean是RequestScoped,每次请求都会重新实例化,回发时没有termsid,ARTermsEditBean.termsID就会为空,执行initializeExisting自然会报错。

不用加大量额外代码的解决办法

办法1:在表单里加隐藏字段存主键

直接在<h:form>里加一个隐藏输入框,把termsID的值带在表单提交请求中,这样不管验证成功还是失败,回发时主键都会跟着传回去:

<h:form id="artermsform">
    <!-- 新增隐藏字段,传递主键 -->
    <h:inputHidden value="#{ARTermsEditBean.termsID}" />
    
    <!-- 原表单内容不变 -->
    <h:panelGrid columns="3" columnClasses="formLabel">
        <h:outputLabel value="Terms" for="terms" />
        <p:inputText id="terms" value="#{ARTermsEditBean.terms}"
                     required="true" maxlength="60" />
        <p:message for="terms" />
        <h:outputLabel value="Due Date Days" for="duedatedays" />
        <p:inputText id="duedatedays" value="#{ARTermsEditBean.dueDateDays}"
                     maxlength="3" />
        <p:message for="duedatedays" />
    </h:panelGrid>
    <p:commandButton value="Save" ajax="false"
                     action="#{ARTermsEditBean.submit}" />
</h:form>

这样不管验证是否失败,termsID都会被提交到后台,Bean重建时能拿到正确的主键值,不会触发错误。

办法2:优化初始化逻辑,避免回发时重复初始化

把原来的<f:event type="preRenderView">换成<f:viewAction>,设置只在非回发请求时执行初始化,这样验证失败回发时不会重新调用initializeExisting,就算万一主键没传(配合办法1就不会有这情况),也不会因为重复初始化报错:

<f:metadata>
    <f:viewParam name="termsid" value="#{ARTermsEditBean.termsID}" />
    <!-- 替换preRenderView,仅首次加载页面时执行初始化 -->
    <f:viewAction action="#{ARTermsEditBean.initializeExisting}" if="#{not facesContext.postback}" />
</f:metadata>

两个办法一起用效果最佳,既保证主键不会丢,又避免不必要的重复初始化。

关于其他页面的差异说明

那些主键在只读字段里的页面能正常工作,是因为只读输入框(比如<h:inputText readonly="true">)会把主键值作为表单字段一起提交到后台;而你当前页面没把termsid放进表单里,所以验证失败回发时就丢了这个参数。

内容的提问来源于stack exchange,提问作者Kevin Rahe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 20:44:52