When a partial submit is executed, the full JSF lifecycle is still executed. Thus, the validation phase is still processed, and all of the components in the component hierarchy are validated.
There are good reasons for this. A change in one component could cause a (potentially invalid) change in another component. For example, a selection from a selectOneMenu
could set a value in a inputText
.
ICEfaces alters processing in one significant way: During a partial submit, ICEfaces temporarily marks all components other than the one that triggered the sumbit as optional (required="false"
). Thus, "required" validations are skipped. However, ICEfaces does not disable the other validations.
There are two possible solutions to this problem:
Set immediate="true"
in addition to partialSubmit
. This changes the lifecycle slightly for the component when the partial submit is executed to perform the validation in the apply request values phase. This may cause the other validations to be skipped.
Detect if a partial submit occurred in your custom validator. Skip the validation if it isn't the component that triggered the partial submit. Unfortunately, there isn't any documentation on how to detect a partial submit, but I found the solution in the source code for the com.icesoft.faces.application.PartialSubmitPhaseListener
class.
It turns out that ICEfaces adds two request parameters when a partial submit is executed:
ice.submit.partial
- set to "true" to indicate that a partial submit was done.
ice.event.captured
- contains the component ID of the component that generated the partial submit.
You can take advantage of these two parameters in your validation methods. Here's an example:
public void validateAccount(FacesContext context,
UIComponent component, Object value)
{
if(!partiallySubmitted(context) ||
componentWasPartiallySubmitted(context, component)
// Perform validation
}
}
public boolean partiallySubmitted(FacesContext context) {
ExternalContext externalContext = context.getExternalContext();
Map parameterMap = externalContext.getRequestParameterMap();
return "true".equals(parameterMap.get("ice.submit.partial"));
}
public boolean componentWasPartiallySubmitted(FacesContext context,
UIComponent component) {
ExternalContext externalContext = context.getExternalContext();
Map parameterMap = externalContext.getRequestParameterMap();
String componentId = (String) parameterMap.get("ice.event.captured");
return component.getId().equals(componentId);
}
Of course, accessing the two request parameters directly is probably unsupported. However, until the ICEfaces team provides a supported way to "detect" a partial submit, it may be your only option.