Based on various sources, the InputListOfValues sometimes skips validation when the value has changed. The reasoning behind this is that the framework assumes that all values present in the LOV list are valid choices.
In reality, this may not always be the case. Especially if complex business rules dictate which values are valid; or if there is dependency for valid values between various fields. These complex validation scenarios are normally solved using a custom validator.
My solution to the issue of custom validators not being reliably called, was to subscribe to the ValueChangedEvent, and manually call each validator individually. Note that it is not enough to simply call control.validate().
JSF
<af:inputListOfValues id="xxItNo"
value="#{row.bindings.ItemNo.inputValue}"
model="#{row.bindings.ItemNo.listOfValuesModel}"
autoSubmit="true"
valueChangeListener="#{BackingBeanInst.itemNoChangedListener}"
autoComplete="off">
<f:validator binding="#{row.bindings.ItemNo.validator}"/>
<f:validator validatorId="MultiOpItemNoValidator"/>
</af:inputListOfValues>
Java Bean
public class BackingBeanInst {
public void itemNoChangedListener(ValueChangeEvent valueChangeEvent) {
log.fine("Entered itemNoChangedListener()");
try {
UIXInput input = (UIXInput)valueChangeEvent.getSource();
forceInputValidation(input, valueChangeEvent.getNewValue());
if (input.isValid()) {
// Perform some optional calculations if required
} else {
log.fine("input is invalid, skipping calculations");
}
} catch (Exception ex) {
log.severe(ex);
}
}
}
Java Validator
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import oracle.adf.share.logging.ADFLogger;
/**
* Performs some arbitrary validation
*/
@FacesValidator("MultiOpItemNoValidator")
public class MultiOpItemNoValidator implements Validator {
private static ADFLogger log = ADFLogger.createADFLogger(MultiOpItemNoValidator.class);
@Override
public void validate(FacesContext facesContext, UIComponent uiComponent, Object value) throws ValidatorException {
if (log.isFine()) {
log.fine("in validate");
log.fine("new value= " + value);
}
boolean valid = true;
try {
// Super Advanced Custom Validation
valid = false;
} catch (Exception ex) {
log.severe(ex);
}
if (!valid) {
log.info("Falied Validation: " + ve.getMessage());
FacesMessage msg = new FacesMessage("Item Number Validation Failed", ve.getMessage());
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg);
}
}
}
faces-context
Remember to add your validator to faces-config.xml.