In this
post, you can see how to use OmniFaces, <o:validateBean>
validator to control bean validation on a per-UICommand (it can be used on
a per-UIInput
also).
So, let's
build a scenario to emphasize a use case of <o:validateBean> on a
per-UICommand.
Let's suppose that we have a simple form that contains two input fields
representing the name and the e-mail of an website member or admin. Next to these
inputs, we have two buttons, one with label Contact Member and another
one with label Contact
Admin. When the user clicks on the first button, he will
"contact" the specified website member, and when he clicks on the
second button, he will "contact" the specified website admin. The
form is:
<h:form>
Name:
<h:inputText value="#{contactBean.name}"/>
E-mail:
<h:inputText value="#{contactBean.email}"/>
<h:commandButton value="Contact
Member" action="contact_member"/>
<h:commandButton value="Contact
Admin" action="contact_admin"/>
</h:form>
For a
website member/admin the name input should not violate any of the next
validation constrains (snipped from Contact Bean):
@Size.List({
@Size(min = 3, max = 20, message =
"(member)# please enter a valid name (between 3-20 characters)",
groups = beans.MemberContactValidationGroup.class),
groups = beans.MemberContactValidationGroup.class),
@Size(min = 6, max = 10, message =
"(admin)# please enter a valid name (between 6-10 characters)",
groups = beans.AdminContactValidationGroup.class)
groups = beans.AdminContactValidationGroup.class)
})
@Pattern(regexp
= "(admin)[a-zA-Z0-9]*", message = "(admin)# please enter a
valid name (it should start with admin...)",
groups = beans.AdminContactValidationGroup.class)
groups = beans.AdminContactValidationGroup.class)
private
String name;
For a
website member/admin the email input should not violate any of the
next validation constrains (snipped from Contact Bean):
@Size(min =
1, message = "Please enter the e-mail !")
@Pattern.List({
@Pattern(regexp = "[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]+",
message = "(member)# please enter a valid formated e-mail",
groups = beans.MemberContactValidationGroup.class),
groups = beans.MemberContactValidationGroup.class),
@Pattern(regexp =
"(admin)+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]+", message = "(admin)#
please enter a valid e-mail (it should start with admin@...)", groups =
beans.AdminContactValidationGroup.class)
})
private
String email;
So, in
group, MemberContactValidationGroup
we have added the constrains for the members of a website, and, in the AdminContactValidationGroup
group we have added the constraints for the admins of the website. Moreover, we
have a constraint over email in the default group.
Next, we
should "attached" these constraints to the name and email
inputs, but, we need to obtain the following functionality:
·
if the user clicks on the Contact
Member button, then the validation should take into account only constraints
from default group and from MemberContactValidationGroup, and ignore the
constraints from AdminContactValidationGroup
·
if the user clicks on the Contact Admin
button, then the validation should take into account only constraints from default
group and from AdminContactValidationGroup,
and ignore the constraints from MemberContactValidationGroup
In a naive approach,
you may think that the below snippet will do the job:
<h:form>
<f:validateBean
validationGroups="javax.validation.groups.Default,
beans.MemberContactValidationGroup, beans.AdminContactValidationGroup">
beans.MemberContactValidationGroup, beans.AdminContactValidationGroup">
Name:
<h:inputText value="#{contactBean.name}"/>
E-mail: <h:inputText
value="#{contactBean.email}"/>
</f:validateBean>
<h:commandButton value="Contact
Member" action="contact_member"/>
<h:commandButton value="Contact
Admin" action="contact_admin"/>
</h:form>
Well, it
doesn't work! In the above snippet of code we attached all constraints (member
+ admin constrains) to the name and email inputs. This means
that it just doesn't matter if you click on Contact Member or on Contact
Admin button, because all constrains will be applied (obviously, not
desirable). Finding a solution will end up in boilerplate code, because it will
required a bunch of tags, EL expressions, conditions, server-side code, etc.
Most likely, at the end, our form will look like a total mess.
OmniFaces
provides a custom validator that can help us to solve these kind of tasks. This
validator is exposed to JSF page authors via <o:validateBean> tag.
Among its features, it can be used to control bean validation on a per-UICommand,
which is perfect for our use case. So, we just remove the <f:validateBean>,
and add <o:validateBean>
nested in <h:commandButton>,
as below:
xmlns:o="http://omnifaces.org/ui"
...
<h:form>
Name: <h:inputText
value="#{contactBean.name}"/>
E-mail: <h:inputText
value="#{contactBean.email}"/>
<h:commandButton value="Contact
Member" action="contact_member">
<o:validateBean
validationGroups="javax.validation.groups.Default,
beans.MemberContactValidationGroup"/>
</h:commandButton>
<h:commandButton value="Contact
Admin" action="contact_admin">
<o:validateBean validationGroups="javax.validation.groups.Default,
beans.AdminContactValidationGroup"/>
</h:commandButton>
</h:form>
Done! Now,
everything will work as expected. Complete source code on GitHub.
Check
OmniFaces Showcase to see more details about <o:validateBean>.
Beside an example that allows the developer to control bean validation on a
per-UICommand,
you can see an example of how to use <o:validateBean> to validate a
given bean at the class level.
Niciun comentariu :
Trimiteți un comentariu