Reputation:
This is my project structure:
This is in my XHTML file:
<h:inputText id="username" value="#{user.username}" required="true"
validator="#{UsernameValidator}" />
<h:message for="username"/>
And here is UsernameValidator
class:
@FacesValidator("UsernameValidator")
public class UsernameValidator implements Validator {
@Override
public void validate(FacesContext fc, UIComponent uic, Object value) throws ValidatorException {
JOptionPane.showMessageDialog(null, "in validator class");
if (String.valueOf(value).length() == 0 || String.valueOf(value).length() < 3) {
FacesMessage message = new FacesMessage("Username Validation Failed", "Invalid Username");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
But when I write something in username
field, This error happens:
/Registration.xhtml @19,81 validator="#{UsernameValidator}": Identity 'UsernameValidator' was null and was unable to invoke
Upvotes: 0
Views: 864
Reputation: 5021
As your question was a little modified, I added a strikeout to the content related to your original question:
First, The application level validation include points 3 and 4 (Custom validation using Validator interface and Validation methods in backing beans) in addition to using Custom Component.
It seems that you are mixing up Validation using bean methods and implementing custom validator classes (the two last ones), a quick refresh about this two approaches taking your code as an example :
This is the most simple one, as hou will just need to add validation method to your class and invoke it through a method expression using the validator
attribute, like your example :
<h:inputText id="username" value="#{user.username}" required="true" validator="#{usernameValidator}" />
// I changed to usernameValidator to respect naming conventions
But, in that case, usernameValidator
is a method in the user
@ManagedBean
, something like this:
@ManagedBean("user")
@SessionScoped
public class User implements Serializable{
// Please notice that this method should have the same signature as the validate method of the interface Validator
public void usernameValidator(FacesContext fc, UIComponent uic, Object value) throws ValidatorException {
JOptionPane.showMessageDialog(null, "in validator class");
if (String.valueOf(value).length() == 0 || String.valueOf(value).length() < 3) {
FacesMessage message = new FacesMessage("Username Validation Failed", "Invalid Username");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
The implementation for the Class is the same as what you did, which is implementing the Validator
Interface, and registring the Validator by giving it and ID
, I will copy your exact code to make the answer clean:
// I just changed the ID from UsernameValidator to usernameValidator
@FacesValidator("usernameValidator")
public class UsernameValidator implements Validator {
@Override
public void validate(FacesContext fc, UIComponent uic, Object value) throws ValidatorException {
JOptionPane.showMessageDialog(null, "in validator class");
if (String.valueOf(value).length() == 0 || String.valueOf(value).length() < 3) {
FacesMessage message = new FacesMessage("Username Validation Failed", "Invalid Username");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
}
You can give and ID
to your Validator by using annotation @FacesValidator("usernameValidator")
(which you already did), Or in the faces-config.xml
by adding the following:
<validator>
<validator-id>usernameValidator</validator-id>
<validator-class>yourpackage.UsernameValidator</validator-class>
</validator>
Then, you will use the same ID
in the f:validator
Tag, like this:
<h:inputText id="username" value="#{user.username}" required="true">
<f:validator validatorId="usernameValidator" />
</h:inputText>
NB: This is not all validation appraoches in JSF, but I think that these two are the simplest ones for Custom validation which you can use in your example (It's the 4 and 3 respectively in the list of JSF validation ways you provided).
As additional information, I will also give a brief review about the Built-in validation components which doesn't fit to your Code example:
JSF (I am talking about 2.0 as I am not sure if there is some new ones in JSF 2.2) has standard validators that you can use to validate:
String
using f:validateLength
double
/ long
value within an optional range using f:validateDoubleRange
/ f:validateLongRange
respectivly.String
against a regular expression using f:validateRegex
f:validateRequired
or the attribute required
There is another alternative for using those Tags by using the f:validator
, you can find a good example here.
Upvotes: 2
Reputation: 1108802
Your mistake is here:
<h:inputText ... validator="#{UsernameValidator}" />
You're trying to reference a @FacesValidator
as a managed bean. This won't work. The value in the @FacesValidator
annotation represents the application-wide validator ID which is to be specified as a string, not a managed bean name.
So, below should do:
<h:inputText ... validator="UsernameValidator" />
True, you'll probably have seen code snippets wherein a validator (or converter) is referenced as a managed bean via #{...}
. But in those cases they are actually also registered as a managed bean via @ManagedBean
or @Named
instead of @FacesValidator
(or @FacesConverter
).
@ManagedBean
@RequestScoped
public class UsernameValidator implements Validator {}
This is often done so in order to be able to inject an EJB into it so that any necessary business/DB logic could be performed.
Unrelated to the concrete problem: the below
JOptionPane.showMessageDialog(null, "in validator class");
Is a very, very bad way to perform "logging" in a web application. Please stop doing that.
Upvotes: 2
Reputation: 521457
There appears to be a problem in your Registration.xhtml file. The validator requires a separate tag inside the <h:inputText> tag:
<h:inputText id="username" value="#{user.username}" required="true">
<f:validator validatorId="UsernameValidator" />
</h:inputText>
<h:message for="username" />
The error you have seems to be caused by JSF not being able to find the validation bean. Your project directory looks OK but check to make sure the class file for UsernameValidator is there and can be read by your app server.
Upvotes: 0