You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.
You may run into situations where JSF validation logic other than Hibernate Validator (or custom Hibernate Validator) is required. I have tried using Hibernate Validators (e.g. @org.hibernate.validator.Pattern) with SFSB/SLSB methods. This is not recommended or supported in the context of a Seam application.
An example I ran into recently is as follows:
1) user enters data into HtmlInputText in a HtmlForm 2) we require live validation using a4j:support (usually using onblur for HtmlInputText and onchange for HtmlSelectOneMenu)
We are performing live validation to check that the data the user entered is valid (i.e. already exists in a db table code column) as well as for duplicates. This validation requires a db read so therefore we will implement this validation using Seam validation.
This is implemented by adding a validator attribute to the HtmlInputText component. The value of the validator attribute should be the name of the Seam validator component (in this case JavaBean that implements javax.faces.validator.Validator and java.io.Serializable interfaces.) Also, the validator class should be annotated with @org.jboss.seam.annotations.faces.Validator. Note that with this single validator class, we can validate for three different scenarios. And the good thing is that this implementation supports re-usability, in case you have other use cases that require this business validation functionality. Enjoy!
Here's a partial code snippet:
@Name("seamValidatorProblemCodes")
@Scope(ScopeType.CONVERSATION)
@org.jboss.seam.annotations.faces.Validator
public class SeamValidatorProblemCodes implements javax.faces.validator.Validator, java.io.Serializable
{
@Logger
Log log;
//skipping instance variables for brevity...
public void validate(FacesContext context, UIComponent cmp, Object value) throws ValidatorException
{
if (value != null)
{
cmpId = cmp.getId();
log.info("validate(): cmpId = "+cmpId);
clientId = cmp.getClientId(context);
log.info("validate(): clientId = "+clientId);
String mode = "";
Boolean dupeExists = false;
//validation for modalPanel (edit problem code in RepairCaseDetails)
if (value instanceof DropDownValue)
{
DropDownValue ddv = (DropDownValue)value;
problemCode = Integer.toString(ddv.getCode());
mode = "edit";
dupeExists = checkForDupes(cmp, value, mode);
if (dupeExists)
{
disableSubmitButton = true;
throw new ValidatorException(new FacesMessage("this problem code already exists for this repair Id, please select a different one"));
}
else
disableSubmitButton = false;
}
//validation for problem code adds (CreateRepairCase)
else
{
problemCode = (String)value;
if (problemCode != null && !problemCode.equals(""))
{
if (!validateProblemCodes(problemCode))
{
throw new ValidatorException(new FacesMessage("invalid value")); //doesn't apply to edit code b/c UI is dropdown...
}
mode = "add";
dupeExists = checkForDupes(cmp, value, mode);
if (dupeExists)
{
throw new ValidatorException(new FacesMessage("duplicates not allowed"));
}
}
}
}
}
In your xhtml, use something like this:
<s:decorate id="problemCode1" template="layout/edit.xhtml">
<h:inputText id="_problemCode1"
value="#{createRepairCase.problemCode1}"
validator="seamValidatorProblemCodes">
<a4j:support event="onblur"
reRender="problemCode1"
bypassUpdates="true"
eventsQueue="myQueue"
requestDelay="200"
ignoreDupResponses="true"
oncomplete="setFocusProblemCodes();" />
</h:inputText>
</s:decorate>
Request: I'm not sure whether I can post this comment-cum-query towards your valuable tip. Regret for any inconvenience caused!
I need an elaboration towards following w.r.t injection(@In) of inherited class from org.jboss.seam.framework.EntityQuery:
1. Is java.io.Serializable for validator, must?
2. 'checkForDupes(cmp, value, mode)': Implementation if feasible
Problem: I need to check the duplicate ID from the database towards inputted ID.
Work: I tried to use '@In(create true) IssuesList' [extended from EntityQuery] in extended validators class. However it throws nullpointer exception. And if I use as 'IssuesList issueList = new IssuesList()', unexpected results.
Please assist/clarify to resolve the problem.
Code:
`
@Name("MyValidator")
@BypassInterceptors
@Validator
@Scope(ScopeType.CONVERSATION)
public class MyValidator implements javax.faces.validator.Validator
{
@In Identity identity;
@Logger private Log log;
@In FacesMessages facesMessages;
@In(create=true)
IssuesList issuesList;
public void validateIssueId(FacesContext arg0,UIComponent arg1, Object arg2)throws ValidatorException
{
System.out.println("@PasswordValidator.validateIssueId()");
// IssuesList issuesList = new IssuesList();
int size = -1;
try {
String issueId = arg2.toString();
System.out.println("Issue Id Entered: "+ issueId);
issuesList.getIssues().setIssueId(issueId);
System.out.println("Issue Id For Restriction: "+ issuesList.getIssues().getIssueId());
size = issuesList.getResultList().size();
System.out.println("ResultSet size: "+size);
} catch (Exception e) {
System.out.println("@PasswordValidator.validateIssueId(): "+e);
System.out.println("issuesList: "+issuesList);
}
if(size > 0){
throw new ValidatorException(new FacesMessage("IssueId already exists!", null));
}else{
throw new ValidatorException(new FacesMessage("IssueList is null!", null));
}
}
}
`
Thank you in advance!
Forum Post
1. Is java.io.Serializable for validator, must?
</blockquote>
I don't know what the technical reason is, but yes, I have found that if I don't make the validator Serializable, it doesn't work.
<blockquote>
2. 'checkForDupes(cmp, value, mode)': Implementation if feasible
Problem: I need to check the duplicate ID from the database towards inputted ID.
Work: I tried to use '@In(create true) IssuesList' in extended validators class. However it throws nullpointer exception. And if I use as 'IssuesList issueList = new IssuesList()', unexpected results.
</blockquote>
The @BypassInterceptors annotation means that @In won't work.
You should use Component.getInstance(), something like:
'issueList = (IssueList)Component.getInstance("issueList");'
Oops, is there any way to edit a post? I have stuffed the formatting...
(And I see it has already been answered in the forum anyway)
Seam 2.1 and after requires @BypassInterceptors for Seam validators.
I'm learning Objective-C, it's about time I learned an OO language other than Java!