Customize bean validation message? - jsf

Two stupid questions about bean validation used in JSF:
How can I remove the prefix form1:userName: from the output message?
<h:message for="userName" />
Which gets:
form1:userName: Please enter a valid username (5-20 characters)
I‘d also like to translate the name form1:userName to User Name, it's easy to implement such translation but I can't find where to build the message.
I have a custom validator, say #CreditCard, its default message is {foo.bar.BadCreditNumber}
#interface CreditCard {
String message() default "{foo.bar.BadCreditNumber}";
}
And the message is defined in foo/bar/ValidationMessages.properties in classpath. Now how can I make this properties file loaded in every page?

Concerning 1: The error message's format depends on the property javax.faces.validator.BeanValidator.MESSAGE which must be specified in a resource bundle of the application like this:
javax.faces.validator.BeanValidator.MESSAGE={1}: {0}
The placeholder {0} refers to the error message as created by the Bean Validation runtime, {1} refers to the component label. So if you don't want to have the label within the message, just make sure that the placeholder {1} isn't contained within that property value.
More information can be found in the JSF 2 spec. section 3.5.6.3.
Concerning 2: It's as BalusC is saying, just put ValidationMessages.properties to the root of your classpath. More information can also be found in the Hibernate Validator reference guide.

Use the input element's label attribute.
<h:inputText label="User name" ... />
See also JSF 2.0 tutorial - Finetuning validation.
The ValidationMessages.properties file has to be placed in the classpath root, without any package. See also JSR-303 specification.

Related

Since upgraded to JSF2.0, Client ID:FormID:ComponentID being preceded to the validation message while using f:validateDoubleRange

I have upgraded from JSF 1.1 to JSF 2.0. Earlier I was using f:validateLongRange or f:validateDoubleRange and the validation worked fine. However, since I have migrated to JSF 2.0 the validation message precedes with client ID which looks something like below :
FormID:ClientID:0:ComponentID in my case, the message appears as
premiumCategory:j_idt368:0:tlNewLOS: Validation Error: Specified attribute
is not between the expected values of 1 and 999,999.
There is a Jira which talks about prefixing ClientID but I dont think its of any use to me.
I learnt from the blog Communication in JSF 2.0 these tag handlers do not work correctly in JSF 2.0 thus we should create custom validators using f:validator
I followed BalusC’s answer from here; The only difference was I did not get my max and min values from the bean, I specified them in the xhtml,it still printed the validation message as stated above.
While debugging I realised that the client ID is generated as FormID:ClientID:0:ComponentID and is stored in the UIComponent instance which gets passed to the MessageFactory.getMessage method.
The same blog which I mentioned before has a topic in it saying "Ajax rendering of content outside form" which I thought would have a solution to my issue, but again no luck.
Now I have my own custom validator class which extends to DoubleRangeValidator and overrides validate method. I get the desired message. However, I am not convinced that writing a custom validator for each f:validatorXXXX component is the solution.
I am still on my learning curve, can anyone explain me why and where MessageFactory.getMessage binds these IDs to to the faces message?
Please advise,
Dakshata Gulkhobare
The label is overrideable by setting the label attribute on the input component of interest.
<h:inputText ... label="Your label" />
This way the validation message will be formatted as follows:
Your label: Validation Error: Specified attribute
is not between the expected values of 1 and 999,999
Otherwise it will indeed default to the component's client ID.
If you happen to use <h:outputLabel> already and would like to use exactly its value, but don't want to duplicate it into the label attribute of every single input component, then you may find OmniFaces <o:outputLabel> helpful.

JSF 2.0 : Runtime variables in property files

All text in our app is read from properties file
e.g.
<h:outputText value="#{text['fill.form']}"/>
text is a resource bundle that resolves to Text.properties.
Text.properties
fill.form=Please fill out the form below
There are other instance where we need run time variables inside the properties
e.g.
welcome.user=Welcome #{name.last}, #{name.first} to our site
name is a managed bean whose properties first and last get resolved at run time.
However the first name and last name are not resolved at run time. Instead the user sees the following
Welcome #{name.last}, #{name.first} to our site
Any solutions to this problem?
Should I write a custom EL resolver to resolve the text from the properties and also any run time properties inside of it.
I believe you want to use h:outputFormat to accomplish this. In your example, you might do this:
<h:outputFormat value="#{text['welcome.user']}">
<f:param value="#{name.last}"/>
<f:param value="#{name.first}"/>
</h:outputFormat>
For this to work, you need to change your welcome message to this:
welcome.user=Welcome {0}, {1} to our site

JSF2 i18n bean validation messages

How can I return a i18n localized bean validation message?
For example, in:
#Size(min = 1, message = "{pleaseProvideADescription}")
private String description;
Even though I set properties file in faces-config.xml, and I include a pleaseProvideADescription=Please provide a...
I'm still getting:
{pleaseProvideADescription}
As validation message in tag
Thanks
Bean validation (JSR-303) is completely unrelated to JSF2 (JSR-314). It's another part of standard Java EE API.
The validation messages have to go in a file named ValidationMessages.properties in the classpath root (which you can internationalize with ValidationMessages_xx_XX.properties files).
Put your custom message there. You don't need to configure anything in JSF's faces-config.xml.

Displaying custom error message for a blank field in a simple JSF application

I was trying out a simple JSF application, in which I need to check if the "name" field is blank, then display an error message.
The code which takes the field's value is:
<h:outputLabel value="Name"/>
<h:inputText value="#{greeting.name}" required="true">
<f:validator validatorId="NumValidator"/>
</h:inputText>
The control of the program does not go into the validator class, if the field is submitted without entering anything, and it displays the default error message:
j_id_jsp_869892673_1:j_id_jsp_869892673_4: Validation Error: Value is required.
How do i display a custom message for this ?
The Message.properties file stored the default validation messages. This file is contained in the JAR of the JSF implementation library.
If you look at the content of this file, regarding the required validation, you will see that:
javax.faces.component.UIInput.REQUIRED={0}: Validation Error: Value is required.
To define your own error messages, create a new properties file, add the adequate error message, for example:
javax.faces.component.UIInput.REQUIRED=Hey, you forgot to fill the input {0}!
(note that {0} will be replaced by the ID of the field)
then, in your faces-config.xml, define a new message-bundle:
<message-bundle>package.that.contains.the.properties.file</message-bundle>
So for example, if your my-messages.properties is stored in the foo/bar package, you will have to write:
<application>
...
<message-bundle>foo.bar.my-messages</message-bundle>
</application>
(note that you will not have to specify the .properties extension)
The way suggested by romaintaz is definitely way to go.
On the other hand if you are looking for more customization, you can use a phase listener that fires before render response phase as does some customizing.
For example first define the value for key as below:
javax.faces.component.UIInput.REQUIRED=INPUT_REQ_FAIL
then for input components that require validation have them pass a attribute using f:attribute .Then in phase listener iterate over the face messages and check for INPUT_REQ_FAIL and replace it with cutom message along with the attribute value for the component.
I think you should look at JSR 303! This is fully standard based user input, it works out of the box with JSF 2 (I use My Faces). And the nice thing is, no need for xml or properties files to specify custom messages.

What does <h:messages> do in JSF?

I am learning JSF and came across this line:
<h:messages layout="table"></h:messages>
in a sample application ?
Am not sure what does this line do? I get no error when removing the line from the code, and am able to run it and get the same output ?
The h:messages tag renders all messages for the current JSF view which are not covered by a h:message (remark the missing 's' at the end) tag. Messages can be generated explicitly by your backing beans (FacesContext.addMessage) or implicitly by JSF.
E.g. if you have marked an input value as required and the user submits the form without filling in the required value, an error message will be added to the view. If a h:message tag is bound to the relevant component, the message will be rendered there, otherwise it will be rendered by the global h:messages tag in your view (if any).
The layout attribute specifies what the HTML code to be generated should look like. The table layout (used in your example) uses an HTML table to display messages, while the list layout uses a bulleted list (HTML ul tag).
If you do not specify a h:messages tag in your view and also no h:message tags, the user will not be informed about errors. Therefore, it is best practice to include a h:message tag for each input component of your view and a h:messages tag for your whole view to ensure that all messages are visible to the user.
You will find a compact JSF tag reference at JSF Toolbox.
The components <h:message> and <h:messages> are dedicated to display messages to users (generally error message).
For example, when you have a validation on a field that failed (for example the user didn't fill a required field, or inputed a string in a number-only field), then a FacesMessage is added to the FacesContext object. The <h:message> and <h:messages> are then used to display the message in the page.
The component <h:messages> will display all the messages contained in the FacesContext, while the <h:message> is dedicated to a specific clientId (a specific field). The latter is usefull when you want to place the message close to a field for example.
Note that you can add any kind of message that will displayed to the user:
FacesContext.getInstance().addMessage(null, new FacesMessage("The message to display"));
In this example, the first parameter is the ID field of the field that is concerned by this message (usefull when the message is a validation message for a specific field). null means that the message is a general information (i.e. not linked to any particular field).
You can see an example of this component here. Note that this example uses the rich:messages that is an extension (provided by RichFaces) of the "basic" <h:message/>, but the principle is the same.

Resources