Validation 在JSF中将异常注册为转换/验证冲突

Validation 在JSF中将异常注册为转换/验证冲突,validation,jsf,exception-handling,optimistic-locking,Validation,Jsf,Exception Handling,Optimistic Locking,异常处理程序(公然从中窃取): 数据表: <p:dataTable id="dataTable" var="row" value="#{bean}" lazy="true" sortMode="multiple" selection="#{bean.se

异常处理程序(公然从中窃取):

数据表:

<p:dataTable id="dataTable"
             var="row"
             value="#{bean}"
             lazy="true"
             sortMode="multiple"
             selection="#{bean.selectedValues}"
             rows="10">

    <p:column selectionMode="multiple">
        <f:facet name="footer">

            <p:commandButton oncomplete="PF('confirmDelete').show()"
                             update=":form:confirmDialog"
                             process=":form:dataTable"
                             actionListener="#{bean.confirmDelete}"/> <!---->
        </f:facet>
    </p:column>

    ...
    ...
    ...

    <p:column headerText="Edit">
        <p:rowEditor/>
    </p:column>
</p:dataTable>

<p:confirmDialog id="confirmDialog"
                 widgetVar="confirmDelete"
                 message="Message from bean">

    <p:commandButton id="confirmDelete"
                     value="Yes"
                     process="@this"
                     update="dataTable messages"
                     oncomplete="PF('confirmDelete').hide()"
                     actionListener="#{bean.delete}"/> <!---->

    <p:commandButton id="declineDelete"
                     value="No" 
                     onclick="PF('confirmDelete').hide()"
                     type="button"/>
    </p:confirmDialog>

...
...
...
并且不应触发模型值或操作(侦听器)方法

首先,列出的业务服务异常是在调用应用程序阶段之外的其他阶段抛出的,这会很奇怪。这些异常实际上是在调用应用程序阶段抛出的,对吗?如果跳过更新模型值和调用应用程序阶段,那就太晚了

动作方法中的通常流程为:

  • 如有必要:预处理数据,例如准备服务方法参数
  • 调用服务方法(它可以引发任何异常)
  • 如有必要:对数据进行后处理,例如在不进行后处理时刷新bean的属性
因此,如果从服务方法抛出异常,那么后处理步骤将被跳过,并且(视图范围)bean仍将保留旧属性。最终用户只能在bean是请求作用域时,或者在呈现响应期间刷新bean的属性时,重新执行相同的请求

因此,您面临这个问题表明bean是请求范围的,或者您在呈现响应期间刷新bean的属性,例如(in)直接在getter方法中。根据评论和更新的问题,
LazyDataModel
正在这样做。在大多数情况下可能是合理的,但在你的情况下肯定不是


i、 e.不应更新目标
或任何其他包含行的UI组件

您在
中指定的任何内容都在API中提供。这将返回一个可变集合,因此您可以简单地清除它

facesContext.getPartialViewContext().getRenderIds().clear();

在处理异常和添加faces消息的同时执行此操作。

“即不应更新模型值或操作(侦听器)方法”,但我收集到这些异常是在调用应用程序阶段引发的?当引发上述异常之一时,如果不可能的话,保存数据的UI组件不应该以任何可行的方式进行更新。是的,我理解这一部分,我可以回答这一点,但我尝试后退一步,因为这听起来有些可疑。例如,bean请求的作用域是否是视图的作用域?或者模型是在呈现响应阶段而不是在服务调用后直接调用应用程序阶段刷新的?请更新问题。bean通常是视图范围的。哦,这是一个懒惰的数据模型。至于具体问题,
partialViewContext.getRenderIds().clear()?(忽略您(自动)更新消息的方式)如果没有对EJB的服务调用(在本例中由操作(侦听器)依次执行),则无法引发服务层的异常。我忘了考虑这个直观的东西,它甚至不直接与JSF有关。当我意识到事情的真相后,我感到很难过。我只是朝一个方向思考。否则,问题的格式可能会完全不同。如果不是这样,您会怎么问这个问题呢?请直接回答数据表和托管bean代码片段,并回答这样一个问题:“当出现异常时,如何防止UI组件(如
)被轴向更新?”(或者最好是从服务层抛出一个预定义的异常?”(提到应用程序如何使用异常处理程序工厂处理异常)在其内容中完全或可能省略“Where this required”部分,将其减少为一行或两行(尤其是令人困惑的部分,“不应更新模型值,也不应更新操作(侦听器)方法”)
<p:dataTable id="dataTable"
             var="row"
             value="#{bean}"
             lazy="true"
             sortMode="multiple"
             selection="#{bean.selectedValues}"
             rows="10">

    <p:column selectionMode="multiple">
        <f:facet name="footer">

            <p:commandButton oncomplete="PF('confirmDelete').show()"
                             update=":form:confirmDialog"
                             process=":form:dataTable"
                             actionListener="#{bean.confirmDelete}"/> <!---->
        </f:facet>
    </p:column>

    ...
    ...
    ...

    <p:column headerText="Edit">
        <p:rowEditor/>
    </p:column>
</p:dataTable>

<p:confirmDialog id="confirmDialog"
                 widgetVar="confirmDelete"
                 message="Message from bean">

    <p:commandButton id="confirmDelete"
                     value="Yes"
                     process="@this"
                     update="dataTable messages"
                     oncomplete="PF('confirmDelete').hide()"
                     actionListener="#{bean.delete}"/> <!---->

    <p:commandButton id="declineDelete"
                     value="No" 
                     onclick="PF('confirmDelete').hide()"
                     type="button"/>
    </p:confirmDialog>
facesContext.getPartialViewContext().getRenderIds().clear();