Not quite what I expected…JSF & Validation

So I’m working on a simple search screen (for querying LDAP attributes). There is a Googley type interface (simple box with a search button beside it). The LDAP throws a fit if you search on ‘null’ (the value assigned to a text box in JSF when no value has been entered). JSF field tags support a ‘required’ attribute which will validate them. The validation message is, well, brutal.

‘Validation Error: Input Required’

No big deal…I’ve coded lots of custom JSF validators before (for other types of validation), I’ll put a validation method on the pagecode, reference it in the field and be done with it. Here’s the method I created:

public void validateQueryString(FacesContext context, UIComponent toValidate, Object value) {

String queryString = (String) value;

if (queryString == null || queryString.trim().length()<1){
((UIInput) toValidate).setValid(false);
FacesMessage message = new FacesMessage("I'm sorry, I can't make something from nothing...please enter a search string");
context.addMessage(toValidate.getClientId(context), message);
}
}

If you’re not familiar with JSF, let me walk you through…it casts the object being validated into a String and then checks to see if it’s null or empty…if it is, it sets ths validator to invalid, binds a message to the field and drops out of the Validation phase of the lifecycle.

I brought up the form, hit ‘Search’ without entering a value in the field and expected to see my cheeky validation message…I see a roar of red text ripping along the console…the Validation passed, the LDAP is getting queried?!?!  That wasn’t supposed to happen
I checked the method name and confirmed it was the same as the reference on the jsp…yep, matched.

I tried again, only this time, I entered a single space in the text field (knowing I’d trim the string and therefore fail validation)…the method was called, my cheeky message appeared…hmmm.  Validation failed as expected

I was coming to the conclusion that JSF doesn’t event create the field for validation if it’s null when I stumbled upon this tread.

Are you kidding me?!

The part I really don’t understand is the response from an architect:

“Hi,

This is what our architect had to say regarding the validator not getting invoked when no value has been entered in a field:

“JSF validators are *not* invoked on empty fields. The general reasoning is that, if there is no input data, then there is nothing to validate. Therefore, the components are working as they should for this use case.”

Hope this helps

Thanks,
Creator Team.”

I’m scratching my head on this one…not because it’s a road block (I could just live with the Eastern block type validation message), but because it throws off what I believed was a pretty solid validation framework.

JSF is self centered when it comes to validation (it wants to do ALL the heavy lifting) which is something I’ve learned to live with. It makes validation testing a pain but again, you learn to live with the cards you’re dealt. I figured I could live with JSF Validation provided I had full control over how it’s used and now I don’t believe that to be the case.

If anyone out there can shed some light on my interpretation of JSF validation on empty fields, I’d really appreciate your input.

Advertisements

39 thoughts on “Not quite what I expected…JSF & Validation

  1. Is there a reason you have to use the JSF validation? You mentioned JSF wants to do all the heavy lifting vis. validation. I am curious what you mean by that (I have not used JSF). The only justification I can think of is that JSF validation is intended strictly for validation of the format of entry fields. If that’s the case, then it makes sense not to validate empty fields…

  2. “Is there a reason you have to use the JSF validation?”

    Like most things in development, there’s a compelling reason to and not to use is. The compelling reason not to use it follows the line of great information you’ve been providing with regards to domain level validation.

    The compelling reason to use it goes something like this: JSF likes to use your domain beans as part of the View. The last phase of the JSF lifecycle is binding screen information to this bean.

    Here’s an example. Let’s say you have a screen. The screen has CUSTOMER information (simple example, name, address, phone, website). A CUSTOMER NAME cannot be blank. So let’s say you’re editing a CUSTOMER record. The CUSTOMER name is ABC Corp. That name is persistent (live in the db) and the object is valid. When editing the CUSTOMER screen, you accidentally remove the NAME from the CUSTOMER and try to save. If the JSF lifecycle doesn’t know that CUSTOMER is required, it will obviously pass validation (with the intention of some domain level of validation picking it up). Here’s where it gets a little tricky. The NULL value is now bound to the Domain bean. You have a disconnect from the information stored on disk. Rollback, right? That means one of two scenarios:
    1) You go back to the database and retrieve the persisted state of the object and replace the inmemory version
    2) You have some DTO layer that has a representation of the Persisted object that you can then rollback your Domain object to.

    The issue with both is something on the screen OTHER than the accidentally removed NAME may have changed (a new address, new phone number, etc). You’re now putting a bunch of complexity around validation/transaction management. The JSF lifecycle takes care of all of that for you (when it works like I think it should). It prevents any binding to the Domain object from happening until all validation is satisfied.

    From everything I’ve read, the JSF validation is still pretty immature and so I’m ok living with it’s current state.

    I’m glad you responded Vlad, you seem to be a bit of an expert on Validation and your comments had me revisiting my feelings on JSF/Validation.

  3. Interesting. I like the idea that the form is bound to the actual domain object in JSF. As time goes on I think more and more that it’s a better approach than using DTOs. For example, look at how nice and clean ruby on rails is. There is no doubt in my mind that JSF should call its validate method on each form field attribute, regardless of whether data was entered in for that field. I don’t know what the architect you mention is thinking (smoking?), but it’s clearly a bug if you ask me. I do like the idea of keeping all the validation logic in pure domain methods rather than in methods that are dependent on the JSF framework. If you think that’s of value (only really matters in practice if data can come into the system via an import file or a web service that doesn’t go through JSF), you could try a pattern Jeff Perrin mentioned in his blog where you separate create a class to handle the validation of each domain attribute. Maybe something like this:

    public void validateQueryString(FacesContext context, UIComponent toValidate, Object value) {
    String queryString = (String) value;
    DomainMessage message = new QueryStringValidator(this, queryString).validate();
    if (!message.empty()) {
    context.addMessage(toValidate.getClientId(context), domainMessageToFacesMessage(message));
    }
    }

  4. hii i also tried all jsf’s validation techniques…but i got same experience as jamie got.
    its not validating empty fields. Its very strange. You have to put ‘required’ attribute for validation if u want empty field to validate. When u use ‘required’ attribute it calls jsf’s internal built in validator, even if u have written ur validator separately.

  5. Hi,
    I have put an h:hiddenInput on the page with value=” ” and validator=”#{bean.validateRequired}”. es:

    This way the validator is called and I can call the validator of other component inside of it

    public void validateRequiredFields(Faces context, UIComponent comp, Object value) {
    UIComponent field1 = context.getViewRoot().findComponent(“field1_id”);
    validateField1(context, fied1, field1.getValue);
    }

    The hidden must be after input fields I want to validate.

    let me know if u can find best solutions,
    Davide

  6. Like the others, it seems a little bit odd that the validation rules don’t apply. A simply solution though is a hand – replace the error message with your own. If you register a properties file in faces-config.xml

    ….
    org.company.file

    and in the file.properties put in

    javax.faces.component.UIInput.REQUIRED=Cannot be blank
    javax.faces.component.UIInput.REQUIRED_detail=This is required. Please enter a value

    You’ll find that this error text is used rather than the JSF default.

  7. The problem with editing the messages in faces-config.xml is that these are global for every field.

    What if you want to have different messages for different fields?

  8. You can specify error messages for specific input fields by setting the value for the inputtext attribute validatormessage=”Specific Message text”.

  9. I completely agree with your post.

    It also took me a looong time to figure this out.

    In my validator, I wanted to perform some custom actions when the fields are empty, but apparently JSF does not allow me to do that.

    It just seems weird why a validator should be bypassed at all.

  10. Argh, this is a huge let down.

    I want to write my own Required Field Validator but can’t as I can’t get it to trigger.

    Being able to set a “required” message is not enough, and not very flexible.

    I for example, if not valid, set a red border around the text field that is invalid by adding a css style. I can’t do this with the inbuilt required field validator.

    I’m a .Net developer, but have been playing around with JSF and quite enjoying it. This is quite a poor design flaw. As is not being able to get a textbox’s associated label (at least in an easy way).

    I’ll post a fix if I find one.

  11. Not calling a validator on empty fields is an JSF design decision and for the sake of backward compatibility will not be changed, so let’s not grumble about it, but try to find a wotrking solution, which in fact is quite easy.

    Firstly – simple check on empty fields can be done with converters – they, in turn, will always get called, even if nothing is entered. Pretty simple, huh?

    Secondly – if you want to introduce a nonstandard, application-wide behavior on conversion/validation that is not doable using available JSF tags, like changing field classes on errors, start working with JSF phase-aware callbacks, like this one:
    http://www.oracle.com/technology/pub/articles/masterj2ee/j2ee_wk7.html
    They let you find all the fields that have validation/conversion messages assigned and do whatever you like with the fields and messages alike.

  12. Hey folks,

    its definitely rubbish by jsf not to invoke validation on empty inputs.
    im currently concerned to create a validation which immediately marks invalid fields on onblur events. this means, when you leave the field the value is submitted via ajax and checked against domain model validation (hibernate validators). this results in less code in the view( no required attributes or defining error messages in the view) and immediate feedback to the user (e.g. highlighting the incorrect field). now i came across a strange thing:
    if u use notempty or notnull hibernate annotations on a field (class variable) the validation gets invoked even if the input is null or empty. as hibernate also allows annotation on method level (very useful if you dont have an own field for each setter) i tried to add notempty resp. notnull annotations to the setter of my property. now the validation is not invoked anymore…..how stupid is that.
    if anyone knows a solution for that one he gets a big hug (introducing a class variable which corresponds to the setter isnt one 🙂 )….
    so, after years of webdevelopment, there still no proper, user friendly and developer friendly validation framework working…isnt that poor.

    greetz

    • Here’s the funny part (to me)…I wrote that post close to 3 years ago. I’m back at the same client I was working with at the time of that article and working on…you guessed it, JSF. I’m taking that same application and porting it to a new JSF implementation (icefaces, which is quite nice) and removing all the hibernate from behind the scenes. Friday I bumped up against this validation issue again…all that’s old is new again I suppose

  13. hi again,

    just read

    http://www.oracle.com/technology/pub/articles/masterj2ee/j2ee_wk7.html

    well its not bad, but most of the stuff the guy wrote i was already ware of. and where the hell we get to if i have to reimplement phasecallback listeners in jsf ?
    by the way, the id of the ui component which is invalid is anyway included in the new jsf facesmessages. i also get it easily done to display an icon next to the invalid field, but how to easily highlight the input field ITSELF???. consider style problems, when showing an icon or even the whole validation message it might bust your layout.
    so, the article above does not provide any solution for me. by the way the guys from oracle, maybe his adf components are really as powerful as he says, honestly i doubt it.

    @jamie: worked with icefaces as well, really nice, though im not really into its validation mechanisms and wether they do better than the ones of richfaces, which we migrated to from icefaces after having problems.

  14. Yes, I too have struggled with JSF validation! I think I ran into almost all of the scenarios posted on this blog.

  15. I out this code and it worked!

    public void prerender() {
    txtname.setRequiredMessage(“Name can’t be blank”);
    }

    Now this message pops up when I leave the txtname component blank. Seems simple enough.

  16. By far the most concise and up to date information I found on this topic. Sure glad that I navigated to your page by accident. I’ll be subscribing to your feed so that I can get the latest updates. Appreciate all the information here

  17. Pingback: Kumarakom

  18. Pingback: this site

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s