How validate two password fields by ajax? - jsf

I'm trying to validate two password fields with JSF but no good until now, I search for it on google but everything was about JSF 1.2 and pretty confusing, I'm using JSF 2.0.
This is what I'm doing so far:
<h:outputLabel for="password" value="Password:" />
<h:inputSecret id="password" value="#{register.user.password}" >
<f:ajax event="blur" listener="#{register.validatePassword}" render="m_password" />
</h:inputSecret>
<rich:message id="m_password" for="password"/>
<h:outputLabel for="password_2" value="Password (again):" />
<h:inputSecret id="password_2" value="#{register.user.password_2}" >
<f:ajax event="blur" listener="#{register.validatePassword}" />
</h:inputSecret>
This is how I it is my controller:
public void validatePassword() {
FacesMessage message;
if (!user.getPassword().equals(user.getPassword_2()) ){
message = new FacesMessage(FacesMessage.SEVERITY_ERROR, null, "different password");
}else{
message = new FacesMessage(FacesMessage.SEVERITY_INFO, null, "ok");
}
FacesContext.getCurrentInstance().addMessage("form:password", message);
}
Any idea guys ?

First of all, use a real Validator to validate the input. Don't do it in an action event method.
As to your concrete problem, you just need to specify the both fields in the execute attribute of the <f:ajax>, it namely defaults to the current component only. If you attach a validator to the first input and send the the value of the second input along as a <f:attribute>, then you will be able to grab it in the validator. You can use the binding attribute to bind the component to the view. This way you can pass its submitted value along by UIInput#getSubmittedValue().
Here's a kickoff example:
<h:outputLabel for="password" value="Password:" />
<h:inputSecret id="password" value="#{bean.password}" required="true">
<f:validator validatorId="confirmPasswordValidator" />
<f:attribute name="confirm" value="#{confirmPassword.submittedValue}" />
<f:ajax event="blur" execute="password confirm" render="m_password" />
</h:inputSecret>
<h:message id="m_password" for="password" />
<h:outputLabel for="confirm" value="Password (again):" />
<h:inputSecret id="confirm" binding="#{confirmPassword}" required="true">
<f:ajax event="blur" execute="password confirm" render="m_password m_confirm" />
</h:inputSecret>
<h:message id="m_confirm" for="confirm" />
(note that I added required="true" to both components and also note that you don't necessarily need to bind the confirm password component value to a managed bean property, it's worthless over there anyway)
with this validator
#FacesValidator("confirmPasswordValidator")
public class ConfirmPasswordValidator implements Validator {
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
String password = (String) value;
String confirm = (String) component.getAttributes().get("confirm");
if (password == null || confirm == null) {
return; // Just ignore and let required="true" do its job.
}
if (!password.equals(confirm)) {
throw new ValidatorException(new FacesMessage("Passwords are not equal."));
}
}
}

With seam 2 you have the component <s:validateEquality> and you don't need to write code. For JSF2 then you have Seam 3 modules, particulary Faces module and Cross-field Form Validation. An example :
First you have to use the s:validateForm tag:
<h:form id="passwordForm">
<h:inputSecret id="newPassword"
required="true"
redisplay="true"
value="#{passwordController.newPassword}">
</h:inputSecret>
<h:inputSecret id="confirmationPassword"
value="#{passwordController.confirmPassword}"
required="true"
redisplay="true">
</h:inputSecret>
<h:commandButton id="submit" value="Submit" action="#{passwordController.submitPassword}" />
<s:validateForm validatorId="passwordValidator" />
</h:form>
and the corresponding Validator for the password form above would look like this:
#FacesValidator("PasswordValidator")
public class PasswordValidator implements Validator
{
#Inject
#InputField
private String newPassword;
#Inject
#InputField
private String confirmPassword;
#Override
public void validate(final FacesContext context, final UIComponent comp, final Object values) throws ValidatorException
{
if (!confirmPassword.equals(newPassword))
{
throw new ValidatorException(new FacesMessage("Passwords do not match!"));
}
}
}

You can use Primefaces p:password tag. Please see demo example. It has match attribute which should be the id of confirm password.
<p:panel header="Match Mode">
<p:messages id="messages" showDetail="true" autoUpdate="true"/>
<h:panelGrid columns="2" id="matchGrid">
<h:outputLabel for="pass" value="Password " />
<p:password id="pass" value="#{passwordBean.password}" match="confirmPass" required="true"/>
<h:outputLabel for="confirmPass" value="Confirm Password " />
<p:password id="confirmPass" value="#{passwordBean.confirmPassword}" required="true"/>
</h:panelGrid>
<p:commandButton id="saveButton" update="matchGrid" value="Save" />
</p:panel>

Related

jsf managed bean returns 2 values how to display in JSF

I have an issue where I have a primefaces outputtext field and from the managed bean, I'm attempting to return an array type back to this field. Something is amiss in that I'm getting no return value back to my outputtext field. I will admit that I'm a bit rusty on my Java coding skills and it could be that I'm not performing something correctly within my bean method with respect to my return value.
My JSF page outputtext field
<p:panel id="horizontal" header="Conversion from Lat Long to MGRS" toggleable="true" toggleOrientation="horizontal">
<h:panelGrid columns="2" cellpadding="10" styleClass="left">
<h:outputLabel for="lat" value="Enter Latitude:" />
<p:inplace id="lat">
<p:inputText value="Latitude" />
</p:inplace>
<h:outputLabel for="long" value="Enter Longitude:" />
<p:inplace id="long">
<p:inputText value="Longitude" />
</p:inplace>
<h:outputLabel for="mgrs" value="MGRS conversion value:" />
 <h:outputText id="mgrs" value="#{coordinates.MGRSCoordreturn}" />
<p:commandButton value="Submit" update="mgrs" icon="ui-icon-check" actionListener="#{coordinates.mgrsFromLatLon(lat, long)}"/>
</h:panelGrid>
</p:panel>
<h:outputLabel for="mgrs_input" value="Enter MGRS:" />
<p:inplace id="mgrs_input">
<p:inputText value="MGRS" />
</p:inplace>
<h:outputLabel for="mgrs_output" value="Lat Long conversion values:" />
<h:outputText id="mgrs_output" value="#{coordinates.latLongVReturn}" />
<p:commandButton value="Submit" update="mgrs_output" icon="ui-icon-check" actionListener="#{coordinates.latLonFromMgrs(mgrs_input)}"/>
My managed bean code:
#ManagedBean
#SessionScoped
public class Coordinates implements Serializable{
private String MGRSCoordreturn;
private Double LatLongVReturn;
public String mgrsFromLatLon(double lat, double lon){
// 37.10, -112.12
Angle latitude = Angle.fromDegrees(lat);
Angle longitude = Angle.fromDegrees(lon);
MGRSCoordreturn = MGRSCoord.fromLatLon(latitude, longitude).toString();
return MGRSCoord.fromLatLon(latitude, longitude).toString();
}
public String getMGRSCoordreturn() {
return MGRSCoordreturn;
}
public void setMGRSCoordreturn(String MGRSCoordreturn) {
this.MGRSCoordreturn = MGRSCoordreturn;
}
public double[] latLonFromMgrs(String mgrs){
MGRSCoord coord = MGRSCoord.fromString("31NAA 66021 00000");
double LatLongVReturn[] = new double[]{
coord.getLatitude().degrees,
coord.getLongitude().degrees
};
return new double[]{
coord.getLatitude().degrees,
coord.getLongitude().degrees
};
}
public Double getLatLongVReturn() {
return LatLongVReturn;
}
public void setLatLongVReturn(Double LatLongVReturn) {
this.LatLongVReturn= LatLongVReturn;
}
}

Show faces message below input fields

I am working with JSF (PrimeFaces)/EJB/JPA and a MySQL database. What I want to do is to show AT THE TOP OF THE XHTML BODY "User was successfully added to database" info message when an user is introduced successfully in the DB. I know I can use h:messages but then, also the validation error messages `are shown at the top of the body, and I want the error messages to be shown below the input fields. How could I do this?
Facelet code
<h:body>
<h:messages errorStyle="color: red" infoStyle="color: green" layout="table"/>`<!--WRONG-->
<p:inputText id="name" required="true" value="#{usersManagedBean.username}" requiredMessage="requiered field">
<f:validator validatorId="validators.NameValidator"/>
</p:inputText>
<p:watermark for="name" value="User" />
<p:message for="name" />
<p:inputText id="age" required="true" value="#{usersManagedBean.username}" requiredMessage="requiered field">
<f:validator validatorId="validators.AgeValidator"/>
</p:inputText>
<p:watermark for="age" value="Age" />
<p:message for="age" />
<p:commandButton value="Save user" action="#{usersManagedBean.saveUser}" ajax="false" />
</h:body>
Managed Bean code
//imports
#Named(value = "usersManagedBean")
#SessionScoped
public class UsersManagedBean implements Serializable
{
String username;
int userage;
#PostConstruct
public void init()
{
username="";
userage=0;
}
//Getters and Setters
public void saveUser()
{
User eUser = new Users();
eUser.setName(username);
eUser.setAge(userage);
ejbUsersDAO.create(eUser); //DAO
addSuccessMessage("User was successfully added to database");
}
public static void addSuccessMessage(String msg)
{
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg);
FacesContext fc = FacesContext.getCurrentInstance();
fc.addMessage("successInfo", facesMsg);
}
}
Try setting globalOnly="true" attribute in your <h:messages> and change your addSuccessMessage to
fc.addMessage(null, facesMsg);

Illegal Syntax for Set Operation

I have a problem in connecting My xhtml page to the managed bean, the action on the commandButton works but when it comes to passing values it doesn't work.
here is my jsf code:
<h:form id="form" class="form-signin">
<p:panel id="panel" header=" Authentification" style="" >
<h:panelGrid columns="2" rowClasses="3">
<h:outputLabel for="login" value="Nom d'utilisateur :" styleClass=""/>
<p:inputText id="login" value=" #{authenticationBean.profil.login }" required="true" label="login" >
<f:validateLength minimum="4" />
</p:inputText>
<h:outputLabel for="password" value="Mot de passe :" />
<p:password id="password" value=" #{authenticationBean.profil.password }" required="true" label="password" styleClass=""/>
<p:row>
<p:commandButton id="loginButton" value="Login" ajax="false" action="#{authenticationBean.validate}" />
<h:messages id="messages" globalOnly="false"/>
</p:row>
</h:panelGrid>
</p:panel>
</h:form>
i'm using morphia to map data to mongo db, i have also an entitie called profil and one bean to manage authenfication. here is my athentication bean Code :
public class AuthenticationBean implements Serializable {
private static final long serialVersionUID = 1L;
private Profil profil;
private ProfilDAO profileDao = DAOFactory.getProfilDAO();
public void validate() {
FacesMessage message = new FacesMessage("Succès de l'inscription !");
FacesContext.getCurrentInstance().addMessage(null, message);
}
// getters and setters
here is my profil entitie code :
#Entity("profils")
public class Profil {
#Id protected ObjectId _id;
protected String nomProfil,prenomProfil,login,password;
#Embedded protected List<Droit> droits;
#Reference protected Admin admin;
public Profil() {
}
//getters and setters ...
this is the eror i get when i submit some data and click the submit button :
javax.el.PropertyNotWritableException: /index.xhtml #29,125 value=" #{authenticationBean.profil.login }": Illegal Syntax for Set Operation
Look closer at the value and compare with what all sane JSF tutorials/examples try to show you:
value=" #{authenticationBean.profil.login }"
Whitespace is significant in attributes and EL expressions. Get rid of it:
value="#{authenticationBean.profil.login}"

How to retrieve values of textboxes in JSF managed bean which are generated through a loop?

I need to generate textboxes through a loop as follows.
<p:panel id="dataPanel" closable="true" toggleOrientation="horizontal" toggleable="true" header="Data">
<h:panelGrid id="dataPanelGrid" columns="3" cellpadding="5">
<c:forEach var="row" items="#{zoneChargeManagedBean.list}">
<p:outputLabel for="txtCharge" value="#{row[1]}"/>
<p:inputText id="txtCharge" value="#{row[2]}" converter="#{bigDecimalConverter}" onkeydown="return isNumberKey(event, this.value);" label="#{row[1]}" required="false" maxlength="45">
<f:validator validatorId="negativeNumberValidator"/>
<f:attribute name="isZeroAllowed" value="false"/>
<f:validator validatorId="bigDecimalRangeValidator"/>
<f:attribute name="minPrecision" value="1"/>
<f:attribute name="maxPrecision" value="33"/>
<f:attribute name="scale" value="2"/>
</p:inputText>
<p:message for="txtCharge" showSummary="false"/>
</c:forEach>
<p:commandButton id="btnSubmit" update="dataPanel messages" actionListener="#{zoneChargeManagedBean.insert}" icon="ui-icon-check" value="Save"/>
<p:commandButton value="Reset" update="dataPanel" process="#this">
<p:resetInput target="dataPanel" />
</p:commandButton>
</h:panelGrid>
</p:panel>
The value of the given textbox is a type of BigDecimal from the database.
When the given command button is pressed, the values held by these textboxes should be retrieved from the corresponding JSF managed bean so that they can either be inserted or updated in the database.
It would be even better, if it is possible to retrieve the values of all of these text fields at once in some kind of collection (like java.util.List), when the given button is pressed.
<ui:repeate>, a render time tag works correctly but not <c:foreEach>, a view build time component (I can't clarify why) but in this particular case, I found <p:dataGrid> is more suitable. The XHTML has been modified accordingly as follows.
<p:panel id="dataPanel" rendered="#{zoneChargeManagedBean.renderedDataPanel}" closable="true" toggleOrientation="horizontal" toggleable="true" header="Data">
<p:dataGrid columns="3" value="#{zoneChargeManagedBean.list}" var="row" paginator="true" paginatorAlwaysVisible="false" pageLinks="10" rows="15">
<p:watermark for="txtCharge" value="Enter charge."/>
<p:tooltip for="lblCharge" value="Some message."/>
<p:column>
<p:outputLabel id="lblCharge" for="txtCharge" value="#{row[1]}"/><br/>
<p:inputText id="txtCharge" value="#{row[2]}" onkeydown="return isNumberKey(event, this.value);" converter="#{bigDecimalConverter}" label="#{row[1]}" required="false" maxlength="45">
<f:validator validatorId="negativeNumberValidator"/>
<f:attribute name="isZeroAllowed" value="false"/>
<f:validator validatorId="bigDecimalRangeValidator"/>
<f:attribute name="minPrecision" value="1"/>
<f:attribute name="maxPrecision" value="33"/>
<f:attribute name="scale" value="2"/>
</p:inputText>
<h:message for="txtCharge" showSummary="false" style="color: #F00;"/>
</p:column>
</p:dataGrid>
<p:commandButton id="btnSubmit" update="dataPanel messages" actionListener="#{zoneChargeManagedBean.insert}" icon="ui-icon-check" value="Save"/>
<p:commandButton value="Reset" update="dataPanel" process="#this">
<p:resetInput target="dataPanel" />
</p:commandButton>
</p:panel>
The managed bean:
#Controller
#Scope("view")
public final class ZoneChargeManagedBean implements Serializable
{
#Autowired
private final transient ZoneChargeService zoneChargeService=null;
private ZoneTable selectedZone; //Getter and setter
private List<Object[]>list; //Getter and setter
private boolean renderedDataPanel; //Getter and setter
public ZoneChargeManagedBean() {}
public void ajaxListener() {
if(this.selectedZone!=null){
list=zoneChargeService.getZoneChargeList(this.selectedZone.getZoneId());
renderedDataPanel=true;
}
else {
renderedDataPanel=false;
}
}
public void insert() {
//Just do whatever is needed based on the list with new values which is retrieved when <p:commandButton> as shown in the given XHTML is clicked.
if(selectedZone!=null&&zoneChargeService.addOrUpdate(list, selectedZone)) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Message Summary", "Message"));
}
else {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, "Message Summary", "Message"));
}
}
}
The service method as in the ajaxListener() method returns a list of type of an array of objects - List<Object[]>.
public List<Object[]>getZoneChargeList(Long id) {
return entityManager.createQuery("select w.weightId, w.weight, zc.charge from Weight w left join w.zoneChargeSet zc with zc.zoneTable.zoneId=:id order by w.weight").setParameter("id", id).getResultList();
}
I can't use the corresponding JPA criteria query which is intended because the with operator which doesn't seem to be supported by the JPA criteria API.
This method is invoked when an item from <p:selectOneMenu> is selected which is not covered in this question.

JSF FacesContext#addMessage is not displayed

In my previous question I had the problem of displaying validation messages from a Login form. That issue is now solved, but this time I am not able to display a custom message with FacesContex#addMessage.
Using JSF + PrimeFaces.
<p:dialog header="Login" widgetVar="loginDlg">
<h:form id="loginForm">
<h:panelGrid columns="3" cellpadding="5">
<h:outputLabel for="username" value="Username:" />
<p:inputText value="#{loginBean.username}" id="username" required="true" label="username" />
<p:message for="username" />
<h:outputLabel for="password" value="Password:" />
<h:inputSecret value="#{loginBean.password}" id="password" required="true" label="password" />
<p:message for="password" />
<f:facet name="footer">
<p:commandButton value="Login" id="loginDlgButton" update=":loginForm,:welcomeMsg" actionListener="#{loginBean.login}"
oncomplete="handleLoginRequest(xhr, status, args)"/>
<p:message for="loginDlgButton" />
</f:facet>
</h:panelGrid>
</h:form>
</p:dialog>
In LoginBean (a SessionScoped ManagedBean):
public void login() {
FacesContext context = FacesContext.getCurrentInstance();
RequestContext rContext = RequestContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
try {
request.login(this.username, this.password);
rContext.addCallbackParam("loggedIn", true);
} catch (ServletException e) {
rContext.addCallbackParam("loggedIn", false);
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Login Error", "Invalid credentials"));
}
}
This code, when validation succeeds and login fails, should display the "Invalid credential" message, but doesn't. Moreover, somewhere in the body of my web page, I have also added this line:
<p:messages autoUpdate="true" />
but my message isn't displayed even there.
Javadocs say that
If clientId is null, this FacesMessage is assumed to not be associated with any specific component instance
But I can't understand what this means.
place <p:messages autoUpdate="true" /> inside your form or inside some wrapper that is being updated by update of your commandButton , or place loginDlgButton instead of null in context.addMessage(...
I don't see a p:messages tag in your code. It is not the same as the p:message tag. p:message is attached to another component and is displayed as part of validation. The p:messages (or p:growl) component is what you are updating in your bean. Try adding a messages or growl component like this:
<h:form id="loginForm">
<p:growl id="messageGrowl" showDetail="true" sticky="false" />
<h:panelGrid columns="3" cellpadding="5">

Resources