Primefaces Wizard and selectOneRadio - jsf

I have a problem with using primeface's wizard component and the core selectOneRadio. My signup page looks like this
<ui:define name="content">
<f:view>
<h:form id="signUpForm">
<p:wizard widgetVar="wiz" flowListener="#{SignUpBean.onFlowProcess}">
<p:tab id="personalTab" title="">
<p:panel header="Personal">
<h:messages/>
<h:panelGrid id="panel1" columns="2">
<h:outputLabel for="firstName" value="First Name"/>
<h:inputText id="firstName" value="#{SignUpBean.firstName}" required="true"/>
<h:outputLabel for="lastName" value="Last Name"/>
<h:inputText id="lastName" value="#{SignUpBean.lastName}" required="true"/>
<h:outputLabel for="email" value="Email"/>
<h:inputText id="email" value="#{SignUpBean.email}" required="true">
<f:validator validatorId="emailValidator"/>
</h:inputText>
</h:panelGrid>
</p:panel>
</p:tab>
<p:tab id="passwordTab" title="">
<p:panel header="Password">
<h:messages/>
<h:panelGrid id="panel2" columns="2">
<h:outputLabel for="password" value="Password"/>
<h:inputSecret id="password" value="#{SignUpBean.password}" required="true"/>
<h:outputLabel for="retypePass" value="Retype Password"/>
<h:inputSecret id="retypePass" value="#{SignUpBean.retypePassword}" required="true"/>
</h:panelGrid>
</p:panel>
</p:tab>
<p:tab id="groupTab" title="">
<p:panel header="Group">
<h:messages/>
<h:panelGrid id="panel3" columns="2">
<h:outputLabel for="radioGroup" value=""/>
<h:selectOneRadio id="radioGroup" value="#{SignUpBean.join}">
<f:selectItem itemValue="true" itemLabel="Join existing group"/>
<f:selectItem itemValue="false" itemLabel="Create new group"/>
</h:selectOneRadio>
Group Name
<h:inputText id="group" value="#{SignUpBean.group}" required="true"/>
Group Password
<h:inputSecret id="groupPass" value="#{SignUpBean.groupPass}" required="true"/>
</h:panelGrid>
</p:panel>
</p:tab>
<p:tab id="confirmTab" title="">
<p:panel header="Confirm">
<h:messages/>
<p:growl id="signUpGrowl" sticky="false" life="1000" showDetail="true" />
<h:panelGrid id="panel4" columns="4" cellpadding="5">
Firstname:
<h:outputText value="#{SignUpBean.firstName}"/>
Lastname:
<h:outputText value="#{SignUpBean.lastName}"/>
Email:
<h:outputText value="#{SignUpBean.email}"/>
Groupname:
<h:outputText value="#{SignUpBean.group}"/>
<h:panelGroup style="display:block; text-align:center">
<p:commandButton value="Submit" action="#{SignUpBean.signUp}" update="signUpGrowl"/>
</h:panelGroup>
</h:panelGrid>
</p:panel>
</p:tab>
</p:wizard>
</h:form>
</f:view>
</ui:define>
And the signUpBean like this:
#ManagedBean(name="SignUpBean")
#SessionScoped
public class SignUpBean {
private String groupName, groupPass, firstName, lastName,
email, password, retypePassword;
private boolean join;
private boolean skip;
#EJB
private MessageBeanRemote messageBean2;
/** Creates a new instance of SignUpBean */
public SignUpBean() {
this.skip = false;
this.join = true;
}
/**
* Signs up a user with all the data given on the signUp.jsf page.
* If everything is ok then a confirmation email is generated and send
* to the new user.
* #return Either signUpSucces or signUpFailure
*/
public void signUp() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session.beginTransaction();
// Boolean to decide if the data should be commited or not.
boolean commitOK = true;
UserHelper uh = new UserHelper();
BasicUser user = uh.getByEmail(this.email);
GroupHelper gh = new GroupHelper();
Group group = gh.getByName(this.groupName);
// If email does not already exist
if(user == null) {
user = new BasicUser();
user.setEmail(this.email);
user.setFirstName(this.firstName);
user.setLastName(this.lastName);
if(this.password.equals(this.retypePassword)) {
user.setPassword(password);
}
else {
commitOK = false;
FacesMessage fm = new FacesMessage("Passwords does not match");
FacesContext.getCurrentInstance().addMessage(null, fm);
}
}
else {
commitOK = false;
FacesMessage fm = new FacesMessage("Email does already exist");
FacesContext.getCurrentInstance().addMessage(null, fm);
}
// If it's a joiner to a group
if(this.join) {
// Is it the right groupPassword and groupName
if(group != null && group.getGroupPassword().equals(this.groupPass)) {
user.setGroup(group);
}
else {
commitOK = false;
FacesMessage fm = new FacesMessage("Wrong group name or password");
FacesContext.getCurrentInstance().addMessage(null, fm);
}
}
else {
if(group == null) {
group = new Group();
group.setGroupName(this.groupName);
group.setGroupPassword(this.groupPass);
user.setGroup(group);
}
else {
commitOK = false;
FacesMessage fm = new FacesMessage("Group does already exist");
FacesContext.getCurrentInstance().addMessage(null, fm);
}
}
//--- IF EVERYTHING OK THEN UPDATE THE DB ---//
if(commitOK) {
session.save(group);
session.save(user);
tx.commit();
session = HibernateUtil.getSessionFactory().getCurrentSession();
tx = session.beginTransaction();
BasicUser newUser = uh.getByEmail(email);
int id = newUser.getId();
MobileUser mobile = new MobileUser();
mobile.setId(id);
mobile.setUseWhen("Lost");
StatUser stats = new StatUser();
stats.setId(id);
stats.setRating("");
DateUser dates = new DateUser();
dates.setId(id);
Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();
dates.setMemberSince(date);
dates.setLastLogin(date);
session.save(stats);
session.save(mobile);
session.save(dates);
tx.commit();
//----- SEND CONFIRMATION EMAIL ----------//
BasicUser emailUser = uh.getByEmail(email);
MailGenerator mailGenerator = new ConfirmationMailGenerator(emailUser);
try {
StringWriter plain = mailGenerator.generatePlain();
StringWriter html = mailGenerator.generateHTML();
messageBean2.sendMixedMail(email, "WMC: Account Info", plain.toString(),
html.toString());
}
catch (Exception ex) {
Logger.getLogger(SignUpBean.class.getName()).log(Level.SEVERE, null, ex);
}
FacesMessage msg = new FacesMessage("Successful", "Welcome :" + this.getFirstName());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
//---- DO NOTHING ----//
}
public String onFlowProcess(FlowEvent event) {
if (skip) {
skip = false; //reset in case user goes back
return "confirm";
} else {
return event.getNewStep();
}
}
... getters and setters
}
I know it is a bad signup method and it will be changed later. When i reach the last tab and submit I get this error:
When I debug I see that the join variable is either true or false not null. What is it complaining about?

Change the variable declaration to:
private Boolean join;
instead of
private boolean join;
Make sure that you have appropriate getter and setter!

I solved the problem by adding a
<h:inputHidden value="#{SignUpBean.join}"/>
Inside the confirmation tab. This works:)

Related

How to use href inside rich:column?

I'm new to xhtml and I am trying to use href inside a table's cell via a certain name(auction's name in my case). When I press the auction's name, I want to be send inside another page for adding a bid, seeing hightest bid and so on. It just shows me the last panel Group from the referenced page(where it says: No bids for this auction).
Can someone help me please ?
the code from rich:column is auctionList.xhtml:
<composite:implementation>
<rich:dataTable id="auctionsTable" rows="6" value="#{cc.attrs.auctions}" var="auct" border="1" styleClass="flat list auctions" rendered="#{cc.attrs.rendered and not empty cc.attrs.auctions}">
<f:facet name="header">
<rich:dataScroller forComponent="auctionsTable" />
</f:facet>
<h:link outcome="/destination" value="link" />
<rich:column sortBy="#{auct.name}" sortOrder="ascending" >
<a href="detail.xhtml">
#{auct.name}
</a>
</rich:column>
and detail.xhml is:
<ui:composition>
<h2>Details</h2>
<h:panelGroup layout="div"
rendered="#{auctionManager.currentAuction != null}">
<a4j:poll interval="3000" render="highestBidOutput, bidHistory" action="#{auctionManager.refreshAuction(currentAuction)}" />
<h3>#{currentAuction.name}</h3>
<h:panelGrid>
<h:column>
<h:outputLabel value="ID:" />
<h:outputText value="#{currentAuction.id}" />
</h:column>
<h:column>
<h:outputLabel value="Owner:" />
<h:outputText value="#{currentAuction.owner.name}" />
</h:column>
<h:column>
<h:outputLabel value="Original price:" />
<h:outputText value="#{currentAuction.originalPrice}" />
</h:column>
<h:column>
<h:outputLabel value="Description:" />
<h:outputText value="#{currentAuction.description}" />
</h:column>
<h:column>
<h:outputLabel value="Location:" />
<h:outputText value="#{currentAuction.location}" />
</h:column>
</h:panelGrid>
<h:panelGrid columns="2">
<h:outputLabel value="Highest bid:"
rendered="#{not empty currentAuction.highestBid}" />
<h:outputText id="highestBidOutput"
value="#{currentAuction.highestBid.amount} (#{currentAuction.highestBid.bidder.name})"
rendered="#{not empty currentAuction.highestBid}" />
<h:outputLabel value="Bid" rendered="#{loginManager.logged}" />
<h:form rendered="#{loginManager.logged}">
<h:inputText id="bidAmountInput" value="#{bidAmount}"
validator="#{bidValidator.validateBid}" />
<h:commandButton value="Add"
action="#{auctionManager.addBid(bidAmount)}" />
<h:messages style="color: red" />
</h:form>
</h:panelGrid>
<h:panelGroup id="bidHistory" rendered="#{not empty currentAuction.bids}">
<h3>Bids</h3>
<h:dataTable var="offer" value="#{currentAuction.bids}" border="1"
styleClass="flat">
<h:column>#{offer.bidder.name}</h:column>
<h:column>#{offer.amount}</h:column>
</h:dataTable>
</h:panelGroup>
</h:panelGroup>
<h:panelGroup layout="div"
rendered="#{auctionManager.currentAuction == null}">
<p>No bids for given auction.</p>
</h:panelGroup>
and AuctionManagerImpl.java used in detail.xhtml:
private static final long serialVersionUID = 1L;
private Auction currentAuction = null;
#PersistenceContext(type=PersistenceContextType.EXTENDED)
private EntityManager em;
#Inject
private LoginManager loginManagerBean;
#Resource SessionContext sessionContext;
#Produces
#Named
#Dependent
#CurrentAuction
#PermitAll
public Auction getCurrentAuction() {
if (currentAuction != null && !em.contains(currentAuction)) {
currentAuction = em.merge(currentAuction);
}
return currentAuction;
}
#PermitAll
public Long getCurrentAuctionId() {
return (currentAuction == null) ? null : currentAuction.getId();
}
#PermitAll
public void setCurrentAuctionId(Long currentId) {
this.currentAuction = em.find(Auction.class, currentId);
}
#PermitAll
public List<Auction> getAll() {
return em.createQuery("SELECT a FROM Auction a", Auction.class)
.getResultList();
}
#PermitAll
public List<Auction> getAuctionsWinningByUser(User user) {
String jql = "SELECT auction FROM Auction auction, User user "
+ "WHERE user=:user AND auction.highestBid member of user.bids "
+ "ORDER BY auction.id";
TypedQuery<Auction> query = em.createQuery(jql, Auction.class);
query.setParameter("user", user);
List<Auction> auctions = query.getResultList();
return auctions;
}
#PermitAll
public List<Auction> getAuctionLoosingByUser(User user) {
String jql = "SELECT DISTINCT auction FROM User user "
+ "JOIN user.bids bid JOIN bid.auction auction "
+ "WHERE user=:user AND auction.highestBid.bidder != user "
+ "ORDER BY auction.id";
TypedQuery<Auction> query = em.createQuery(jql, Auction.class);
query.setParameter("user", user);
List<Auction> auctions = query.getResultList();
return auctions;
}
#PermitAll
public void refreshAuction(Auction auction) {
em.refresh(auction);
}
//#PermitAll
public void addBid(long bidAmount) {
if (sessionContext.getCallerPrincipal() == null) {
throw new IllegalStateException(
"user must be logged in order to add bid");
}
if (currentAuction == null) {
throw new IllegalStateException(
"currentAuction have to be selected in order to add bid");
}
Bid bid = new Bid(loginManagerBean.getCurrentUser(), currentAuction, bidAmount);
em.persist(bid);
em.flush();
em.refresh(bid);
}
}
also very important is list.xhtml where I make use of auctionList.xhtml:
<ui:composition template="templates/home.xhtml">
<ui:param name="activeTab" value="list" />
<ui:define name="content">
<h2>Auction List</h2>
<a:auctionList auctions="#{auctionManager.all}" />
</ui:define>
Basicaly you need put a value in the request and redirect to destination page, using JSF, a method that have a String, implicitly return a navigation, you can make this in this way:
public String sendToPageAndPutValue(){
FacesContext.getCurrentInstance().getExternalContext().getFlash().put(paramName, paramValue);
return "pageDestination.xhtml";
}
To recover this value in destination Bean you can make this:
FacesContext.getCurrentInstance().getExternalContext().getFlash().get("paramName")
check in your bean.:
#Named -> javax.inject.Named
#ViewScoped -> org.omnifaces.cdi.ViewScoped
public class YourBean
In the your xhtml, you need call this method in a h:commandButton or a4j:commandButton using the property action
<h:commanButton id="idButton" value="Send" execute="#this" action="#{yourBean.sendToPageAndPutValue()}"/>

Updating a field after a failed Validation

I am building a web application using the technologies mentioned in the post header. I have searched similar threads, but none of them provided an answer to my problem. I have configured my Maven project, the pom file is correct, JSF and PrimeFaces are working, but I encounter a problem when I do the following:
I copied the Client Side Validation example from the Prime Faces Showcase website, and on my end, it isn't working as expected.
When validation fails for a field, an error appears to the right of the field, and as long as it's there, I cannot update the field. When I try to type something, nothing happens on the screen, but if I highlight the text in the field, I can see it there.
Here's my registration.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
Hello from Facelets
<h2>Registration Form</h2>
<h:form id="form">
<p:panel id="panel" header="Form" style="margin-bottom:10px;">
<p:fieldset legend="Registration Form" widgetVar="regWidget" style="width: 600px;">
<h:panelGrid columns="3" width="550" border="0">
<h:outputLabel value="UserName" />
<p:inputText value="#{regCont.prospect.userName}"
id="userName"
required="true"
requiredMessage="UserName is required"
validatorMessage="UserName should be of length from 5 to 15 chars"
>
<f:validateLength minimum="5" maximum="15" for="userName"></f:validateLength>
</p:inputText>
<p:message for="userName"/>
<h:outputLabel value="Password" />
<p:password value="#{regCont.password}"
id="password"
required="true"
requiredMessage="Password is required"
validatorMessage="Password should be of length from 5 to 15 chars"
>
<f:validateRegex pattern="^(?=^.{8,12}$)(?!.*(.)\1{3,})(?=.*[A-Z])(?=.*[a-z]{3,})(?=.*[^a-zA-Z0-9]{2,})(?=.*[0-9]{2,})[a-zA-Z]"/>
</p:password>
<p:message for="password" />
<h:outputLabel value="FirstName" />
<p:inputText value="#{regCont.prospect.firstName}"
id="firstName"
required="true"
requiredMessage="FirstName is required"
validatorMessage="FirstName should be of length from 5 to 15 chars"
>
<f:validateLength minimum="1" maximum="45" for="firstName"></f:validateLength>
</p:inputText>
<p:message for="firstName" display="tooltip" />
<h:outputLabel value="LastName" />
<p:inputText value="#{regCont.prospect.lastName}"
id="lastName"></p:inputText>
<p:message for="lastName" display="tooltip"/>
<h:outputLabel value="Email" />
<p:inputText value="#{regCont.prospect.email}"
id="email"
validatorMessage="Invalid Email">
<f:validateRegex pattern="[a-zA-Z0-9]+#[a-zA-Z]+.[a-zA-Z]{2,3}"></f:validateRegex>
</p:inputText>
<p:message for="email" />
<h:outputLabel value="Nation" />
<p:inputText value="#{regCont.prospect.nation}"
id="nation">
</p:inputText>
<p:message for="nation" />
<h3 style="margin-top:0">User type</h3>
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
<p:outputLabel for="type" value="User type:" />
<p:selectOneRadio id="type" value="#{regCont.prospect.userType}">
<f:selectItem itemLabel="Delegate" itemValue="Delegate" />
<f:selectItem itemLabel="Leader" itemValue="Leader" />
</p:selectOneRadio>
</h:panelGrid>
<p:commandButton value="Register" update="panel" icon="ui-icon-check" validateClient="true" style="margin-right:10px"/>
<h:commandButton value="Reset p:ajax" style="margin-right:20px;" >
<p:ajax update="panel" resetValues="true" />
</h:commandButton>
</h:panelGrid>
</p:fieldset>
</p:panel>
</h:form>
</h:body>
</html>
And here's my RegistrationController class:
#ManagedBean(name = "regCont")
#RequestScoped
public class RegistrationController implements Controller {
#ManagedProperty(value = "#{prospect}")
private Prospect prospect;
#ManagedProperty(value = "#{user}")
private User user;
private String msg;
private String password;
public void hashPassword() throws NoSuchAlgorithmException {
byte[] salt = Passwords.getNextSalt();
prospect.setSalt(salt);
prospect.setPasswordHash(Passwords.getHashWithSalt(password, salt));
password = "";
}
public Prospect getProspect() {
return prospect;
}
public void setProspect(Prospect prospect) {
this.prospect = prospect;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
private void clearAll() {
user.setFirstName("");
user.setLastName("");
user.setNation("");
user.setEmail("");
user.setUserName("");
user.setPasswordHash(null);
prospect.setFirstName("");
prospect.setLastName("");
prospect.setNation("");
prospect.setEmail("");
prospect.setUserType("");
prospect.setUserName("");
prospect.setPasswordHash(null);
}
public void saveUser() {
UserDAO dao = new UserDAO();
dao.createEntity(user);
this.msg = "Member Info Saved Successfull!";
clearAll();
}
public void saveProspect() {
ProspectDAO dao = new ProspectDAO();
try {
hashPassword();
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(User.class.getName()).log(Level.SEVERE, null, ex);
}
dao.createEntity(prospect);
this.msg = "Member Info Saved Successfull!";
}
public void reset() {
RequestContext.getCurrentInstance().reset("form");
}
public void updateUser(int id) {
UserDAO dao = new UserDAO();
try {
hashPassword();
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(User.class.getName()).log(Level.SEVERE, null, ex);
}
dao.updateEntity(id);
this.msg = "Member Info Update Successfull!";
clearAll();
}
public void deleteUser(int id) {
UserDAO dao = new UserDAO();
dao.deleteEntity(id);
this.msg = "Member Info Delete Successfull!";
clearAll();
}
}
Only case this works is, when I implemented the Reset button, and on a failed validation, I click reset, then I can input values into fields.
Also, when I hover above a field (p:inputText), the cursor doesn't change to the text cursor like on other fields (eg. h:inputText). Really don't have an idea how does the same piece of code work on the PrimeFaces ShowCase web site, and not on my end?
Does anybody have an idea how can I fix this?
I'm using JSF 2.2 + PrimeFaces 5.3

Open p:dialog in action listener method

I'm trying get a return of my ManagedBean. I have a dialog to login users and I have a method at managedbean that check if user exist. If user exist return true if not return false.
I want if user exist dialog is hide if not dialog is show.
How I can do that ?
XHTML
<h:form id="UsuarioLoginForm">
<p:growl id="growl" life="3000"/>
<p:panelGrid columns="2" id="display">
<p:outputLabel value="Login"/>
<p:inputText
required="true"
value="#{usuarioMB.bean.login}"
maxlength="50"
onkeyup="strToUpper(this)"
/>
<p:outputLabel value="Senha"/>
<p:password
required="true"
value="#{usuarioMB.bean.senha}"
maxlength="12"
onkeyup="strToLower(this)"
/>
<p:commandButton value="Login"
actionListener="#{usuarioMB.isLoginExiste(usuarioMB.bean)}"
>
<f:ajax execute="#form" render="#form"/>
</p:commandButton>
</p:panelGrid>
</h:form>
</p:dialog>
Managed Bean
/** check if login exist */
public Boolean isLoginExiste(Usuario u){
if(new CustomUsuarioDAO().isLoginExiste(u.getLogin(), u.getSenha())){
return true;
}else{
return false;
}
}
}
Solved
/** check if login exist */
public void isLoginExiste(){
RequestContext rctx = RequestContext.getCurrentInstance();
boolean existe = new CustomUsuarioDAO().isLoginExiste(getLogin(), getSenha());
if(existe){
rctx.execute("UsuarioLoginDialog.hide()");
}else{
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro","Usuário ou senha inválido"));
rctx.update("UsuarioLoginForm:growl");
rctx.execute("UsuarioLoginDialog.show()");
}
}

Value in <p:inputText> won't pass to bean

I have a problem with my code where the values from various `'s won't pass over to the bean. The code is basically the same as my old projects (where everything worked perfectly fine), but no matter what I do the values in the bean won't be updated. What I want to do is for the user to fill in a form in order to register an account. I tried doing it in two ways:
<p:inputText id="address" value="#{Register.user.address}.../>
Here Register is the bean with the property user of the User class, where there are several properties including String address. This didn't really work, so I tried putting the getters and setters in the RegisterBean, and setting them to this format
public String getAddress(){
return user.getAdress();
}
and using them like this in the xhtml
<p:inputText id="address" value="#{Register.address]".../>
but it still doesn't work. Tried debugging, and it appears that the setters are never entered at all. Does anybody know why this doesn't work and potentially how to fix it?
Here is the rest of the code:
The .xhtml
<h:head>
<title>Register</title>
</h:head>
<body>
<ui:composition template="userTemplate.xhtml">
<ui:define name="content">
<h:form>
<h:panelGrid id="grid" columns="3" >
<f:facet name="header">
Please fill in the required information
</f:facet>
<p:outputLabel value="Username" />
<p:inputText id="username" value="#{Register.user.username}" validator="#{Register.validateUsername}" required="true" requiredMessage="Cannot be blank!"/>
<p:message for="username"/>
<p:outputLabel value="Password"/>
<p:password id="password" value="#{Register.user.password}" validator="#{Register.validatePasswords}"/>
<p:message for="password" showSummary="true" showDetail="false"/>
<p:outputLabel value="Repeat password" />
<p:password id="repPassword" value="#{Register.user.repeatPass}" validator="#{Register.validateRepPassword}"/>
<p:message for="repPassword" showSummary="true" showDetail="false"/>
<p:outputLabel value="First name" />
<p:inputText id="firstName" value="#{Register.user.firstName}"/>
<p:message for="firstName" showSummary="true" showDetail="false"/>
<p:outputLabel value="Surname" />
<p:inputText id="surname" value="#{Register.user.surname}" required="true" requiredMessage="Cannot be blank!"/>
<p:message for="surname" showSummary="true" showDetail="false"/>
<p:outputLabel value="Address" />
<p:inputText id="address" value="#{Register.user.address}" required="true" requiredMessage="Cannot be blank!"/>
<p:message for="address" showSummary="true" showDetail="false"/>
<p:outputLabel value="Postnumber"/>
<p:inputText id="postnumber" value="#{Register.user.postnumber}" validatorMessage="Can only be numbers!" required="true" requiredMessage="Cannot be blank!"/>
<p:message for="postnumber" showSummary="true" showDetail="false"/>
<p:outputLabel value="City"/>
<p:inputText id="city" value="#{Register.user.city}" required="true" requiredMessage="Cannot be blank!"/>
<p:message for="city" showSummary="true" showDetail="false"/>
<p:outputLabel value="E-mail" />
<p:inputText id="email" validator="#{Register.user.validateEmail}" value="#{Register.email}"/>
<p:message for="email" showSummary="true" showDetail="false"/>
<p:outputLabel value="Phone number" />
<p:inputText id="phone" value="#{Register.user.phone}" required="true" validatorMessage="Phone number must be between 8 and 16 numbers long" requiredMessage="Cannot be blank!">
<f:validateLongRange minimum="8" maximum="16"/>
</p:inputText>
<p:message for="phone" showDetail="false" showSummary="true"/>
<p:commandButton type="submit" id="submitButton" value="submit" update="grid" ajax="true"/>
<p/>
#{Register.user}
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
The bean:
#SessionScoped
#ManagedBean(name="Register")
public class registerBean implements Serializable {
private User user = new User();
public void validateUsername(FacesContext context, UIComponent component, Object value) {
String message = "";
String username = (String) value;
if(username == null || username.equals("")) {
((UIInput)component).setValid(false);
message = "Enter a username";
context.addMessage(component.getClientId(context), new FacesMessage(message));
}
//else user.setUsername(username);
}
public void validatePasswords(FacesContext context, UIComponent component, Object value) {
String message = "";
String password = (String) value;
boolean hasNumber = false;
for(int i = 0; i < password.length(); i++) {
if(Character.isDigit(password.charAt(i))) {
hasNumber = true;
}
}
if(!hasNumber && password.length() < 8) {
((UIInput)component).setValid(false);
message = "You need to have at least one number and the password must be atleast 8 characters long";
context.addMessage(component.getClientId(context), new FacesMessage(message));
}
//else user.setPassword(password);
}
public void validateRepPassword(FacesContext context, UIComponent component, Object value) {
String message = "";
String repPassword = (String) value;
if(!repPassword.equals(user.getPassword())) {
((UIInput)component).setValid(false);
message = "The passwords don't match.";
context.addMessage(component.getClientId(context), new FacesMessage(message));
}
//else user.setRepeatPass(repPassword);
}
public void validatePostnumber(FacesContext context, UIComponent component, Object value) {
String message = "";
try {
Integer postnumber = (Integer) value;
} catch (Exception e) {
((UIInput)component).setValid(false);
message = "The postnumber can only be numbers";
context.addMessage(component.getClientId(context), new FacesMessage(message));
}
//user.setPostnumber(((Integer) value).intValue());
}
public void validateEmail(FacesContext context, UIComponent component, Object value) {
String message = "";
try {
InternetAddress email = new InternetAddress((String) value);
email.validate();
} catch(AddressException ae) {
((UIInput)component).setValid(false);
message = "Type a valid email address";
context.addMessage(component.getClientId(context), new FacesMessage(message));
}
//user.setEmail((String)value);
}
public User getUser() {
return user;
}
}
And finally the normal User java class
public class User {
private String username;
private String password;
private String repeatPass;
private String address;
private int postnumber;
private String city;
private String firstName;
private String surname;
private String email;
private long phone;
+setters/getters and a toString()
}
I figured out the problem. I feel kinda stupid, but there wasn't really any problem from the start. The thing was that because of all the validators and everything, the validation was set to false on several fields which led to the fact that the values didn't pass back. As soon as I set all correct information, it worked.

JSF Complex form - Binding Error

I have a form with some inputs which has a ViewScoped *ManagedBean* behind. At the bottom of the form I have a CommandButton for saving the data. There is a datatable on the form which new items could be added by entering data to an input and clicking another CommandButton. When user filled all the inputs and added any items to the datatable he/she can click the save button. But I have some problems in controling the add button and updating the datamodel. When I set the immadiate of the button to true the value of the input won't update and when I set it to false validation error will happen for the rest of the inputs on the form!!!
Code if it helps:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="./templates/master.xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns="http://www.w3.org/1999/xhtml">
<ui:define name="windowTitle">
#{lbls.registerWaggon}
</ui:define>
<ui:define name="sectionTitle">
<h:panelGroup layout="block" styleClass="sectionTitle">
<h:graphicImage library="img" name="railways.png"/>
</h:panelGroup>
</ui:define>
<ui:define name="right">
<ui:include src="templates/railwaysright.xhtml"/>
</ui:define>
<ui:define name="extraCSS">
<h:outputStylesheet library="css" name="persiancalendar.css"/>
<h:outputStylesheet library="css" name="grid.css"/>
</ui:define>
<ui:define name="extraJS">
<h:outputScript library="js" name="lib/persiancalendar.js"/>
</ui:define>
<ui:define name="content">
<h:panelGroup rendered="#{!current.hasLoggedIn()}">
<h:panelGroup layout="block" styleClass="warningBox">
<h:outputText value="#{app.youHaveNotLoggedIn}"/>
<br/>
<h:link value="#{lbls.login}" outcome="login"/>
</h:panelGroup>
</h:panelGroup>
<p:panel rendered="#{current.hasLoggedIn() and requestWaggon.isViewable()}">
<f:facet name="header">
<h:outputText value="#{lbls.registerWaggonLong}" />
</f:facet>
<h:form id="frmRequest">
<h:panelGrid columns="3" footerClass="buttons">
<h:outputText value="#{lbls.number}:"/>
<h:inputText id="number" label="#{lbls.number}" styleClass="ltr" value="#{requestWaggon.request.number}" readonly="true" />
<h:message for="number" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.requestDate}:"/>
<h:inputText styleClass="ltr" id="date" label="#{lbls.requestDate}" value="#{requestWaggon.request.date}" required="true" readonly="true">
<f:converter converterId="ir.khorasancustoms.DateConverter"/>
</h:inputText>
<h:message for="date" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.nameOfMaterialOwner}:"/>
<h:inputText id="ownerName" label="#{lbls.nameOfMaterialOwner}" value="#{requestWaggon.request.fullName}" required="true" readonly="true"/>
<h:message for="ownerName" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.companyName}:"/>
<h:inputText id="companyName" label="#{lbls.companyName}" value="#{requestWaggon.request.companyName}" required="true" readonly="true"/>
<h:message for="companyName" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.nameOfMaterial}:"/>
<h:inputText id="nameOfMaterial" label="#{lbls.nameOfMaterial}" value="#{requestWaggon.request.materialName}" required="true" readonly="true"/>
<h:message for="nameOfMaterial" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.materialWeight}:"/>
<h:panelGroup>
<h:inputText id="materialWeight" styleClass="ltr" label="#{lbls.materialWeight}" value="#{requestWaggon.request.materialWeight}" required="true" style="min-width: 0px; width: 60px" readonly="true"/>
<h:outputText value=" #{requestWaggon.request.weightUnit}"/>
</h:panelGroup>
<h:message for="materialWeight" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.senderAddress}:"/>
<h:inputText id="senderAddress" label="#{lbls.senderAddress}" value="#{requestWaggon.request.address}" required="true" style="width: 350px;" readonly="true"/>
<h:message for="senderAddress" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.receiverAddress} (#{lbls.country}):"/>
<h:outputText value="#{requestWaggon.request.country}"/>
<h:message for="country" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.station}:"/>
<h:inputText id="station" label="#{lbls.station}" value="#{requestWaggon.request.station}" required="true" readonly="true"/>
<h:message for="station" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.loadingDate}:"/>
<h:panelGroup>
<h:inputText styleClass="ltr" id="loadingDate" label="#{lbls.loadingDate}" value="#{requestWaggon.request.loadingDate}" required="true" readonly="true">
<f:converter converterId="ir.khorasancustoms.DateConverter"/>
</h:inputText>
</h:panelGroup>
<h:message for="loadingDate" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.boundryStation}:"/>
<h:outputText value="#{requestWaggon.request.bountryStation}"/>
<h:message for="boundryStation" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value=""/>
<h:outputText value=""/>
<h:outputText value=""/>
<h:outputText value="#{lbls.confirmDate}:"/>
<h:panelGroup>
<h:inputText styleClass="date ltr" id="confirmDate" label="#{lbls.confirmDate}" value="#{requestWaggon.request.confirmDate}" required="true">
<f:converter converterId="ir.khorasancustoms.DateConverter"/>
</h:inputText>
<input type="button" value="..." onclick="displayDatePicker('frmRequest:confirmDate', this);" class="datePicker"/>
</h:panelGroup>
<h:message for="confirmDate" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.confirm}:" styleClass="b"/>
<h:selectOneMenu value="#{requestWaggon.request.confirm}">
<f:selectItem/>
<f:selectItems value="#{searchRequest.allConfirms}" var="confirm" itemLabel="#{searchRequest.confirmCaption(confirm)}" itemValue="#{confirm}"/>
</h:selectOneMenu>
<h:message for="confirm" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.description}:"/>
<h:inputText id="description" label="#{lbls.description}" value="#{requestWaggon.request.confirmDescription}" required="false" style="width: 350px;"/>
<h:message for="description" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
<h:outputText value="#{lbls.waggonType}:"/>
<h:selectOneMenu id="waggonType" label="#{lbls.waggonType}" value="#{requestWaggon.request.waggonType}" required="true">
<f:selectItem/>
<f:selectItems value="#{requestWaggon.waggonTypes}"/>
<f:converter converterId="ir.khorasancustoms.CatalogValueFixedConverter"/>
</h:selectOneMenu>
<h:message for="waggonType" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>
**<h:outputText value="#{lbls.specialWaggonNumber}:"/>
<h:panelGroup>
<h:inputText id="specialWaggonNumber" label="#{lbls.specialWaggonNumber}" binding="#{requestWaggon.waggonNumberComponent}" />
<h:commandButton value="#{lbls.add}" action="#{requestWaggon.addWaggon}" immediate="true"/>
</h:panelGroup>
<h:message for="specialWaggonNumber" infoClass="info" warnClass="warning" errorClass="error" fatalClass="fatal"/>**
<h:outputText value="#{lbls.waggons}:"/>
<h:dataTable value="#{requestWaggon.waggonsDataModel}" var="waggon" columnClasses="index,,action" styleClass="grid" headerClass="title" rowClasses="two,three,one">
<h:column>
<f:facet name="header">#{lbls.index}</f:facet>
<h:outputText value="#{searchRequest.datamodel.rowIndex + 1}"/>
</h:column>
<h:column>
<f:facet name="header">#{lbls.number}</f:facet>
<h:outputText value="#{waggon.number}"/>
</h:column>
<h:column>
<f:facet name="header">#{lbls.action}</f:facet>
<h:commandLink action="delete">
<h:graphicImage styleClass="nb" alt="#{lbls.delete}" title="#{lbls.delete}" library="img" name="delete.png"/>
<f:param name="id" value="#{waggon.id}"/>
</h:commandLink>
</h:column>
</h:dataTable>
<f:facet name="footer">
<h:button outcome="searchrequest" value="#{lbls.cancel}" rendered="#{requestWaggon.id ne null}"/>
<h:commandButton action="#{requestWaggon.doNew}" value="#{lbls.new}" rendered="#{requestWaggon.request.id ne null}"/>
<h:commandButton action="#{requestWaggon.save}" value="#{lbls.ok}"/>
</f:facet>
</h:panelGrid>
<h:outputScript>
focusElement('frmRequest:confirmDate');
</h:outputScript>
</h:form>
<f:facet name="footer">
<h:messages styleClass="boxMessages" layout="table" infoClass="infoBox" warnClass="warningBox" errorClass="errorBox" fatalClass="errorBox" globalOnly="true"/>
<h:link outcome="searchrequest" value="#{lbls.searchRequestWaggon}"/>
</f:facet>
</p:panel>
<p:panel rendered="#{current.hasLoggedIn() and !requestWaggon.isViewable()}">
<h:panelGroup layout="block" styleClass="warningBox">
<h:outputText value="#{app.accessDenied}" />
</h:panelGroup>
</p:panel>
</ui:define>
</ui:composition>
bean
#ManagedBean(name = "requestWaggon")
#ViewScoped
public class RequestWaggonBean {
//<editor-fold defaultstate="collapsed" desc="FIELDS">
private Logger logger;
#ManagedProperty(value = "#{current}")
private CurrentSessionBean current;
private RequestWaggon request;
private Set<CatalogValue> weightUnits;
private Set<CatalogValue> countries;
private Set<CatalogValue> boundryStations;
private Set<CatalogValue> waggonTypes;
private Integer id;
#ManagedProperty(value = "#{searchRequest}")
private SearchRequestBean searchRequest;
private Integer newWaggonNumber;
private HtmlInputText waggonNumberComponent;
private DataModel<Waggon> waggonsDataModel;
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="CONSTRUCTORS">
public RequestWaggonBean() {
logger = LogUtil.getLogger(RequestWaggonBean.class);
request = new RequestWaggon();
ExternalContext exContext = FacesContext.getCurrentInstance().getExternalContext();
HttpServletRequest httpRequest = (HttpServletRequest) exContext.getRequest();
String strId = httpRequest.getParameter("id");
try {
id = Integer.parseInt(strId);
} catch (Exception ex) {
logger.fatal(ex);
}
}
#PostConstruct
public void init() {
request.setDate(current.getDate());
SessionFactory factory = new Configuration().configure().buildSessionFactory();
Session session = factory.openSession();
ResourceBundle app = ResourceBundle.getBundle("application");
try {
//session.beginTransaction();
if (id != null) {
request = (RequestWaggon) session.get(RequestWaggon.class, id);
}
Query query = session.createQuery("from CatalogGroup as catalogGroup where catalogGroup.englishTitle = :englishTitle");
query.setParameter("englishTitle", "WeightUnit");
CatalogGroup weightUnit = (CatalogGroup) query.uniqueResult();
weightUnits = weightUnit.getValues();
query.setParameter("englishTitle", "Country");
CatalogGroup country = (CatalogGroup) query.uniqueResult();
countries = country.getValues();
query.setParameter("englishTitle", "BoundryStation");
CatalogGroup boundryStation = (CatalogGroup) query.uniqueResult();
boundryStations = boundryStation.getValues();
query.setParameter("englishTitle", "WaggonType");
CatalogGroup waggonType = (CatalogGroup) query.uniqueResult();
waggonTypes = waggonType.getValues();
//session.getTransaction().commit();
} catch (Exception ex) {
logger.fatal(ex);
Transaction tx = session.getTransaction();
if (tx.isActive()) {
tx.rollback();
}
String message = app.getString("databaseConnectionFailed");
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, message, message));
} finally {
session.close();
}
Waggon[] arrayWaggons = new Waggon[request.getWaggons().size()];
arrayWaggons = request.getWaggons().toArray(arrayWaggons);
waggonsDataModel = new ArrayDataModel<Waggon>(arrayWaggons);
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="METHODS">
public void save() {
boolean canSave = false;
String cantSaveMessage = "";
SessionFactory factory = new Configuration().configure().buildSessionFactory();
Session session = factory.openSession();
ResourceBundle app = ResourceBundle.getBundle("application");
try {
session.beginTransaction();
int number = 0;
if (request.getNumber() == null) {
number = RequestWaggon.nextNumber();
}
if (request.getNumber() != null || number > 0) {
if (request.getNumber() == null) {
request.setNumber(number);
canSave = isInsertable();
cantSaveMessage = app.getString("insertDenied");
} else {
canSave = isEditable();
cantSaveMessage = app.getString("editDenied");
}
if (canSave) {
session.saveOrUpdate(request);
RequestWaggonHistory history = new RequestWaggonHistory(request, current.getUser(), number > 0 ? 'I' : 'U', current.getIP());
session.save(history);
session.getTransaction().commit();
String message = app.getString("savedSuccessfully");
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, message, message));
} else {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, cantSaveMessage, cantSaveMessage));
}
} else {
logger.fatal("Getting next number failed!");
String message = app.getString("databaseConnectionFailed");
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, message, message));
}
} catch (Exception ex) {
logger.fatal(ex);
Transaction tx = session.getTransaction();
if (tx.isActive()) {
tx.rollback();
}
String message = app.getString("databaseConnectionFailed");
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, message, message));
} finally {
session.close();
}
}
public void addWaggon(ValueChangeEvent event) {
ResourceBundle app = ResourceBundle.getBundle("application");
String strNewWaggonNumber = event.getNewValue().toString();
Integer newWaggonNumber = Integer.parseInt(strNewWaggonNumber);
if (newWaggonNumber == null || newWaggonNumber <= 0) {
String message = app.getString("EnterWaggonNumber");
FacesContext.getCurrentInstance().addMessage("frmRequest:specialWaggonNumber", new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message));
} else {
Waggon newWaggon = new Waggon();
newWaggon.setNumber(newWaggonNumber);
request.getWaggons().add(newWaggon);
Waggon[] arrayWaggons = new Waggon[request.getWaggons().size()];
arrayWaggons = request.getWaggons().toArray(arrayWaggons);
waggonsDataModel = new ArrayDataModel<Waggon>(arrayWaggons);
}
}
public boolean isViewable() {
return current.isViewable();
}
public boolean isDeletable() {
return current.isDeletable() && request.getWaggons().isEmpty();
}
public boolean isInsertable() {
return current.isInsertable();
}
public boolean isEditable() {
return current.isEditable() && request.getConfirm() == null;
}
public void doNew() {
request = new RequestWaggon();
request.setDate(current.getDate());
}
public String delete() {
SessionFactory factory = new Configuration().configure().buildSessionFactory();
Session session = factory.openSession();
ResourceBundle app = ResourceBundle.getBundle("application");
try {
session.beginTransaction();
session.delete(request);
RequestWaggonHistory history = new RequestWaggonHistory(request, current.getUser(), 'D', current.getIP());
session.save(history);
session.getTransaction().commit();
searchRequest.search();
String message = app.getString("deletedSuccessfully");
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, message, message));
} catch (ConstraintViolationException ex) {
String message = app.getString("constraintViolation");
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, message, message));
} catch (Exception ex) {
logger.fatal(ex);
Transaction tx = session.getTransaction();
if (tx.isActive()) {
tx.rollback();
}
String message = app.getString("databaseConnectionFailed");
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, message, message));
} finally {
session.close();
}
return "searchrequest";
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="PROPERTIES">
public RequestWaggon getRequest() {
return request;
}
public void setRequest(RequestWaggon requestWaggon) {
this.request = requestWaggon;
}
public CurrentSessionBean getCurrent() {
return current;
}
public void setCurrent(CurrentSessionBean current) {
this.current = current;
}
public Set<CatalogValue> getWeightUnits() {
return weightUnits;
}
public void setWeightUnits(Set<CatalogValue> weightUnits) {
this.weightUnits = weightUnits;
}
public Logger getLogger() {
return logger;
}
public void setLogger(Logger logger) {
this.logger = logger;
}
public Set<CatalogValue> getCountries() {
return countries;
}
public void setCountries(Set<CatalogValue> countries) {
this.countries = countries;
}
public Set<CatalogValue> getBoundryStations() {
return boundryStations;
}
public void setBoundryStations(Set<CatalogValue> boundryStations) {
this.boundryStations = boundryStations;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public SearchRequestBean getSearchRequest() {
return searchRequest;
}
public void setSearchRequest(SearchRequestBean searchRequest) {
this.searchRequest = searchRequest;
}
public Set<CatalogValue> getWaggonTypes() {
return waggonTypes;
}
public void setWaggonTypes(Set<CatalogValue> waggonTypes) {
this.waggonTypes = waggonTypes;
}
public Integer getNewWaggonNumber() {
return newWaggonNumber;
}
public void setNewWaggonNumber(Integer newWaggonNumber) {
this.newWaggonNumber = newWaggonNumber;
}
public DataModel<Waggon> getWaggonsDataModel() {
return waggonsDataModel;
}
public void setWaggonsDataModel(DataModel<Waggon> waggonsDataModel) {
this.waggonsDataModel = waggonsDataModel;
}
public HtmlInputText getWaggonNumberComponent() {
return waggonNumberComponent;
}
public void setWaggonNumberComponent(HtmlInputText waggonNumberComponent) {
this.waggonNumberComponent = waggonNumberComponent;
}
//</editor-fold>
}
The h:commandButton submits the whole form and all elements will be validated. You can use ajax to do a partial submit. Try the following:
Give your datatable an id value. So you can reference it from your commandButton:
<h:panelGroup id="tableWrapper">
<h:datatable id="mytable" value="#{requestWaggon.waggonsDataModel}" ..>
...
</h:datatable>
</h:panelGroup>
Then put an <f:ajax> inside your commandButton. The render and execute attributes must contain the id of your datatable; immediate=true is not needed:
<h:commandButton value="#{lbls.add}" action="#{requestWaggon.addWaggon}">
<f:ajax render="tableWrapper" execute="mytable"/>
</h:commandButton>

Resources