I'm wondering what the recommended practice is for handling what I would call "page level validation?"
For example, I have two text boxes. Either one text box or the other must have a non-null value. If they are both null, I want the page validation to fail and redisplay the page the same way it would if validation for a particular field failed. However, I don't want the message that is posted to be associated with either of the two text boxes. I want it to use some other unique ID because I want to display the error text at a location that is different than for either of the text box error messages.
I have yet to see a solution to this problem. The biggest issue here is that JSF does not validate empty fields. My understanding is that JSF relies on the required attribute to determine the validity of an empty field. Unfortunately, this kind of framework doesn't seem to support the scenario where two fields are related and at least one of them must be filled in, at least not without big efforts.
Re: Recommended practice for handling page level validation?
Jun 29, 2004 12:07 PM
(reply 2
of 16) (In reply to
#1 )
Yeah, I remember finding out about the required field problem when working on a different problem. IMHO, it should call the validators even if the value is null. Being able to do this kind of validation easily seems pretty fundamental.
I'm guessing that I'll try to figure something out using the method that is being called by the button on my form... I'm thinking of trying to figure out how to post a generic (application?) message and then setup navigation so that it reposts to the same page if the validation in that method fails.
Re: Recommended practice for handling page level validation?
Jun 29, 2004 3:48 PM
(reply 3
of 16) (In reply to
#2 )
I think I kind of figured out a solution, however, I think I'm having problems with the client identifier. I have something similar to the following. It isn't displaying the error message. However, if I use a <h:messages/> tag instead, I can see the error message. I'm guessing I'm just not setting the client ID correctly? In the JSP page, I it prepends the parent ID's to the beginning of the client ID (at least in the HTML). Anyone have any ideas what the proper way to set the client ID is? I tried it without the preceding "form1:" and that didn't work either.
Re: Recommended practice for handling page level validation?
Jul 6, 2004 9:48 AM
(reply 5
of 16) (In reply to
#4 )
Having to create a custom component for multi-component validation seems like overkill to me.
However, the two components that I'm dealing with are both custom components, or, more specifically, custom tag/renderer pairs. What I need to figure out is how to imbed one of the components within the other one because I don't want to just copy and paste code from one to the other.
Another thing that I'm thinking of is creating an input component, but, make it so that it has no visible representation in the UI. And make it so that it always has a non-null value so that it always gets called. Maybe call it something like <pageValidator validator="myBean.myValidator"/>. I don't know if the input value always has to change with each request in order for the validator to run or not though. I need to test that.
Re: Recommended practice for handling page level validation?
Jul 6, 2004 1:32 PM
(reply 6
of 16) (In reply to
#5 )
I would suggest creating custom converter for each of basic types by extending the Faces standard ones. This way I can control the conversion policy (including null handling) at the application level. For example: In my application, I would not allow blanks to escape required checks (which it does in the standard conversion/validation).
In your case, plug your conditional requirement validation in the second component. Since the component tree is built in the order in which they appear in the JSP page, the validation on the second component will always execute after the first one.
The hidden control usage / enforcement in the Action method is also a great way. For finding the client-ids, maybe you can bind the controls to your managed bean and use it to get the IDs. This would free you of changing your controller code if you happen to rearrange the compoenents in the UI.
Without making a sweeping generalization, IMHO: In medium to large applications, it is preferable NOT to put non-UI validation logic in the controller layer. The conditional required field check seems such a requirement. But the controller should be invoking such validations. The model bean can throw Exceptions to indicate errors which can be mapped to fields by the controller layer.
Re: Recommended practice for handling page level validation?
Jul 7, 2004 2:30 PM
(reply 7
of 16) (In reply to
#6 )
The reason I don't want to use a custom converter is because I'm using a custom tag/renderer which aggregates several HTML input components and has complex conversion logic. Maybe I could chain things together, but, a converter should be used for conversion not validation. Secondly, I don't understand why validation occurs after conversion. This seems backward to me.
One hack that I tried which almost worked was to create a custom tag/rendererer that was an input component, but, had no visible UI. I made that component always have a value which caused the validator to always be called. I made it so that it accepted a method binding as an input so that you could specify which validation method was called. I checked the component values for the components of interest using UIInput.getValue(). However, I ran into what might be a bug. Everything worked fine as long as the value changed to a non-null value. When the value was set to null, UIInput.getValue() was returning the old value instead of null. The strange thing is that the bean property that the component was bound to, ultimately was changed to null as I would have expected to. The problem was that UIInput.getValue() was returning the old value instead of null.
My current solution which isn't ideal is by using code similar to the following in my action method that my form submit button calls.
if(value1 == null && value2 == null) {
String message = "Validation Error: Value is required.";
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage("id1", new FacesMessage(message, message));
return "validationError";
}
Note, I had to create my own custom tag/renderer equivalent of h:message because I couldn't get h:message to work. h:message couldn't find the message that I posted.
The down side to doing it this way is that the validation is occurring after the validation phase. Hence, the error message isn't displayed at the same time as other error messages. Furthermore, if you have more than one button on the form, you'd have to do the check for each action method.
This is really stupid. I can't believe something that should be so simple is so difficult in JSF. I'm planning on taking a closer look at ASP.NET. I'm pretty sure all you have to do in ASP.NET is override a method to do this and you have access to all the form controls as variables within the Page object. i.e. no having to lookup the controls using a method and a client ID.
Re: Recommended practice for handling page level validation?
Jul 9, 2004 2:12 PM
(reply 9
of 16) (In reply to
#7 )
Initially, I shared the same confusion as you, regarding conversion and validation. If user enters ?abc? in a currency field, this would be "validated" during conversion. This initially sounds counter-intuitive, but actually makes sense if you consider conversion as a special case validation.
IMO, Conversion should precede validation. This is because user-visible values are often different from the biz object values. Example: a double currency field will most likely be formatted with commas; -ve currency shown in brackets; localized formatting. Similarly when a boolean field needs to be shown as text, it might be shown as True/False or Active/Inactive depending on the context.
Translating to/from these should be under the purview of conversion. Therefore Validation in the JSF sense actually means ?semantic? validations.
Re: Recommended practice for handling page level validation?
Jul 9, 2004 2:18 PM
(reply 10
of 16) (In reply to
#9 )
I have less of an issue with the order in which conversion and validation occurs than with the fact that I've yet to find a good way to do multi-field validation. This should be a no brainer. Instead, I have to spend days hacking something together in order to do something as simple as require that one of two fields contains a valid value.
Re: Recommended practice for handling page level validation?
Jul 10, 2004 9:41 AM
(reply 12
of 16) (In reply to
#11 )
The problem I had was that both values were not required. It was valid if either one or the other of the fields were valid. Thanks for the pointer on the x:validateEquale though.
Re: Recommended practice for handling page level validation?
Jul 12, 2004 8:49 AM
(reply 13
of 16) (In reply to
#7 )
context.addMessage("id1", new FacesMessage(message,
message));
return "validationError";
}
Note, I had to create my own custom tag/renderer
equivalent of h:message because I couldn't get
h:message to work. h:message couldn't find the message
that I posted.
The client id you are setting for the message is probably incorrect. Render your page in a browser and then view source, look at the id of the component the message is for. Most likely the id is something like formId:componentId. If you use that same one in your addMessage call it should work fine. This is how we handle page level validation as well.