JSF form validation with AJAX and validator class [duplicate] - ajax

This question already has answers here:
How to perform JSF validation in actionListener or action method?
(5 answers)
Closed 3 years ago.
I have an assignment for university where we shall validate form input with AJAX and a Validator Class. Now, I have used AJAX in JSF for filtering a list. But I don't know how to combine it with a validator. The validation should happen when user leaves input field. The validator should check if email input matches a regex pattern and if there is an existing user with the same email. If validation fails, a FacesMessage should be shown. How do I connect the dots?
This is part of a bigger project and I have tried to include only the relevant code.
FILE STRUCTURE (only relevant part)
.
├── java
│ ├── dao
│ ├── logic
│ ├── presentation
│ │ ├── managedbeans
│ │ │ └── UserBean.java
│ │ └── validator
│ │ └── Email.java
│ │
│ └── transfer
└── webapp
└── signup.xhtml
THE CODE
signup.xhtml only relevant part of the form
<h:form id="registerForm" class="col l6 s12 center">
<h:outputLabel for="eMail" value="Email" class="active" />
<h:inputText
id="eMail"
value="#{user.email}"
class="validate"
requiredMessage="Email is required"
label="eMail"
maxlength="25"
alt="email"
autocomplete="on"
required="true">
<f:validator validatorId="emailValidator"/>
<f:ajax event="change" listener="#{user.validateEmail}" execute="eMail" render="emailError"></f:ajax>
</h:inputText>
<h:message for="eMail" id="emailError" />
<h:commandButton value="Sign up" action="#{user.addUser}" class="waves-effect waves-light btn" type="submit" />
</h:form>
Email.java
import java.util.regex.Pattern;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
#FacesValidator("emailValidator")
public class Email implements Validator {
private static final Pattern EMAIL_PATTERN = Pattern.compile("[\\w\\.-]*[a-zA-Z0-9_]#[\\w\\.-]*[a-zA-Z0-9]\\.[a-zA-Z][a-zA-Z\\.]*[a-zA-Z]");
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
if( value == null) {
return;
}
String email = (String) value;
boolean matches = EMAIL_PATTERN.matcher(email).matches();
if(!matches) {
FacesMessage msg = new FacesMessage(
FacesMessage.SEVERITY_FATAL,
"Email is invalid",
null);
throw new ValidatorException(msg);
}
}
}
UserBean.java
So, I thought it might make sense to call a function validateEmail in the UserBean and then call the validate function within the Validator Class. But I am really not sure about this. How would I pass the parameters context, component and value?
public void validateEmail(AjaxBehaviorEvent e) {
// Email emailValidator = new Email();
// emailValidator.validate(context, component, value);
}

You could validate your email in your XHTML files.
For that, have a look on this:
Email validation using regular expression in JSF 2 / PrimeFaces
So you only actually need to validate, if Username or Email already exists. You can do that in a validation class for the University.
If you have a validation in your UserManager already, you can use that in the validation class.
regards

Related

Ajaxified SelectOneListBox not working [duplicate]

This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 5 years ago.
I wanted to test if an ajaxified <p:selectOneListBox> element works fine or not. On a JSF+PrimeFaces based portlet I've created the above code. Basically, on a item selection from a <p:selectOneListBox> list, I want to update a label with the value of the previously selected item. Unfortunately, it doesn't seem to work as expected.
.xhtml side:
<form id="myform">
<p:selectOneListbox id="myselect" value="#{bean.optionSelected}">
<p:ajax listener="#{bean.onChange}" process="myselect" update="toupdate" onstart="onstart()" oncomplete="oncomplete()" onerror="onerror()" onsuccess="onsuccess()"/>
<f:selectItem itemLabel="Option 1" itemValue="1" />
<f:selectItem itemLabel="Option 2" itemValue="2" />
<f:selectItem itemLabel="Option 3" itemValue="3" />
</p:selectOneListbox>
<h:outputText id="toupdate" value=">#{bean.optionSelected}" />
</form>
Bean side:
#ManagedBean(name = "bean")
#ViewScoped
public class Bean implements Serializable {
private static final long serialVersionUID = 201709131528L;
private static Logger logger = Logger.getLogger(Bean.class);
private String optionSelected = "-1";
public Bean() {
logger.trace("bean created");
}
#PostConstruct
private void onPostConstruct() {
logger.trace("start");
}
public String getOptionSelected() {
return this.optionSelected;
}
public void setOptionSelected(String optionSelected) {
logger.trace("start");
this.optionSelected = optionSelected;
}
public void onChange() {
logger.trace("start");
}
}
Every time I select an option from the list I've got the following log from the console:
Bean:<init>():bean created
Bean:onPostConstruct():start
And from the console of my browser I've got the following log:
onstart():
onerror():
oncomplete():
As a newcomer to the JSF+PF world, I'd like to know:
1) why the onChange() listener is not invoked.
2) why the property optionSelected is not set.
3) why the bean bean is created on each option selection.
4) why the ajax request fails.
Any clarification would be really apreciated. Thanks.
As a newcomer to the JSF+PF world, I'd like to know: 1) why the onChange() listener is not invoked. 2) why the property optionSelected is not set. 3) why the bean bean is created on each option selection. 4) why the ajax request fails.
I believe all of your issues are caused by the fact that you are using an html <form> element rather than a JSF <h:form> component. I was able to reproduce all these errors locally on my machine (except #4 for some reason), and once I changed the <form> into an <h:form>, everything worked correctly.
For more information on what the JSF h:form tag does, check out these links:
https://docs.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/facelets/h/form.html
https://docs.oracle.com/cd/E17802_01/j2ee/javaee/javaserverfaces/2.0/docs/api/javax/faces/component/html/HtmlForm.html
What exactly does JSF h:form tag
How to use <f:ajax> in a plain <form> instead of <h:form>?
How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms?

Input value doesn't clear after validation failure

I've searched a lot and haven't found a solution.
I'm using JSF 2.1 and RichFaces 4.2.3 and want to validate the login data of the user
I have two input fields.
One Username and one Password, both with #NotEmpty
login.xhtml
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:mt="http://java.sun.com/jsf/composite/components">
<h:body>
<ui:composition template="/protected/user/login-template.xhtml">
<ui:define name="panel-navigation">
<ui:include src="/protected/user/login-left-menu.xhtml" />
</ui:define>
<ui:define name="contentbody">
<h:form>
<div id="content">
<div class="subcolumns">
<div class="c65l">
<div class="subcl">
<p class="sum-error-message" />
<fieldset>
<h3>
<h:outputText value="#{styleguideMessages.login}" />
</h3>
<p>
<h:outputText value="#{messages.login_text}" />
</p>
<div class="subcolumns">
<mt:inputText
id="loginName"
value="#{authenticationPM.loginName}"
label="#{messages.general_label_loginname}"
required="true" />
<div class="c33r validation"></div>
</div>
<div class="subcolumns">
<mt:inputText
id="password"
value="#{authenticationPM.password}"
label="#{styleguideMessages.db_password}"
required="true"
secret="true" />
<div class="c33r validation"></div>
</div>
<div class="subcolumns">
<h:commandLink
id="loginButton"
action="#{authenticationPM.doLogin}"
value="#{styleguideMessages.login}"
title="#{styleguideMessages.login}"
styleClass="button last" />
</div>
</fieldset>
</div>
</div>
</div>
</div>
<mt:commandButton
id="login"
action="#{authenticationPM.doLogin}"
value="hidden"
style="visibility:hidden" />
</h:form>
<script
src="#{facesContext.externalContext.requestContextPath}/js/lib/loginEnter.js"
type="text/javascript"
charset="utf-8"></script>
</ui:define>
</ui:composition>
AuthentificationPM.java
import *;
#Named
#SessionScoped
public class AuthenticationPM extends AbstractPM implements Serializable {
/**
* The user name from the login.
*/
private String userName;
/**
* password.
*/
private String password;
/**
* Returns the login name.
*
* #return String
*/
#NotNull
#Pattern(regexp = "^[^\"/\\[\\]:;|=,+?*<>]*$", message = "{user.loginname.pattern}")
public String getLoginName() {
return userName;
}
/**
* Returns the password.
*
* #return String
*/
#NotNull
public String getPassword() {
return password;
}
/**
* Sets the login name.
*
* #param loginName
* - the login name of the user
*/
public void setLoginName(String loginName) {
this.userName = loginName;
}
/**
* Sets the password.
*
* #param password
* - the password of the user
*/
public void setPassword(String password) {
this.password = password;
}
}
If one of those (say the password) is not filled, the validation fails and a message is shown (as it should).
Now I delete the username and type in a password.
The validation fails because the username is empty.
It cleans the password field and displays a message for the username.
And now the error happens: the former entered username reappeares!
How can I prevent this behaviour?
I know that after process validation, the update model values and invoke application are skipped and the render response is executed. As described here. The render response takes the values stored in the ui component (at apply requests) and uses them to rerender instead of deleting the invalid value.
I've tried this solution as well as this idea. Both ways don't find my component.
Any help or ideas are very appreciated.
Greetings,
Kevin
If you just erase the username from the inputfield, the value should be submitted as an empty string, which would be a legit replacement for the username and also matches the pattern defined.
I can only assume, that you have configured
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
in your web.xml. So, when you try to submitt an empty field, it is interpreted as null, which will not match your #NotNull Annotation on the username attribute. So, the setting of the value is canceled and it will maintain its prior state, cause it's SessionScoped - which is the username that has been entered once.
At least this is the only szenario a (String-)value is not updated when an empty string is submitted I can imagine.
Having this value set to true allows to reproduce the behavior you are describing.
You might ask, why this does not apply for your textbox where you are entering the password when erasing it? Since you are using secret="true" the text-box will not show any information about the string entered (i.e. the length), even if the backing bean attribute is not set to null (after removing the password) and still contains the wrong password.
But be aware that simply removing this attribute might screw functionality where other devs are relying on to get null instead of the empty string. So you should maybe consider to remove the #NotNull annotation and check for null manually.

TabChangeEvent not reaching listener with validation error

I am currently working on a project using Primefaces 4.0 and JEE 6. As a build-tool we use maven, and we got a JBoss Application Server.
So it was supposed to be simple. When a validation error occurs, I was supposed to prevent a tab-change in my view. Nothing big, but it needed to be done.
What happened next totally flabberghasted me, but first what I did:
Define a backing bean to handle the event.
Define a listener there.
Use <p:ajax /> to fire the tabChange event to my bean.
Well it was simple enough until there. When there were no validation errors, it worked just fine. Then I tried to validate the values in the view against my Model-Bean and was quickly stopped in my tracks.
As soon as I willingly produced errors in the View, to trigger the faces messages, the tabChange listener was not executed anymore. In fact, not even the #RequestScoped controller-class with the listener was constructed.
I proceeded to create a minimal working example with help of the Weld CDI maven archetype.
Now here I stand, at wits end and present to you my example:
home.xhtml:
I removed the surrounding xml-declaration and ui:define stuff, but that's what I took to reproduce it.
<h1>Hello World!</h1>
<p>
Your CDI bean
<code>HelloWorld</code>
says <span style="color: blue;">#{helloWorld.text}</span> using the
Unified EL.
</p>
<h:form id="bv">
<h2>Bean Validation examples</h2>
<p>Enforces annotation-based constraints defined on the model
class.</p>
<p:tabView id="tabView" effect="fade"
effectDuration="normal">
<p:ajax event="tabChange" update="tabView" listener="#{controller.tabChange}"/>
<p:tab title="Tab 1">
<table>
<tr>
<th style="text-align: right;"><h:outputLabel for="letters"
value="Letters:" /></th>
<td><p:inputText id="letters" value="#{helloWorld.letters}" />
<p:message for="letters" errorClass="invalid" /></td>
</tr>
</table>
</p:tab>
<p:tab title="Tab 2">
<p>Random text to be displayed</p>
</p:tab>
</p:tabView>
</h:form>
Controller.java:
here I only removed the package-declaration, for the protection of the innocent.
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import org.primefaces.event.TabChangeEvent;
#Named
#RequestScoped
public class Controller implements Serializable {
private static final long serialVersionUID = -1126987875831465303L;
public Controller() {
}
#PostConstruct
public void init() {
System.out.println("Constructed " + this.getClass().getSimpleName());
}
public void tabChange(final TabChangeEvent event) {
System.out.println("Listener was reached");
}
}
Last but not least, the model-bean, slightly shortened from what the archetype provides:
HelloWorld.java:
Again I removed the namespace declaration.
import javax.annotation.PostConstruct;
import javax.enterprise.inject.Model;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.NotEmpty;
public #Model
class HelloWorld {
private final String text = "Hello World!";
private String letters;
public HelloWorld() {
}
#PostConstruct
public void initialize() {
System.out
.println(this.getClass().getSimpleName() + " was constructed");
}
public String getText() {
return text;
}
#NotNull
#NotEmpty
#Pattern(regexp = "[A-Za-z]*", message = "must contain only letters")
public String getLetters() {
return letters;
}
public void setLetters(final String letters) {
this.letters = letters;
}
}
It seems that the JSF lifecycle interferes with what I want to do.
Taken from this german webiste:
It seems, that the event listener will only get invoked in the "Invoke Application"-phase.
Assuming that, it becomes quite obvious, that after "Process Validations" we skip to "Render Response" and our whole backing bean gets ignored.
It is possible to circumvent this, using immediate="true", but upon realizing there is a way better solution to the underlying problem I used that on, namely <p:wizard /> instead, that does exactly what I want.

How to add multiple results to an JSF form

Hi there i currently have a web page that uses ajax on submit to display the message the user entered on the same page below the input box, what i am wondering, if it is possible to keep a record of all messages inputted such as message 1, message 2 etc all displayed under them?
what is the best method for this ? also is there a way to do this with out the user having to press the submit button each time ?
this is my code so far :
<h:body>
<h3>JSF 2.0 + Ajax Hello World Example</h3>
<h:form>
<h:inputText id="name" value="#{helloBean.name}"></h:inputText>
<h:commandButton value="Welcome Me">
<f:ajax execute="name" render="output" />
</h:commandButton>
<h2><h:outputText id="output" value="#{helloBean.sayWelcome}" /></h2>
</h:form>
</h:body>
my bean
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import java.io.Serializable;
#ManagedBean
#SessionScoped
public class HelloBean implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSayWelcome(){
//check if null?
if("".equals(name) || name ==null){
return "";
}else{
return "Ajax message : Welcome " + name;
}
}
}
First you will need to change your bean. Make the attribute a List<String> to store all of the messages.
After that, to show the list you need to change output to a component that allows for showing all elements of the List; v.g. dataTable.
Also, you will need to invoke an action method in you ajax request, because your application will need to execute some logic (add name to the list).

Having multiple validation functions in a class with multiple actions

I want to validate forms in Struts 2 using validate functions in the action class.
I found this example : http://www.javatpoint.com/struts-2-custom-validation-workflow-interceptor
However, I want to have multiple functions (actions) in the same class. And I want to have a validation function for each of these functions. How can we do this?
Edit:
The validate() function in the example gets invoked automatically since it is one of the Validateable interface functions. If I have validate functions with other names they won't be invoked
Create validateXxx methods where Xxx is the name of the related action method.
(Whether or not this is the best option depends on the particular validations you need.)
validations using XML validation file
The naming convention of the XML validation file should be ActionClass-Validation.xml. Here our Action Class name is "Login.java" and the XML validation file name is "Login-Validation.xml".
The Login-Validation.xml file contains the following code.
view source
print?
<validators>
<field name="userName">
<field-validator type="requiredstring">
<message>User Name is required.</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message key="password.required" />
</field-validator>
</field>
</validators>
The field element contains the name of the form property that needs to be validated. The filed-validator element inside the field element contains the type of validation that needs to be performed.
Here you can either specify the error message directly using the message element or you can use the properties file to define all the error messages and use the key attribute to specify the error key.
Note the properties file should also have the same name as the Action class.
The Login Action class contains the following code.
view source
print?
public class Login extends ActionSupport {
private String userName;
private String password;
public Login() {
}
public String execute() {
return SUCCESS;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
The login.jsp page contains the following code.
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%#taglib uri="/struts-tags" prefix="s" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login Page</title>
<s:head />
</head>
<body>
<s:form action="LoginAction">
<s:textfield name="userName" label="User Name" />
<s:password name="password" label="Password" />
<s:submit value="Login" />
</s:form>
</body>
</html>

Resources