Java 验证错误后,后续ajax请求从UI组件而不是从bean获取值

Java 验证错误后,后续ajax请求从UI组件而不是从bean获取值,java,ajax,validation,jsf,omnifaces,Java,Ajax,Validation,Jsf,Omnifaces,在我基于JSF2的应用程序中,我有一个表单,其中包括(在其他UI组件中)一些复选框 在复选框中,我注册了ajax请求,当它们被选中时就会触发。ajax请求实际上只是更新支持bean中另一个复选框的值。 因此,另一个复选框也将被选中(当它被重新渲染时——因为它将在渲染响应阶段从支持bean获取更新的值) 在提交整个表单并出现验证错误之前,这种方法可以正常工作。 然后ajax请求仍然有效并更改支持bean上的值,但是在重新呈现更新的复选框的阶段,它的值不是从支持bean获取的,而是从Componen

在我基于JSF2的应用程序中,我有一个表单,其中包括(在其他UI组件中)一些复选框

在复选框中,我注册了ajax请求,当它们被选中时就会触发。ajax请求实际上只是更新支持bean中另一个复选框的值。 因此,另一个复选框也将被选中(当它被重新渲染时——因为它将在渲染响应阶段从支持bean获取更新的值)

在提交整个表单并出现验证错误之前,这种方法可以正常工作。 然后ajax请求仍然有效并更改支持bean上的值,但是在重新呈现更新的复选框的阶段,它的值不是从支持bean获取的,而是从
ComponentStateHelper
类获取的缓存值

据我所知,这用于JSF2的新特性,只存储对组件树的部分更改


我不明白的是:这与验证阶段有什么关系?当验证发现错误时,为什么在
stateheloper
类中有“我的复选框”的缓存值?

这是一个已知的问题,详细解释如下。简而言之,问题是由于将由
呈现但未由
执行的无效组件与原始提交值一起处于无效状态。当JSF呈现输入组件时,JSF将首先检查提交的值是否不是
null
,然后显示它,否则将显示模型值。基本上,您需要重置要呈现但未由ajax执行的输入组件的提交值

要实现这一点,您可以使用基本上执行以下操作的:

UIViewRoot viewRoot = context.getViewRoot();
PartialViewContext partialViewContext = facesContext.getPartialViewContext();
Set<EditableValueHolder> inputs = new HashSet<EditableValueHolder>();

// First find all to be rendered inputs and add them to the set.
findAndAddEditableValueHolders(partialViewContext.getRenderIds(), inputs);

// Then find all executed inputs and remove them from the set.
findAndRemoveEditableValueHolders(partialViewContext.getExecuteIds(), inputs);

// The set now contains inputs which are to be rendered, but which are not been executed. Reset them.
for (EditableValueHolder input : inputs) {
    input.resetValue();
}
UIViewRoot-viewRoot=context.getViewRoot();
PartialViewContext PartialViewContext=facesContext.getPartialViewContext();
设置输入=新的HashSet();
//首先查找所有要渲染的输入,并将它们添加到集合中。
FindAddeditableValueHolders(partialViewContext.getRenderIds(),输入);
//然后找到所有执行的输入并将其从集合中删除。
FindRemoveEditableValueHolders(partialViewContext.getExecuteIds(),输入);
//该集合现在包含要呈现但尚未执行的输入。重置它们。
用于(EditableValueHolder输入:输入){
input.resetValue();
}

这已被报告为,并且在库中实现了一个完整且可重用的解决方案(源代码和showcase演示)。

非常感谢您的回答。无论如何,我已经在我的项目中包含了您的omnifaces库(用于
FullAjaxExceptionHandlerFactory
)。因此,只需在我的
faces config.xml
文件中包含
resetInputJaxActionListener
,就很容易了。但这只在
InvokeApplicationPhase
中调用,我的ajax请求不会命中该阶段。我的ajax请求由一个
触发,在那里由
触发。但我会仔细看看这个。我只是很快就尝试了你的建议,没有成功?你确定吗?在编辑faces配置之后,您可能需要重新启动服务器。我确实重新启动了它,并添加了omnifaces的源代码,并设置了一个断点以查看它是否被命中。它确实会在常规请求中被命中,但不会在通过选择复选框触发的ajax请求中被命中。我只是添加了代码,在第一个复选框设置第二个复选框值的位置(在我的支持bean中)重置输入组件上的值。如下所示:
resetInputJaxActionListener reset=new resetInputJaxActionListener();reset.processAction(null)然后一切正常。所以我想我必须找到一个更好的地方来触发重置。(仍然想知道为什么选中复选框时发出的axaj请求不会触发
ActionListener
)您使用的是什么JSF impl/版本?