Wednesday, February 29, 2012

JSF 2 - Conditionally Skip Validation

The validated model update is a major foundation of Java Server Faces. It eases the development of complex web forms and together with JPA and Bean Validation it enforces best practices like database consistency and appropriate GUI behaviour, security etc. In JSF additional measures are necessary to skip the basic validation step, for instance in use cases with sub dialogs or wizards.
This article describes, how to update the model but skip the JSF validation in dependence of which button is clicked.

Why would anyone like to skip validation?

I give you one example. We often build heavy weight forms in our business apps - so we are not the cool guys in this cartoon. This are real business requirements and even if we liked to we cannot always change customers use cases.
Such forms not only contain basic input fields, selections etc., but there are also components like Add / Select..., where you go to a searchable list, select one or multiple items and come back.
This is a typical requirement in modern web application with rich visuals - so open a JavaScript based modal subdialog and you are done!? We mainly develop application for the e-Government. Currently this implies in Germany:
All functions must work with disabled JavaScript.
You find this very often in tenders for eGov business apps and it originates in the BITV history and misinterpretations. So we have to solve this without JavaScript, possible steps:
  • action Add / Select..., we must temporarily leave the form
  • apply model updates without validation: ignore invalid input and empty required fields
  • go to a subdialog, come back with the selected data
  • finally Save, but with complete form validation

Conditional Validation - First Considerations

The often recommended <h:commandButton immediate="true"> skips validation but doesn't help here, because no model updates are done either. You can use this feature for Cancel / Reset actions, but not for this use case.

The first solution that comes into mind is to add a parameter to the command action, which is possible since JSF 2:
<h:commandButton action="#{bean.addItem"} value="Add...">
   <f:param name="skipValidation" value="true"/>
Other new JSF 2 features that help here are f:validateBean and f:validateRequired with a dynamic disabled attribute or @SkipValidation from ExtVal. I see multiple problems with this solution:
  • JavaScript necessary
    • With basic JSF components it was always quite clear which components can be used without JS, h:commandButton was one of them. But the new feature f:param changes this.
  • not secure
    • you can skip validation for all actions, even for unintended like saving:
    • simply add skipValidation=true as parameter via a tool, e.g.:
    • with addons like Firefox Tamper Data you can intercept and change POSTs
  • not a global solution
    • if you need this feature for many forms and components you have to duplicate code

JavaScript - resulting HTML for above example:
<input type="submit" name="liste:j_idt90" value="Add..." class="button"
    onclick="mojarra.jsfcljs(document.getElementById('liste'),{'liste:j_idt90':'liste:j_idt90','skipValidation':'true'},'');return false" />


Working Solution

The idea with custom validators is good but we need to find an alternative trigger and provide a global solution for this. Even if I don't like the JS-nature of h:commandButton parameters I understand it's technical reasons. Where can we add information to a button, so that the framework can decide if this should be validated or not?

We define a rule:

All commandButton ids that require validation start with "do" - for instance "doSave".

<h:commandButton action="#{bean.doSave}" id="doSave" value="Save" />
That means, actions with "do" as prefix behave like regular JSF, actions without this prefix are not validated.
If the form has the id="edit" then JSF generates this HTML:
<input id="edit:doSave" type="submit" name="edit:doSave" value="Save" />
If you look into the POST, again with Tamper Data:

The advantages of this rule:
  • we can use this "do" as global (or local) validation trigger (see ValidatorUtil below)
  • you cannot change the behaviour, if you add edit:Save=Save instead of edit:doSave=Save nothing happens, JSF will not execute the action
  • we cannot change the rule to something like "actions with <whatever>" are not validated, again you could add POST attributes that prevent validation for unintended cases


The implementation consists out of an utility class, two slightly enhanced global validator classes and the validator declaration in app/src/main/webapp/WEB-INF/faces-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns=""

Enhanced global Bean Validator app.controller.util.validator.SkipBeanValidator:
package app.controller.util.validator;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.BeanValidator;

public class SkipBeanValidator extends BeanValidator {

 public void validate(final FacesContext context, final UIComponent component, final Object value) {
  if (ValidatorUtil.check(context)) {
   super.validate(context, component, value);


Enhanced global Required Validator app.controller.util.validator.SkipRequiredValidator:
package app.controller.util.validator;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.RequiredValidator;

public class SkipRequiredValidator extends RequiredValidator {

 public void validate(final FacesContext context, final UIComponent component, final Object value) {
  if (ValidatorUtil.check(context)) {
   super.validate(context, component, value);


Utility class app.controller.util.validator.ValidatorUtil:
package app.controller.util.validator;

import java.util.Map;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

public final class ValidatorUtil {

 private static final String VALIDATE = "VALIDATE";

 public static boolean check() {
  return check(FacesContext.getCurrentInstance());

 public static boolean check(final FacesContext context) {
  final ExternalContext externalContext = context.getExternalContext();
  final Object validate = externalContext.getRequestMap().get(VALIDATE);
  if (validate != null) {
   return (Boolean) validate;
  for (final Map.Entry<String, String[]> requestParameters : externalContext.getRequestParameterValuesMap()
    .entrySet()) {
   final String key = requestParameters.getKey();
   if (key.contains(":do")) {
    externalContext.getRequestMap().put(VALIDATE, Boolean.TRUE);
    return true;
  externalContext.getRequestMap().put(VALIDATE, Boolean.FALSE);
  return false;




Please feel free to comment if you recognize problems with this solution or suggest alternatives. Even though I have some years under the belt with JSF - you should always be careful with such framework adaptions. Automatic validation is a foundation of JSF functionality and security. JSF is very extensible - but not all what can be done should be done. In feature JSF releases I would like to find a ready to use solution for this problem.