在JSF2 / PrimeFaces中通过AJAX触发类级别的bean验证

时间:2013-12-19 20:55:04

标签: jsf jsf-2 primefaces bean-validation

问题描述

在我工作的公司,我们正在使用JSF2和PrimeFaces实现Web应用程序。 Web应用程序是一系列业务方法的前端之一,以及作为一组实体类创建的域模型,并使用JPA进行持久化。我们还有一些web服务方法在同一个域模型上运行。因此,我们希望在实体级别上使用bean验证尽可能多地实现验证逻辑。到目前为止,一切都很顺利,但我们最近碰到了一个我不知道如何应对的问题。为了改善用户体验,我们使用AJAX触发大多数bean验证逻辑(使用p:ajax update =" errorMessageForFieldWhatever"),例如当用户选中文本字段时,更改下拉列表中的值等等,以便他们立即得到有关错误的反馈。这在处理字段/属性级约束时工作正常,但我不知道如何使它与类级别的bean验证器一起正常工作。让我举一个例子来说明。 假设以下实体对象,CDI bean和facelets视图,以及要求MaxValue大于MinValue的自定义bean验证器。

@Entity
@CustomClassLevelBeanValidator
public class Model {
    @Min(10) int minValue; int maxValue; // getters/setters ommitted }

@Named
@SessionScoped
public class ModelBean {
    @Valid private Model model; // getter and initialization ommitted }
<f:form>
    min value:
    <p:inputText id="minValue" value="#{modelBean.model.minValue}">
         <p:ajax process="@this" update="minValueErrorMessage"/>
    </p:inputText>
    <p:message for="minValue" id="minValueErrorMessage"/>
    max value:
    <p:inputText id="maxValue" value="#{modelBean.model.maxValue}"/>
    <p:message for="maxValue"/>
</f:form>

我们想要实现的目标如下:

  • 当用户选中minValue时,该字段的错误消息会更新。这已经成功,因为标准的JSF /单字段bean验证集成。
  • 当用户选中EITHER minValue或maxValue时,应更新maxValue的错误消息。请注意,这实际上由4个独立的情况组成:约束可以通过minValue中的更改变为有效和无效,maxValue也是如此。我不清楚如何在不解析JSF级验证的情况下完成这项工作。

目前的事态

  • 直接更新ajax事件上的单字段错误消息已经可以使用(开箱即用)。
  • 通过使用MyFaces&#39; ExtVal组件我们还设法在表单提交时触发了类级别的验证,尽管所有约束违规都会在&#34;全局错误中结束。 section(p:messages globalOnly,这是有意义的,因为在类级别bean验证期间,您没有指定哪个属性验证失败)。
  • 我们已经实现了一个功能上与我上面列出的解决方案(从用户的角度来看),但我讨厌它。它涉及很多进程= this / update =在facelets方面,有时使用JSF级验证从而违反DRY,因为我们必须再次在域模型中重复这些约束以确保webservice调用是经过适当验证。
  • 如果事实证明我们想要实现的目标是不可能/不可行的,我们必须通过AJAX解决触发字段级约束并处理表单提交上的所有跨字段内容。事实并非如此糟糕,但我希望我们能做得更好。来自.NET背景我记得使用WPF和IDataErrorInfo可以很容易地实现这种东西。

解决方案要求

理想的解决方案将满足以下所有要求:

  • 完全使用Bean Validation,没有FacesMessages等实现
  • 允许在编辑表单字段后,对该特定字段的验证错误以及其约束受其影响的所有其他字段直接反馈给最终用户
  • 显示验证错误&#34;它们所属的位置&#34;,例如在上面的例子中规则&#34; max&gt;分钟&#34;至少从用户的角度来看,它与&#34; maxValue&#34;相关联。领域。事实上,这样的约束并不是严格意义上的maxValue错误,而是两个字段之间的关系并不重要,我应该能够选择其中一个作为&#34;受害者&#34;用于验证并向最终用户显示消息&#34;抱歉,该特定字段是错误的&#34;。 我理解这在N字段有约束的一般情况下是不可能的,其中一些甚至可能不在当前视图中,但我认为像min&gt;这样的东西。 max,endDate&gt;可以涵盖startDate等。

从哪里开始?

据我所知,JSF,BeanValidation或PrimeFaces中的任何内容都没有让我实现这一目标。我对ExtVal不太确定,它似乎设计得非常可扩展,但即便如此,我也不知道从哪里开始。如果我完全忽略了这些库中的任何内容并让我解决了这个问题,请告诉我! 如果没有,那么为这个问题构建自定义解决方案需要什么?我已经考虑过手动实现这个,类似于自定义阶段,它会触发当前视图中所有提交字段的所有bean验证器,并将它们转换为FacesMessages。但我怀疑这不是一件容易的事:

  • 标准类级别ConstraintViolations不带有leafBean / property-path,如果没有,验证错误可能无法与jsf的client-id匹配
  • 如果任何模型值未通过验证,则JSF不会应用模型值。在跨领域验证方案中,应用单个值可能违反约束,而应用所有这些可能会使对象再次有效(ExtVal如何执行此操作?它是否遵循JSF的规则?)
  • 我们是否在PROCESS_VALIDATIONS期间验证?如果是这样,我们是否应该启用DISABLE_DEFAULT_BEAN_VALIDATOR上下文参数以允许其他无效模型值填充实体?
  • 似乎问题的一部分是JSR303将约束验证视为状态(对象有效或无效),而JSF将其视为一种操作(不,您不能提交此表单,它&#39 ; s无效)。 JSF2.2会在这方面让生活更轻松吗?我不介意用户提交无效值,我们只是确保不要自己将它们存储在数据库中。至少这解决了必须重置UIInput组件的问题。

我想到的时间越长,我越怀疑它不会按照我想要的方式工作。我仍然觉得有点愚蠢,不得不告诉我们的用户&#34;不抱歉,结束日期必须在开始日期之后是如此复杂的业务规则,我们无法直接提供反馈,您只会遇到该错误你提交整个表格。&#34;因此,如果有人提出满足所有要求的解决方案,我将非常感激听到它。

0 个答案:

没有答案