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.
Related
I have created a form using Primefaces 6.0 and in the bean I have used constrained validators like #NotNull and #NotEmpty in the bean fields. However the asterisk near the label of the input text are not automatically rendered. The asterisk is only displayed when I set and an inputText as "required=true". My problem is that I would like to use the validation messages provided by the bean validation JSR so I would not like to put "required"to the input texts. I have also read that after primefaces 5.0 the validation constraints are automatically detected and the asterisk is rendered automatically. Has anyone faced a similar problem? Have I missed any configuration?
i think whatever you want is possible by some custom code, use CSS for asterisk (*) in read color, do not put required=true use custom validate. have look https://www.primefaces.org/showcase/ui/csv/custom.xhtml
if you did not put required=true your form will submmited to bean and you have to check and bean level for validation.
That is a nice to have feature that doesn't exist (yet).
If you want it implemented, log an enhancement feature.
Or extend bean validation component ;-)
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.
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.
I have some questions about Bean Validation and JSF validation, currently I am using Bean validation:
With the JSF validation, the validation works client side only, no request sent to server, and Bean validation works on server?
If javascript is disabled are both will work JSF & Bean Validation, or only bean validation?
What are the disadvantages of Bean validation if there are any?
That is not true. The validations are applied during the jsf life cycle by Process Validations.
"Conversion and validation occurs when the JSF runtime calls the
processValidators() method on each component in the view hierarchy.
The processValidators() method will first initiate any data conversion
that is required before validating the components value against the
application’s validation rules. If there are any errors during the
conversion or validation process the component is marked invalid and
an error message is generated and queued in the FacesContext object.
If a component is marked invalid, JSF advances directly to the render
response phase, which will display the current view with the queued
validation error messages. If there are no validation errors, JSF
advances to the update model values phase." - johnderinger.wordpress.com
You can also find this information in the specification.
Both work without javascript.
This is more a question of programming style. I think validation is better made in the model than in the view, because it removes logic from the view and it is more DRY (don't repeat yourself). If you use a bean multiple time, you will have to write the validation only once with bean validation. You should also know that bean validation overwrite constraints in JSF.
More information how to use bean validation, you can find here and the specification here.
For more information about the integrated JSF validation, you should visit this site.
Let's say I've got a register page & a register confirm page. I enter user
details into the register page, navigate to the register confirm page where
I can return back to the register page if there are any mistakes.
I'm going to use view parameters to make the registration data available
from the register page to the confirm page, and vice versa.
Supposing there are 20 items of data to be moving from page to page, that's
a lot of view parameters and a lot of setPropertyActionListeners, especially
as all the data is going to end up nicely packaged in a User object.
So what I want to do is input the data on the register page into the
properties of a User record and send a reference to it to the register
confirm page. What gave me an idea was seeing the BalusC WeakHashMap
converter. This is a JSF converter which has a static weak hash map and
generates a uuid as the value for a map entry and the object reference as
the key. So by specifying this as a converter for f:viewParam you send
the uuid in the query string.
This works fine. The issue I have is that on the register page I have to
get an instance of a User class with new. Then I can do:
<h:inputText value="#{bean.user.firstname}"/>
(etc...), and pass the user instance as a view parameter. It works fine from
the register to the confirm page. The issue is that when I perform the
reverse, sending the user reference back to the register page from the
confirm page I absolutely cannot prevent the register page backing bean
from re-instantiating the user object, after the setter has been called
as a result of the view parameter.
So the converter does it's job and retrieves the User object from the
hash map, calls setUser() in the backing bean, and then I see the
constructor for the User class firing.
I've tried calling new User() from the bean constructor, in #PostConstruct,
in a preRenderView (also checking if an ajax request), but nothing I try
prevents the work of the view parameter from getting wiped out if new is
involved. I'm sure there's a simple solution but I just can't see it right
now.
I'd be grateful for any suggestions for how to solve this problem.
The issue I have is that on the register page I have to get an instance of a User class with new.
So what code is initially creating this new User instance then? If you do this in the preRenderView handler, then you can simply check for null, can't you?
If the view parameter and converter haven't done their job, user would still be null and you create a new instance. The bean constructor and #PostConstruct won't do you any good here, since they both run before the view parameter does its thing, but the preRenderView event is guaranteed to run after it.
#ManagedBean
public class Bean {
private User user;
public void onPreRenderView() {
if (user == null) {
user = new User();
}
}
}
(Something to additionally consider is that the conversation scope already does exactly what you're trying to do here. This is part of CDI not JSF, but if you're running in a Java EE 6 Web Profile compliant AS (JBoss AS 6 or 7, Glassfish V3, Resin 4, ...) you already have it. Otherwise it's just an extra jar.)
After several attempts over more than a year to find a solid long term solution
to this problem, at last! I've found one. The solution comes in the form of the
Apache Myfaces CDI extensions project, aka Myfaces CODI.
This provides additional scopes such as the #ViewAccessScoped which ensures that
if a bean is referenced by a page then it is available for that page. Also
provided is support for conversation groups. In the scenario where I want to
pass an object reference from a register page to a register confirm page, the
confirm page can just access the registerView bean directly on the next request.
Alternatively you can #Inject one bean into another and access it on the next
request, or use f:setPropertyActionListener from the source page.
Myfaces CODI works fine with Mojarra and also with ajaxified component libraries
such as primefaces. The concept is similar to what is provided by Jboss Seam,
though I've found the additional scope support to be better thought out and I've
tested this on glassfish 3.1.1 with no problems.
If you're using #ManagedBean and scope annotations from the javax.faces.bean
package in your code, codi intercepts these annotations and uses it's own
CDI based versions, so you can convert to CDI simply by adding codi as a
dependency to your project and not changing any code.
For me this is like moving from black and white TV to colour TV, I wish I'd
found this stuff sooner.
CODI documentation