One of the new features intruduced with JSF 2 is JSR-303 aka. Bean Validation. With bean validation the input’s are validated against built-in or user defined annotations, placed on the fields, methods or classes.
I’m often in the situation, where I have to validate different values in the same form, depending on what action should be executed. After a lot google’ing and researching, I’ve found the following, pretty easy solution.
Imagine, you have the following managed bean, with the two fields firstname and lastname and a bunch of actions for doing some usefull stuff. But for some obvious reasons one of the actions needs only firstname to be validated, but another action needs firstname and lastname to be validated.
For doing this, we first need the placeholder interfaces for building the two validation groups. I use validate.Both and validate.FirstnameOnly here.
1
2
3
4
5
6
7
8
9
10
11 @ManagedBean
@ViewScoped
public class TestBean implements Serializable {
@NotNull(groups = {Both.class, FirstnameOnly.class},
message = "First name must not be empy")
private String firstname;
@NotNull(groups = {Both.class},
message = "Last name must not be empy")
private String lastname;
Now lets see how to trigger the different validation groups using different commandButtons (or commandLinks, …).
For getting things work, we just add a f:param tag to the commandButtons and assign the full qualified class name of the validation group placeholder interface (If you want more than one, just separate it by comma) to a request parameter (GROUPS in my case).
Now you simply have to attach this value to the validationGroups attribute of the f:validateBean tag.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 <h:form>
<h:messages/>
<h:panelGrid columns="2">
<h:outputText value="First name"/>
<h:inputText value="#{testBean.firstname}">
<f:validateBean validationGroups="#{param['GROUPS']}"/>
</h:inputText>
<h:outputText value="Last name"/>
<h:inputText value="#{testBean.lastname}">
<f:validateBean validationGroups="#{param['GROUPS']}"/>
</h:inputText>
</h:panelGrid>
<h:commandButton value="First and last name"
action="#{testBean.someAction}">
<f:param name="GROUPS" value="validate.Both"/>
</h:commandButton>
<h:commandButton value="First name only"
action="#{testBean.someAction}">
<f:param name="GROUPS" value="validate.FirstnameOnly"/>
</h:commandButton>
</h:form>
If you press the first commandLink now, both fields are validated, and if you press the second, only the first name gets validated.
In simpler cases (also if the current case is really simple), where you just want to exclude some fields from validation, just use the same method for disabling the appropriate validators. This can be done by setting the disabled attribute of the f:validateBean tag using the f:param tag.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 <h:form>
<h:messages/>
<h:panelGrid columns="2">
<h:outputText value="First name"/>
<h:inputText value="#{testBean.firstname}">
<f:validateBean />
</h:inputText>
<h:outputText value="Last name"/>
<h:inputText value="#{testBean.lastname}">
<f:validateBean disabled="#{param['FIRSTNAME_ONLY']}"/>
</h:inputText>
</h:panelGrid>
<h:commandButton value="First and last name"
action="#{testBean.someAction}">
<f:param name="FIRSTNAME_ONLY" value="false"/>
</h:commandButton>
<h:commandButton value="First name only"
action="#{testBean.someAction}">
<f:param name="FIRSTNAME_ONLY" value="true"/>
</h:commandButton>
</h:form>
6 comments
1 ping
Ugo says:
December 23, 2011 at 15:51 (UTC 2 )
Hello,
Nice article !
However I tried the first method with the GROUPS param in the validationGroups attribute, but it didn’t work.
I think that this is because your param is set first when you click the command button, but not before. So when you’re action is performed, the validationGroups attribute isn’t set yet.
Am I wrong ?
Feliciano says:
January 18, 2012 at 16:33 (UTC 2 )
Hey Dirk,
. For me the first method worked perfectly. In fact the f:param tag is set before the validation begins and not as Ugo assumes afterwards.
thanks for your advice
Cheers,
Feliciano
Ugo says:
January 23, 2012 at 12:26 (UTC 2 )
That’s right, your f:param is set before the validation begins, but not before the request is sent, unless you re-render the page with the parameters set.
I’ve tried exactly your code, but still it’s not working. I’m interested in this solution, but I can’t find out how to make it work. Isn’t there some special configuration behind this ?
Dirk Reske says:
January 24, 2012 at 00:19 (UTC 2 )
Hello Ugo,
I’ve created a minimal demo project to show the described behavior: Just download the zip from http://dl.dropbox.com/u/654527/validation-test.zip
Sources and packaged war included.
Greets from germany
Dirk
Ugo says:
January 24, 2012 at 11:06 (UTC 2 )
Hello Dirk,
My friend tested your code yesterday, and we noted that it work just fine. So I came back to my computer and tried to find out what’s wrong with my environment. It just came out that a web.xml configuration was making go your code wrong:
javax.faces.PARTIAL_STATE_SAVING
false
With some deeper research I also learnt that the f:param is actually set into the JSF component tree during the Apply Request Value lifecycle phase, so it is reported into the f:validateBean BEFORE the Validation phase, and I was wrong on that point.
Thank you for your help !
Dirk Reske says:
January 24, 2012 at 19:29 (UTC 2 )
No Problem,
but good to know it’s not working with partial state saving enabled.
Les groupes de validation dynamiques avec JSF 2 et Hibernate Validator > Patate-chaude says:
January 27, 2012 at 15:18 (UTC 2 )
[...] originale est tirée de ce blog. Publié le janvier 27, 2012 par mathieu. Cet article a été publié dans Hibernate, Java, JSF, [...]