2 Replies Latest reply on Aug 25, 2014 5:28 AM by barkhabansal

    Skipping JSF validation phase to allow model update / invoke application phase

    jmsjr

      JBoss7.1.1 (Brontes)

      Windows7 64-bit

      JDK 1.7.0_06 x86 32-bit

       

       

      I have a need to skip the PROCESS_VALIDATIONS lifecycle phase, but still proceed to the UPDATE_MODEL_VALUES and INVOKE_APPLICATION phases.

      Now before someone says to use immediate="true", that will not work for the requirement that I have as that will go straight to the RENDER_RESPONSE phase.

       

       

      It is basically a Cancel button, but the cancel button itself needs to invoke a method in the backing bean ( e.g. unlock an external resource ), and then close the window.  The external resource to unlock is specified as HTML input hidden parameters. Thus, the need to have the UPDATE_MODEL_VALUES, as I need to know the parameters to the external resource to unlock, and the need to have the INVOKE_APPLICATION phase, as I need to invoke a method on the bean to actually unlock the external resource.

       

       

      Now I am using the example provided here:

       

       

      http://javalabor.blogspot.com.au/2012/02/jsf-2-conditional-validation.html

       

       

      So along the same lines, I have:

       

       

      1) The following in my faces-config.xml file:

       

      {code}

      <validator>

        <validator-id>javax.faces.Required</validator-id>

        <validator-class>xx.yy.zz.SkipRequiredValidator</validator-class>

      </validator>

      <validator>

        <validator-id>javax.faces.Bean</validator-id>

        <validator-class>xx.yy.zz.SkipBeanValidator</validator-class>

      </validator>

      {code}

       

       

      2) The following class as the SkipRequiredValidator

       

       

      {code}

      package xx.yy.zz;

       

       

      import java.util.logging.Level;

      import java.util.logging.Logger;

       

       

      import javax.faces.component.UIComponent;

      import javax.faces.context.FacesContext;

      import javax.faces.validator.RequiredValidator;

       

       

      /**

      * This validator will skip the JSF validation phase if the Submit action

      * has the parameter cancel with a value of "Cancel".

      *

      * This is required as we still want to have the Invoke Application JSF lifecycle

      * executed in order to have the workItem unlocked.

      *

      * @author salvojo

      */

      public class SkipRequiredValidator extends RequiredValidator {

       

                private static Logger logger = Logger.getLogger(SkipRequiredValidator.class.getName());

       

                @Override

                public void validate(final FacesContext facesContext, final UIComponent component, final Object value) {

       

                          if( SkipValidatorUtil.continueValidation(facesContext)) {

                                    logger.log( Level.FINER, "Calling standard validation" );

                                    super.validate(facesContext, component, value);

                          } else {

                                    logger.log( Level.FINER, "Skipping standard validation" );

                          }

                }

      }

       

      {code}

       

       

      3) The following class as the SkipBeanValidator:

       

       

      {code}

      package xx.yy.zz

       

       

      import java.util.logging.Level;

      import java.util.logging.Logger;

       

       

      import javax.faces.component.UIComponent;

      import javax.faces.context.FacesContext;

      import javax.faces.validator.BeanValidator;

       

       

      /**

      * This validator will skip the JSF validation phase if the Submit action

      * has the parameter cancel with a value of "Cancel".

      *

      * This is required as we still want to have the Invoke Application JSF lifecycle

      * executed in order to have the workItem unlocked.

      *

      * @author salvojo

      */

       

       

      public class SkipBeanValidator extends BeanValidator {

       

                private static Logger logger = Logger.getLogger(SkipBeanValidator.class.getName());

       

                @Override

                public void validate(final FacesContext facesContext, final UIComponent component, final Object value) {

       

                          if( SkipValidatorUtil.continueValidation(facesContext)) {

                                    logger.log( Level.FINER, "Calling standard validation" );

                                    super.validate(facesContext, component, value);

                          } else {

                                    logger.log( Level.FINER, "Skipping standard validation" );

                          }

                }

      }

       

      {code}

       

       

      4) And the utility class

       

       

      {code}

      package xx.yy.zz;

       

       

      import java.util.Map.Entry;

      import java.util.logging.Level;

      import java.util.logging.Logger;

       

       

      import javax.faces.context.FacesContext;

       

       

      /**

      * Utility method that will:

      *

      * 1) Check for a request parameter of attribute {@link SkipValidatorUtil#VALIDATE}

      *

      * 2) If found, return the value of that attribute. It is assumed to be a Boolean.

      *

      * 3) If not found, checks for a parameter with name that ends in ":cancel" ( the

      * text before the colon is the id of the form, which could change ). If found,

      * checks that the value of this parameter is "Cancel". If so, sets the

      * request parameter of attribute {@link SkipValidatorUtil#VALIDATE} to false.

      * If not found, or found but the value of the parameter is not "Cancel",

      * then sets the request parameter of attribute {@link SkipValidatorUtil#VALIDATE} to true.

      *

      * @author salvojo

      */

      public final class SkipValidatorUtil {

       

                private static final String VALIDATE = "xx.yy.zz.VALIDATE";

       

                private static Logger logger = Logger.getLogger(SkipValidatorUtil.class.getName());

       

                public static boolean continueValidation(final FacesContext facesContext) {

       

                          Boolean continueValidation = (Boolean) facesContext

                                    .getExternalContext()

                                    .getRequestMap()

                                    .get(SkipValidatorUtil.VALIDATE);

       

                          if( continueValidation == null ) {

                                    continueValidation = true;

       

                                    for( Entry<String,String> requestParameter : facesContext

                                              .getExternalContext()

                                              .getRequestParameterMap().entrySet()) {

       

                                              if( requestParameter.getKey().contains(":cancel") &&

                                                        "Cancel".equals(requestParameter.getValue()) ) {

                                                        continueValidation = false;

       

                                                        break;

                                              }

                                    }

       

                                    facesContext

                                              .getExternalContext()

                                              .getRequestMap()

                                              .put(SkipValidatorUtil.VALIDATE, continueValidation);

                          }

       

                          logger.log( Level.FINER, "Validation will be continued? " + continueValidation );

       

                          return continueValidation;

                }

      }

      {code}

       

       

       

      5) And in my XHTML page, the following snippet:

       

       

      {code}

      <h:inputText id="f_mbrId" value="#{insuranceCase.planMemberId}" required="true">

      <h:inputHidden id="workItemTag" value="#{insuranceCase.workItemTag}"/>

       

       

      <rich:messages/>

      <h:commandButton id="cancel" value="Cancel" action="#{insuranceCase.unlock}"></h:commandButton>

      {code}

       

       

      6) After deploying, when I click on the Cancel button, I am STILL getting a validation messages rendered when I leave the f_mbrId HTML input field blank, and the action on the backing bean is never invoked. The following output on the log file shows what happens:

       

       

      {noformat}

      18:41:46,155 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2) Before Phase: RESTORE_VIEW 1 Session exist: true

      18:41:46,156 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2)     Session: com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap => {2765221448941953821={-5650150279934172176=[Ljava.lang.Object;@37a9aa}, 4523587801893665884={-84153624240172225=[Ljava.lang.Object;@1a46cd2}}

      18:41:46,159 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2)     Session: javax.faces.request.charset => UTF-8

      18:41:46,167 FINER [xx.yy.zz.ActionProcessorListener] (http--0.0.0.0-8081-2)         Request: j_idt4:f_mbrId =>

      18:41:46,184 FINER [xx.yy.zz.ActionProcessorListener] (http--0.0.0.0-8081-2)         Request: j_idt4:workItemTag => aasdev1|JSFTESTP|salvojo|R|29628|8603194|aasdev1|STRTCASE|0|9

      18:41:46,189 FINER [xx.yy.zz.ActionProcessorListener] (http--0.0.0.0-8081-2)         Request: j_idt4:cancel => Cancel

      18:41:46,191 FINER [xx.yy.zz.ActionProcessorListener] (http--0.0.0.0-8081-2)         Request: javax.faces.ViewState => 4523587801893665884:-84153624240172225

      18:41:46,192 FINER [xx.yy.zz.ActionProcessorListener] (http--0.0.0.0-8081-2) Not an initial request to start or open an existing workitem

      18:41:46,195 FINER [xx.yy.zz.ActionProcessorListener] (http--0.0.0.0-8081-2) After Phase: RESTORE_VIEW 1 Session exist: true Request Path: null

      18:41:46,196 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2) After Phase: RESTORE_VIEW 1 Session exist: true Request Path: null

      18:41:46,197 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2) Before Phase: APPLY_REQUEST_VALUES 2 Session exist: true

      18:41:46,197 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2)     Session: com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap => {2765221448941953821={-5650150279934172176=[Ljava.lang.Object;@37a9aa}, 4523587801893665884={-84153624240172225=[Ljava.lang.Object;@1a46cd2}}

      18:41:46,199 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2)     Session: javax.faces.request.charset => UTF-8

      18:41:46,200 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2) After Phase: APPLY_REQUEST_VALUES 2 Session exist: true Request Path: null

      18:41:46,201 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2) Before Phase: PROCESS_VALIDATIONS 3 Session exist: true

      18:41:46,201 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2)     Session: com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap => {2765221448941953821={-5650150279934172176=[Ljava.lang.Object;@37a9aa}, 4523587801893665884={-84153624240172225=[Ljava.lang.Object;@1a46cd2}}

      18:41:46,203 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2)     Session: javax.faces.request.charset => UTF-8

      18:41:46,203 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,204 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,205 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,205 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,207 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,208 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,208 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,209 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,210 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,210 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,211 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,212 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,213 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,213 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,214 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,215 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,215 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,216 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,217 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,217 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,218 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,219 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,219 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,220 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,221 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,221 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,222 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,223 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,223 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,224 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,225 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,225 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,226 FINER [xx.yy.zz.SkipValidatorUtil] (http--0.0.0.0-8081-2) Validation will be continued? false

      18:41:46,226 FINER [xx.yy.zz.SkipBeanValidator] (http--0.0.0.0-8081-2) Skipping standard validation

      18:41:46,227 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2) After Phase: PROCESS_VALIDATIONS 3 Session exist: true Request Path: null

      18:41:46,228 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2) Before Phase: RENDER_RESPONSE 6 Session exist: true

      18:41:46,229 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2)     Session: com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap => {2765221448941953821={-5650150279934172176=[Ljava.lang.Object;@37a9aa}, 4523587801893665884={-84153624240172225=[Ljava.lang.Object;@1a46cd2}}

      18:41:46,230 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2)     Session: javax.faces.request.charset => UTF-8

      18:41:46,239 FINER [xx.yy.zz.jsf.PhaseTracker] (http--0.0.0.0-8081-2) After Phase: RENDER_RESPONSE 6 Session exist: true Request Path: null

       

      {noformat}

       

       

      As you can see from the above, it did not go through the UPDATE_MODEL_VALUES phase and did not go through the INVOKE_APPLICATION phase. It went stragith through to RENDER_RESPONSE phase, as if ignoring the validators that I provided.

       

       

      So my question are:

       

       

      *) Does providing your own validators in faces-config.xml override the default validators provided by the JSF implementation ?

      *) If yes, then what I am doing wrong above .. as I only call the superclass validate() method when I want to ?

      *) If no, what is an alternative ?