Form getting submitted even A4j validation fails +jsf - jsf

i am using a4j for checking username exists or not for onblur event
it displays the error messages when user already exists but ,if i click on
submit button after displaying the error message it gets submitted
when it comes to the required=true for inputtext it doesn't get submitted
required="true" validator="#{RegistrationBean.checkFirstName}">
public void checkFirstName(FacesContext facesContext, UIComponent component, Object value)
{
String name = (String) value;
if(name.trim().length()==0){
System.out.println("Name *******");
String message = bundle.getString("Name_Required");
FacesContext.getCurrentInstance().addMessage("Reg:firstName",
new FacesMessage(FacesMessage.SEVERITY_ERROR, message,message));
}
if(name.trim().equalsIgnoreCase("tom")){
String message = bundle.getString("Name_exists");
FacesContext.getCurrentInstance().addMessage("Reg:firstName",
new FacesMessage(FacesMessage.SEVERITY_ERROR, message,message));
}
}
could anyone suggest me where i went wrong

With the JSF code, it would be easier to help you. So I suggest that you have something like that in your JSF page:
<h:inputText id="firstName" ... validator="#{aBean.checkFirstName}">
The problem on your Java code is that you do not throw any ValidatorException when an error occurs. Thus, your code must be:
public void checkFirstName(FacesContext facesContext, UIComponent component, Object value) {
String name = (String) value;
if ((name == null) || name.trim().length() == 0) {
System.out.println("Name *******");
String message = bundle.getString("Name_Required");
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message)); // Throw the required error
}
if (name.trim().equalsIgnoreCase("tom")) {
String message = bundle.getString("Name_exists");
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message)); // Throw the already exist error
}
}
This way, if the value filled in this field is empty or already exists, a ValidatorException will be thrown, the user will get an error message (do not forget to add the <h:messages/> or <h:message/> component in your form), and the form will not be submitted!

Related

Handle exception thrown from listener method in f:ajax onevent function

I am trying to handle a situation where an exception is thrown (Intentional in example) from my backing bean method that is being executed via ajax listener and I would like to handle it by displaying a toastr message stating that an error occurred with the request. My thought was that I could set a boolean within my bean when the exception is caught and then I would be able to pass that boolean into the onevent function to determine the type of toast message to display.
The problem is that at the time the onevent function is run, the boolean passed in has not been updated until the ajax has run at least twice (value is false on first call, then true on second call). It acts as if the onevent method runs it's cycle (For the 3 stages) and THEN updates the backing bean boolean. Is there a way in which this could work or am I simply not able to do this. I am aware of the OmniFaces FullAjaxExceptionHandler but I would like to handle the exception in a more graceful manner using toast messages provided through toastr. How can I get it so that when the listenerMethod throws an exception I can run a different set of javascript to display the correct information?
Backing Bean
#Named
#ViewScoped
#Data
public class ExampleBean implements Serializable {
private static final long serialVersionUID = 1L;
private Boolean ajaxError;
public void initialize() {
log.debug("Initialized Bean");
ajaxError = false;
}
public void listenerMethod() {
ajaxError = false;
try {
// method logic... throw intentional exception for now
throw new Exception();
} catch (Exception e) {
ajaxError = true;
}
}
XHTML
<h:commandLink id="ajax-link">
<h:outputText value="Ajax Link" />
<f:ajax listener="#{exampleBean.listenerMethod()}"
render="Ids..."
onevent="function(data) { ajaxEvent(data, '#{exampleBean.ajaxError}') }" />
</h:commandLink>
JavaScript
function ajaxEvent = function(data, ajaxError) {
var status = data.status;
var title = 'Title';
var message = 'Description message';
console.log("AjaxError: " + ajaxError);
switch (status) {
case 'begin':
// logic...
break;
case 'complete':
// other logic...
break;
case 'success':
if (ajaxError === 'true') {
title = 'Error';
message = 'An error occurred. Please try again later.';
toastr['error'](message, title);
} else {
title = 'Success';
message = 'Successful. No Exceptions Thrown.';
toastr['success'](message, title);
}
break;
}
}

Localize Bean Validation messages in JSF app based on a property - I've only 1 file with a key for English and another key for Spanish

ValidationMessages.properties
error.name.invalid= Inavlid name
error.name.invalid.spanish= some spanish text
How to use the Spanish validation message instead of English just for a single page in the application based on a property value?
If you really would like to do this, you could create custom validators. For example:
#FacesValidator("yourValidator")
public class YourValidator implements Validator
{
#Override
public void validate(FacesContext context, UIComponent component, Object value)
throws ValidatorException
{
ResourceBundle resourceBundle = ResourceBundle.getBundle("/ValidationMessages");
String key = yourKey + (yourProperty ? "" : ".spanish");
String message = resourceBundle.getString(key);
FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message);
throw new ValidatorException(facesMessage);
}
}
See also:
How to perform validation in JSF, how to create a custom validator in JSF

JSF greater than zero validator

How do you create a validator in JSF that validates the input text if it is greater than zero?
<h:inputText id="percentage" value="#{lab.percentage}">
<f:validateDoubleRange minimum="0.000000001"/>
</h:inputText>
I have the code above but I am not sure if this is optimal. Although it works but if another number lesser than this is needed then I need to change the jsf file again.
The use case is that anything that is greater than zero is okay but not negative number.
Any thoughts?
Just create a custom validator, i.e. a class implementing javax.faces.validator.Validator, and annotate it with #FacesValidator("positiveNumberValidator").
Implement the validate() method like this:
#Override
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
try {
if (new BigDecimal(value.toString()).signum() < 1) {
FacesMessage msg = new FacesMessage("Validation failed.",
"Number must be strictly positive");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg);
}
} catch (NumberFormatException ex) {
FacesMessage msg = new FacesMessage("Validation failed.", "Not a number");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg);
}
}
And use it in the facelets page like this:
<h:inputText id="percentage" value="#{lab.percentage}">
<f:validator validatorId="positiveNumberValidator" />
</h:inputText>
Useful link: http://www.mkyong.com/jsf2/custom-validator-in-jsf-2-0/

How to show multi error message in jsf while validation is in EJB?

Based on the answer from this question, i understand that if there is an error, EJB will throw an exception which will be catch in the backing bean and backing bean will show user an error message based on exception its catch.
My question is, what if theres more than one error? How can i show multiple error message to the user, while the EJB can only throw one exception at a time?
For example, at registration form user will need to input email address, name, password, and re-password, and must not be null. If all the data is valid but the given email address is already exist, EJB will throw EntityExistException and the user will be notified that email address is already registered. What if theres multiple error like password and re-password not match and the name is empty? And i want to show these two error to the user. What exception should EJB throw? What approach i can take to achieve this?
Note: the validation must be in EJB
You shouldn't be doing validation in a backing bean action method, but in a normal Validator.
E.g.
<h:inputText value="#{register.email}" required="true" validator="#{emailValidator}" />
<h:inputSecret binding="#{password}" value="#{register.password}" required="true" />
<h:inputSecret required="true" validator="confirmPasswordValidator">
<f:attribute name="password" value="#{password.value}" />
</h:inputSecret>
...
with the #{emailValidator} being something like this:
#MangedBean
public class EmailValidator implements Validator {
#EJB
private UserService userService;
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if (value == null) {
return; // Let required="true" handle.
}
if (userService.existsEmail((String) value)) {
throw new ValidatorException(Messages.createError("Email already exists"));
}
}
}
Note that the EJB shouldn't throw an exception here. It should only do that when there's a fatal and unrecoverable error such as DB down or wrong table/column definitions.
And the confirmPasswordValidator being something like this
#FacesValidator("confirmPasswordValidator")
public class ConfirmPasswordValidator implements Validator {
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
Object password = component.getAttributes().get("password");
if (value == null || password == null) {
return; // Let required="true" handle.
}
if (!password.equals(value)) {
throw new ValidatorException(Messages.createError("Password do not match"));
}
}
}

How to put validation on p:fileUpload

Along with couples inputText, one of a mandatory component that I have on the page is a p:fileUpload. So when I click submit, <p:message> show up on component that have require=true, but the user did not type/select
I want the red box Required also appear next to the upload component. Here is what I have tried.
1 . when I set required="true" in p:fileUpload, nothing really happen (not sure if this is a bug).
2 . I put validator in p:fileUpload, below is my validator sources
public void validateFileUpload(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
if(value == null){
FacesMessage message = new FacesMessage();
message.setSeverity(FacesMessage.SEVERITY_ERROR);
message.setSummary("Error");
message.setDetail("Required");
throw new ValidatorException(message);
}
}
nothing really happen when I click submit, not even when I go through the upload, validateFileUpload did not get called at all (not sure if this is a bug)
3 . When I click submit, if everything else pass, and I get into my action method, I am able to check if the file is null or not, then return a FacesMessage and let p:growl pick it up. However, I dont like it that way since it give the user a feeling of multiple layer of validation.
Is there a way to do better validation on p:fileUpload?
For those with the same problem, I ran into this problem while creating a wizard. The workaround I used was to store the uploaded file in a field of my viewscoped bean and check this field when trying to navigate to the next step.
Wizard tag:
<p:wizard id="importBankAccountLogWizard"
widgetVar="importBankAccountLogWizard"
flowListener="#{bankAccountLogImportBean.onFlowProcess}">
File upload tag (I have the rendered and the update attribute set up so that a message will be shown and the uploaded will be hidden after the first upload):
<p:fileUpload id="bankAccountLogFileInput"
fileUploadListener="#{bankAccountLogImportBean.setBankAccountLogFile}"
rendered="#{bankAccountLogImportBean.renderFileUploadInput}"
mode="advanced"
update="importBankAccountLogWizard"
auto="true"
sizeLimit="1000000" />
Bean:
public void setBankAccountLogFile(FileUploadEvent event)
{
importFile = event.getFile();
FacesMessage msg = new FacesMessage(Localization.g("FILE_HAS_BEEN_UPLOADED", event.getFile().getFileName()));
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public String onFlowProcess(FlowEvent event)
{
if("bankAccountLogImportInputTab".equals(event.getOldStep()) &&
importFile == null)
{
FacesMessage msg = new FacesMessage(Localization.g("UPLOAD_A_FILE_TO_CONTINUE"));
FacesContext.getCurrentInstance().addMessage(null, msg);
return event.getOldStep();
}
return event.getNewStep();
}

Resources