Validation is one of the first things you test out when evaluating a web framework and its often one of the most time consuming to wrap your head around. In this post I’ll talk about three types of validation mechanisms present in JBoss’ Seam which will get you on your way towards validating web forms without too much pain:
I’m going to cover three cases:
- Validating required fields without using annotations
- Validating manually and displaying custom messages
- Validating fields using Hibernate annotations in Seam beans
We’ll also display messages using a simple resource bundle (java.util.ResourceBundle
) which will allow us to internationalize our forms and messages. Let’s dive into the examples:
Validating required fields without using annotations
This is the most general case, you want to force the user to input something in your text fields and if they don’t, you want to display a message telling them just that.
Here’s a JSF form which asks for a username and password:
<h:messages/> <h:form id="LoginForm"> <table> <tr> <td><h:outputText value="#{messages['login.username']}"/></td> <td> <h:inputText required="true" value="#{user.username}" label="#{messages['login.username']}"/> </td> </tr> <tr> <td><h:outputText value="#{messages['login.password']}"/></td> <td> <h:inputSecret required="true" value="#{user.password}" label="#{messages['login.password']}"/> </td> </tr> <tr> <td></td> <td> <h:commandButton action="#{loginAction.login}" value="#{messages['button.login']}"/> </td> </tr> </table> </h:form>
Specifying required=”true” is all you need to validate required fields. The matter of displaying messages is left to the <h:messages/>
tag which iterates through the list of messages generated by the validation phase and displays them sequentially.
By default validation messages are displayed in a format that is not very intuitive, in order to change the format you must override a property in your messages.properties
file located at the root of your classpath:
javax.faces.component.UIInput.REQUIRED={0} is a required field.
The placeholder is {0} is automatically filled by the label attribute of the <h:inputText>
tag. So in the above case if login.username is defined to be “Username” in the resource bundle, the messages that will be printed will be: Username is a required field.
If validation passes, then the login()
method on the bean referenced by loginAction will be called (as specified by the <h:commandButton>
tag.
Validating manually and displaying custom messages
This is probably the most powerful way of validating user input – programmatically. Let’s face it, the built-in validators can only do so much, at some point you end up writing java code to validate input by checking it against a database or queue etc. Going back to the login example, say we need to check the values supplied by the user against a database and if they match, let them into the system and if they don’t, kick them back to the login page with a message. The login page does not change, let’s get to the LoginAction class:
@Name( "loginAction" ) public class LoginAction { @In private User user; @In(create=true) private FacesMessages facesMessages; public String login() { if (user.getUsername().equals( "Arsenalist" ) && user.getPassword().equals( "Raptors" )) { return "success"; } else { facesMessages.addFromResourceBundle("login.failed"); return "failure"; } } }
It’s very obvious what’s happening here. The injected instance of FacesMessages
allows you to use its addFromResourceBundle()
method to specify a message that will be displayed in the view resulting from returning “failure”. Just for completeness sakes, here’s the faces-config.xml navigation rule:
<navigation-rule> <from-view-id>/pages/login.xhtml</from-view-id> <navigation-case> <from-action>#{loginAction.login}</from-action> <from-outcome>success</from-outcome> <to-view-id>/pages/home.xhtml</to-view-id> </navigation-case> <navigation-case> <from-action>#{loginAction.login}</from-action> <from-outcome>failure</from-outcome> <to-view-id>/pages/login.xhtml</to-view-id> </navigation-case> </navigation-rule>
Validating fields using Hibernate annotations in Seam beans
The next step is to apply more complex validation without resorting to writing Java code and for that Seam relies on Hibernate’s validation framework. As an aside, this dependency is probably the most annoying thing about Seam at this point but it works well enough to look past.
Let’s say we need to force the value of username to be atleast 5 characters. In order to do this we need to annotate two things:
- The injected user variable in
LoginAction
so Seam knows to validate it - The
User
objects properties to specify what to validate. - @Length(min=, max=) Checks whether the string length matches the range
- @Max(value=) Checks that the value is less than or equal to the max
- @Min(value=) Checks that the value is greater than or equal to the min
- @NotNull Checks that the value is not null
- @Past For a date object, checks that the date is in the past
- @Future For a date object, checks that the date is in the future
- @Pattern(regex=”regexp”, flag=) For a string, checks that the string matches this pattern
- @Range(min=, max=) Checks whether the value is between the min and the max
- @Size(min=, max=) For collections, checks that the size is between the two
- @AssertFalse Asserts that the evaluation of the method is false
- @AssertTrue Asserts that the evaluation of the method is true
- @Valid For a collection or a map, checks that all the objects they contain are valid
- @Email Checks whether the string conforms to the email address specification
Here’s the relevant piece in LoginAction.java
:
@Name( "loginAction" ) public class LoginAction { @In @Valid private User user; public String login() { . . . . }
Here’s the relevant piece in User.java
:
@Name( "user" ) public class User { private String username; private String password; @Length(min=5, message= "#{messages['login.username.length']}" ) public String getUsername() { return username; } . . . .
Notice how we’re using a resource key inside an annotation to print the message. This will look for a resource bundle called messages and inside it for the login.username.length property to retrieve the message. You could alternately just write the message in plain old English inside the annotation but why would you want to when you can internationalize.
The last thing we need to do is tell the JSF page that it will need validation (I think this is a somewhat redundant step since the bean is already annotated but nonetheless it is required). You must wrap the fields of the login form around the <s:validateAll> tag like so:
<h:messages/> <h:form id="LoginForm"> <s:validateAll> . . . . <h:outputText value="#{messages['login.username']}"/></td> . . . . </s:validateAll> </h:form>
Note: Be sure to specify required=”true” for the fields you want to apply annotation validations to. Otherwise, you’ll see some very weird results such as only non-blank fields getting the annotation validations applied to while the blank fields get considered valid.
Here’s a list of annotations that you can use to validate java beans:
That’s all there is to it.
Thank you for nice article.
excelent!!
it’s very usefull
If you owned a gun, do you think you would kill have somebody from a quick reaction yet?
http://www.chirpthis.com/2008/08/17/poll-if-you-own-a-gun-would-you-kill/
thank you.
Thanks..
“The placeholder is {0} is automatically filled by the label attribute of the tag…”
why the label,if I add {1},{2},… how will they be filled?
Im agree.
Good article. Thanks
can you talk more about internationalization?Or can you direct me to some god tutorials?I’m a beginer.
Thanks!
Masini, you can use resource keys which reference .properties files in your HTML controls, e.g:
#{messages[‘login.username’]}
This is already in the example.
Very good article. Concise, right to the point. This is exactly what I was looking for. Thank you.
Thanks for such a nice and useful article
Pingback: Elegando » Blog Archive » Hibernate Validation
Dear Sir,
I am trying to use validator of JSF from managed bean with Jboss Seam , it is throwing error that method not found exception
Method not found: bean.MYbean@2e3cb1.dcno(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object)
Dear Sir,
How can I use a method validation, for example If I wanna to check the user enter name with database, and then let it throw an error if name mismatch , how…
Hi everybody, here every one is sharing these knowledge, so it’s pleasant to read this webpage, and I used to pay a quick visit this weblog all the time.
If, at the end of this time period, the score is tied, there
are two options the officials can take. Understanding video gaming is
a must tip on how to run a game store. In addition, you can save the effort of coding the store functionality, virtual goods dependencies, billing interfaces and rewards.
If, at the end of this time period, the score is tied, there are two options the officials can take.
Understanding video gaming is a must tip on how
to run a game store. It sounds like you log into the game and join a “Shadow war” server and play with hundreds of
other players within that PVP world, but that world is different
from the cooperative Arkfall boss hunting world.
In other trick taking games, players can take tricks on a number of kind of
contract. Leveling up to defeat all the enemies can be time arresting so
apprehend to absorb a acceptable bulk of hours anniversary day accepting the
a lot of out of this game. Making your game play is the next phase you’ll be focusing on.
Even though your goal is just to lose 5 pounds in a week,
you should be strict with what you do so as not to inadvertently undo all
your hard work for vegetarian weight loss. Authorities inside the
area will need to have an intensive understanding of laboratory and labeling techniques, infection security precautions,
appropriate blood attract approaches to the elderly and for infants and even more.
Hence, broccoli is a must-add ingredient in your vegetarian weight
loss diet.
Even though your goal is just to lose 5 pounds in
a week, you should be strict with what you do so as not to inadvertently
undo all your hard work for vegetarian weight loss.
It’s old news that tracking food intake could lead to losing a few pounds [2].
Hence, broccoli is a must-add ingredient in your vegetarian
weight loss diet.
If you copy that same URL and paste it into your browser, you won’t be blocked.
It’s not rocket science, and it’s no secret either.
Google allows you to utilize as much as 10 pictures and I motivate you to
utilize each 1 of them.
Heya i’m for the first time here. I found this board
and I in finding It really helpful & it helped
me out much. I hope to present one thing back
and help others like you aided me.
Hey there Twitter operates perfectly for my situation however your web site
is running steadily which went on about a few minutes to actually
load up, I’m not sure whether it is my personal problem or perhaps your website issue.
However , thank you for writing superb blog post. I’m assuming it
really has been beneficial to a lot of people who arrived at this point.
I really hope I will be able to find more incredible
stuff and I should really complement you simply by stating you
have carried out incredible job. I ‘ve got your site saved
to bookmarks to check blogs you publish.
Hey Your current site starts up honestly slow to me,
I not really know who’s problem is that but twitter and facebook starts up quite good.
However thank you for writing beautiful article. Almost everyone who visited this great site should have noticed this informative article incredibly handy.
I am hoping I will be able to get further incredible stuff and I also really should compliment by saying you have done awesome writing.
I already have your site book-marked to look at blog
you publish.
Hey there Your entire website runs up literally slow in my situation, I don’t know who’s problem is that
however flickr starts up relatively fast. Anyway, Thanks for
publishing an incredibly lovely article.
I think it really has been extremely helpful visitor who actually visit here.
I personally should state that you actually have done fantastic job with this and also expect to discover even more brilliant things from you.
Just after checking out the blog post, I have bookmarked your site.
Heya I don’t know whether it’s me or even your website but it is starting literally sluggish , I had to spend for a minute to successfully load however , facebook does work absolutely .
However , thanks for writing terrific blog post.
Everybody who actually came to this great site should have
discovered this particular article incredibly helpful.
I should say that you have done amazing work with
this as well as expect to discover much more awesome
things from you. Right after viewing the articles, I have book marked your web page.