Thursday, 7 January 2010

Disabling RichFaces FacesBeanValidator

If you use the rich:ajaxValidator, for example:
<rich:ajaxValidator event="onblur" />
It automatically adds a FacesBeanValidator to the components list of validators. If you don't have javax.validation or Hibernate Validator setup then you'll get the following exception:
2010-01-07 00:29:19,889 [http-8443-1] WARN  org.richfaces.validator.ObjectValidator - Hibernate Validator could not be instantiated, use stub instead
javax.validation.ValidationException: Unable to find a default provider
 at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:248)
 at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:115)
 at org.richfaces.validator.BeanValidator.(BeanValidator.java:34)
 at org.richfaces.validator.ObjectValidator.createInstance(ObjectValidator.java:54)
 at org.richfaces.validator.ObjectValidator.getInstance(ObjectValidator.java:85)
 at org.richfaces.validator.FacesBeanValidator.validate(FacesBeanValidator.java:103)
 at org.richfaces.component.html.HtmlInputText.validateValue(HtmlInputText.java:52)

The way I'd like to be able to do it is:
<managed-bean>
  <description>
   Override RichFaces dependance on hibernate validator and validation api. This stops boot up exceptions (errors once).
  </description>
  <managed-bean-name>org.richfaces.validator.HibernateValidator</managed-bean-name>
  <managed-bean-class>org.richfaces.validator.NullValidator</managed-bean-class>
  <managed-bean-scope>application</managed-bean-scope>
 </managed-bean>
However, unless the bean is accessed by an EL expression like #{applicationScope['org.richfaces.validator.HibernateValidator']}, then it won't be instantiated and added to the application map.

So the only other solution is to set it with code in a ContextListener:
public void contextInitialized(ServletContextEvent event) {
  event.getServletContext().setAttribute(
    org.richfaces.validator.ObjectValidator.VALIDATOR_PARAM, 
    new org.richfaces.validator.NullValidator());
}
A bit of work just to hide an exception... And all this because I was chasing a red herring.

2 comments:

  1. Hi Chris,
    I am new to Bean Validation. I tried to use it in my current project with JSF/Facelets+RichFaces+Seam but it did not work:
    javax.validation.ValidationException: Unable to find a default provider
    at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:264)

    I guess it may be a deployment issue? I use JBoss 4.3 EAP. I have hibernate-validator-3.1.0.GA and validation-api-1.0.0.GA in classpath and packaged into EAR.

    Gould you give nay clue, please?

    Thank you.
    Andy.

    ReplyDelete
  2. Hi Andrei,

    I haven't actually tried getting it working (i just wanted to turn it off). However:

    The validaption-api and hibernate-validator I'm pretty sure are already on the JBoss master classpath (they are on JBoss 5). I'd first start by checking /common/lib and /lib directories to see which versions its got.

    Next:
    Look in the code of org.richfaces.validator.ObjectValidator.createInstance()
    It logs 2 messages.
    First if it can't used the beanvalidation.
    And the second is "Hibernate Validator could not be instantiated, use stub instead".
    If you don't see the 2nd message then it should be loaded ok (just not through validation api).

    The validation api looks for a META-INF/services/javax.validation.spi.ValidationProvider which is in hibernate-validator-4.0.2.GA.jar (but not in v3.1).

    Also have a look at:
    this richfaces jira

    ReplyDelete