JSF Seam Validation + Custom Messages + Annotations + Internationalization

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:

  1. Validating required fields without using annotations
  2. Validating manually and displaying custom messages
  3. 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&#91;'login.username'&#93;}"/></td>
	    <td>
		<h:inputText required="true" value="#{user.username}" label="#{messages&#91;'login.username'&#93;}"/>
	    </td>
	</tr>
	<tr>
	    <td><h:outputText value="#{messages&#91;'login.password'&#93;}"/></td>
	    <td>
		<h:inputSecret required="true" value="#{user.password}" label="#{messages&#91;'login.password'&#93;}"/>
	    </td>
	</tr>
	<tr>
	    <td></td>
	    <td>
		<h:commandButton action="#{loginAction.login}"
				 value="#{messages&#91;'button.login'&#93;}"/>
	    </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:

  1. The injected user variable in LoginAction so Seam knows to validate it
  2. The User objects properties to specify what to validate.
    1. 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&#91;'login.username'&#93;}"/></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:

      • @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

      That’s all there is to it.

      Advertisements

26 thoughts on “JSF Seam Validation + Custom Messages + Annotations + Internationalization

  1. Sefai

    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?

    Reply
  2. Arsenalist Post author

    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.

    Reply
  3. Pingback: Elegando » Blog Archive » Hibernate Validation

  4. Anjaya Pillai

    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)

    Reply
  5. Anjaya Pillai

    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…

    Reply
  6. Lydia

    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.

    Reply
  7. celtic Woman

    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.

    Reply
  8. schwinn

    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.

    Reply
  9. Joann

    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.

    Reply
  10. Lisette

    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.

    Reply
  11. Magdalena

    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.

    Reply
  12. Isabell

    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.

    Reply
  13. www.fifaworldhacks.com

    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.

    Reply
  14. dota2hack.org

    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.

    Reply
  15. fifa15psp.com

    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.

    Reply

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