Email uniquness validate in jsf - jsf

Here is my JSF form email code section:
(Registration.xhtml)
<p:inputText id="email" required="true" label="Email" size="20" value="#{registrationBean.email}">
<f:validateRegex pattern="([^.#]+)(\.[^.#]+)*#([^.#]+\.)+([^.#]+)"/>
<f:validator id="uniqueEmailValidator"/>
</p:inputText>
<h:message for="email"/>
And this is my validator class:
#FacesValidator("uniqueEmailValidator")
public class UniqueEmailValidator implements Validator {
#Override
public void validate(FacesContext fc, UIComponent uic, Object value) throws ValidatorException {
if (value == null) {
return;
}
String email = (String) value;
CustomerService cService = new CustomerService();
if (!cService.exists(email)) {
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "mail is already in use.", "error"));
}
}
}
I got this error when to run the application:
/Registration.xhtml #49,73 <f:validator> A validator id was not specified. Typically the validator id is set in the constructor ValidateHandler(ValidatorConfig)

In your f:validator tag, change "id" to "validatorId"
<f:validator validatorId="uniqueEmailValidator"/>

Related

JSF SelectOneMenu not working without converter?

So I have the following xhtml code:
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{interview.interviewer.name}" />
</f:facet>
<f:facet name="input">
<p:selectOneMenu value="#{interview.interviewer}" style="width:100%" converter="interviewerConverter">
<f:selectItems value="#{interviewerController.allInterviewers}" var="s" itemLabel="#{s.name}" itemValue="#{s}" />
</p:selectOneMenu>
</f:facet>
</p:cellEditor>
When I try to edit the data in the cell, I get the following error:
Conversion Error setting value 'com.jpa.entities.Interviewer#288002c2' for 'null Converter'.
I took a look at the similar posts but did not find out what is wrong here.
Also I have created the following converter, with this I do not get a converter error:
#FacesConverter("interviewerConverter")
public class InterviewerConverter implements Converter {
public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
if(value != null && value.trim().length() > 0) {
try {
InterviewerController service = (InterviewerController) fc.getExternalContext().getApplicationMap().get("interviewerController");
return service.getallInterviewers().get(Integer.parseInt(value));
} catch(NumberFormatException e) {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid"));
}
}
else {
return null;
}
}
public String getAsString(FacesContext fc, UIComponent uic, Object object) {
if(object != null) {
return String.valueOf(((Interviewer) object).getId());
}
else {
return null;
}
}
}
After implementing the converter, I get a NullPointerException on the following list: (service.getallInterviewers())
return service.getallInterviewers().get(Integer.parseInt(value));
but in the controller, the list is initialized like this:
#PostConstruct
public void init(){
initAllInterviewers();
}
What can be wrong here?

JSF Validator and outputLabel

I'm working with a web application with the following technologies
spring 4.3
JSF 2.2.14
PrimeFaces 6.1
Omnifaces 2.6.4
I need to validate an h:inputText, and I'm trying to use the javax.faces.validator.Validator interface.
All is working well but when the validation fail, I'm not able to retrieve the label of the field, that is stored in a p:outputLabel using the "for" attribute.
Facelets code
<p:outputLabel id="selectedAdvPriceOutputLabel" for="selectedAdvPrice" value="#{msg['prezzo']}"/>
<h:inputText id="selectedAdvPrice"
value="#{addAdvertisingController.advertisingBean.price}"
class="form-control"
converter="javax.faces.BigDecimal"
required="#{empty param[draftSave.clientId] and empty param[draftSaveXS.clientId]}"
requiredMessage="#{msg['prezzo']} #{msg['campoObbligatorio']}">
<f:validator binding="#{numberGreaterThanZeroJsfValidator}" />
</h:inputText>
Validator - validate method
public void validate(FacesContext context, UIComponent component, Object value) {
if (value != null) {
String v = value.toString();
if (StringUtils.isNotEmpty(v)) {
try {
BigDecimal bd = new BigDecimal(v);
if(bd.compareTo(BigDecimal.ZERO) <= 0){
// how to retrieve the field label???
FacesMessage msg = new FacesMessage("messageWithout label", "messageWithout label");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg, new IllegalArgumentException(exceptionMessage));
}
} catch (NumberFormatException e) {
FacesMessage msg = new FacesMessage("messageWithout label", "messageWithout label");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg, new IllegalArgumentException(exceptionMessage));
}
}
}
}
How can I retrieve the value attribute of the p:outputLabel linked to the h:inputText that is not passing the validation?
Thank you
According to Primefaces User's Guide --> 3.93 OutputLabel
Auto Label
OutputLabel sets its value as the label of the target component to be displayed in validation errors so the target component
does not need to define the label attribute again.
<h:outputLabel for="input" value="Field" />
<p:inputText id="input" value="#{bean.text}" label="Field"/>
can be rewritten as;
<p:outputLabel for="input" value="Field" />
<p:inputText id="input" value="#{bean.text}" />
It means, that OutputLabel simply sets the label attributte of a component to which the label is attached.
Just retrieve this attributte in the validator, for example in this way:
public void validate(FacesContext context, UIComponent component, Object value) {
Object labelObj = component.getAttributes().get("label");
String label = (labelObj!=null) ? labelObj.toString() : "Unknown label";
.....
.....
// how to retrieve the field label???
String message = String.format("%s : My conversion error message", label);
FacesMessage msg = new FacesMessage(message,message) ;
.....
.....
I've tested it and it works for both p:inputText and h:inputText components.
Hi, I've debugged the code and component.getAttributes().get("label")
is null
I've tested it again on JSF 2.2/Primefaces 6.1/Wildfy 10.x and it works.
Here is a simple demo project on GitHub link
index.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form>
<p:panel id="panel" header="Form" style="margin-bottom:10px;">
<p:messages id="messages" />
<h:panelGrid columns="2" cellpadding="5">
<p:outputLabel id="label1_id"
for="input1_id" value="This Is My label for h:input" />
<h:inputText id="input1_id" value="#{myBean.price1}"
required="true" >
<f:validator validatorId="MyValidator" />
</h:inputText>
<p:outputLabel id="label2_id"
for="input2_id" value="This Is My label for p:input" />
<p:inputText id="input2_id" value="#{myBean.price2}" required="true">
<f:validator validatorId="MyValidator" />
</p:inputText>
</h:panelGrid>
<p:commandButton update="panel" value="Submit" />
</p:panel>
</h:form>
</h:body>
</html>
bean
#Named
#SessionScoped
public class MyBean implements Serializable {
private static final long serialVersionUID = 5455916691447931918L;
private Integer price1;
private Integer price2;
public Integer getPrice2() {
return price2;
}
public void setPrice2(Integer price2) {
this.price2 = price2;
}
public Integer getPrice1() {
return price1;
}
public void setPrice1(Integer price1) {
this.price1 = price1;
}
}
Validator
#FacesValidator("MyValidator")
public class MyValidator implements Validator {
public void validate(FacesContext context, UIComponent component, Object value) {
Object labelObj = component.getAttributes().get("label");
String label = (labelObj!=null) ? labelObj.toString() : "Unknown label";
if (value != null) {
String v = value.toString();
if (null != v && !v.isEmpty()) {
try {
BigDecimal bd = new BigDecimal(v);
if (bd.compareTo(BigDecimal.ZERO) <= 0) {
// how to retrieve the field label???
String message = String.format("%s : Value must be greater than 0", label);
FacesMessage msg = new FacesMessage(message,message) ;
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg, new IllegalArgumentException("Validator exception:" + message));
}
} catch (NumberFormatException e) {
String message = String.format("%s : Value must be a number", label);
FacesMessage msg = new FacesMessage(message,message);
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg, new IllegalArgumentException("Validator exception:" + message));
}
}
}
}
}
And a result is:
Some things that may help or are common:
remove id from *:outputLabel as this is not needed
use validatorMessage="#{bundle.SOME_FIELD_VALIDATION_ERROR}" to have a localizable message, if your validator is throwing javax.faces.validator.ValidatorException (you can import this above your validator class, of course)
get rid of the code for the label-retrieval, see above validatorMessage field
<f:validator binding="#{someValidator}" /> seem to cause more problems, common way is: <f:validator validatorId="SomeFooValidator" /> within *:inputText (you have to make it non-self-closing)
and then annotate your validator class with #FacesValidator ("SomeFooValidator") (javax.faces.validator.FacesValidator)
Are you using JSF2.2?

Why do I can alway get label in getAsObject() in Primefaces?

I do not why although I verify everything which is right. Anyone know?
I tried to debug:
- getAsString() return ID (that's right)
- when I submitted - getAsObject() always throw exception because the label values was always passed instead of ID values.
My code as below:
my xhtml file:
<div class="ui-grid-row" style="margin-top: 5px; margin-bottom: 5px;">
<div class="ui-grid-col-2 pdt4">
<p:outputLabel for="txtApprovalScheduler"
value="#{lang['workforce.category.parttimeManagement.approved.scheduler']}"/>
</div>
<div class="ui-grid-col-2">
<p:selectOneMenu value="#{parttimeController.selectedAgentDTO}"
id="txtApprovalScheduler"
filterMatchMode="contains" editable="true"
style="width: 86%;"
required="true"
requiredMessage="#{lang['workforce.category.parttimeManagement.approved.scheduler.missing']}">
<f:converter converterId="agentConverter"/>
<f:selectItem itemValue="" itemLabel="#{lang['wf.common.choose']}"/>
<f:selectItems value="#{parttimeController.agentDTOs}" var="agentItem1"
itemLabel="#{agentItem1.userName}"
itemValue="#{agentItem1}"/>
</p:selectOneMenu>
</div>
<div class="ui-grid-col-2 pdt4">
<p:outputLabel for="txtApprovalRegister"
value="#{lang['workforce.category.parttimeManagement.approved.register']}"/>
</div>
<div class="ui-grid-col-2">
<p:selectOneMenu value="#{parttimeController.selectedAgentDTOForRegister}"
id="txtApprovalRegister" editable="true"
filterMatchMode="contains" style="width: 86%; font-size: 12px !important;"
required="true"
requiredMessage="#{lang['workforce.category.parttimeManagement.approved.register.missing']}">
<f:converter converterId="agentConverter"/>
<f:selectItem itemValue="" itemLabel="#{lang['wf.common.choose']}"/>
<f:selectItems value="#{parttimeController.agentDTOs}" var="item1"
itemLabel="#{item1.userName}"
itemValue="#{item1}"/>
</p:selectOneMenu>
</div>
</div>
My Converter:
#FacesConverter(forClass = AgentDTO.class,value = "agentConverter")
public class AgentConverter implements Converter {
public static List<AgentDTO> listAgentDTOs;
#Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String agentId) {
if (agentId.trim().equals("")) {
return null;
} else {
try {
Long number = Long.parseLong(agentId);
for (AgentDTO a : listAgentDTOs) {
if (a.getAgentId() == number) {
return a;
}
}
} catch (NumberFormatException exception) {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid data"));
}
}
return null;
}
#Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object value) {
if (value == null || value.equals("") || "-1".equals(value)) {
return "";
} else {
String result = String.valueOf(((AgentDTO) value).getAgentId());
return result;
}
}
}
My bean:
#Component
#Scope("view")
#ManagedBean(name = "parttimeController")
public class ParttimeController extends BaseController implements Serializable {
private AgentDTO selectedAgentDTO;
private AgentDTO selectedAgentDTOForRegister;
private List<AgentDTO> agentDTOs;
.... getter/setter and initiallize AgentCenvert.listAgentDTOs
My class:
public class AgentDTO{
private Long agentId;
private String userName;
....getter/setter
}
I found out the reason - I only remove editable attribute in selectOneMenu. So getAsObject() will pass a value instead of a label

primefaces p:messages are not displayed

I have a button in a form and I want an error message to be displayed when I click on this button. It is a step I want to complete before coding something similar. My code does not work because the error message is not displayed when I click on the button.
My form is:
<h:form id="myForm">
<p:messages id="errorMessage" for="myForm" autoUpdate="true" />
<p:fieldset id="myFieldSet"
style="margin-left:auto ; margin-right:auto ; width:98% ; height:90px;">
<p:outputLabel for="numSi"
value="Value :"
style="margin-left:31px;margin-top:25px;" />
<p:inputText id="numSi"
value="#{suppSiBean.researchValue}"
maxlength="9" required="true">
</p:inputText>
<p:commandButton id="suppSignaButton" type="submit" ajax="true"
value="Launch"
style="text-align: center ; height:45px; width:150px ; margin-top:20px;"
action="#{suppSiBean.lancerRequete()}" />
</p:fieldset>
</h:form>
Excerpt of my bean :
public void lancerRequete() {}
FacesContext context = FacesContext.getCurrentInstance();
//I'm intentionally hide the values of the three following variables because it's confidential
ResourceBundle bundle = ...
String message = ...
String messageFormat = ...
FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, messageFormat.toString(), "");
FacesContext.getCurrentInstance().addMessage(getClientId("myForm"), facesMessage);
}
public String getClientId(String id) {
FacesContext context = FacesContext.getCurrentInstance();
UIViewRoot root = context.getViewRoot();
UIComponent c = findComponent(root, id);
LOGGER.info("c.getClientId(context) vaut :" + c.getClientId(context));
return c.getClientId(context);
}
private UIComponent findComponent(UIComponent c, String id) {
if (id.equals(c.getId())) {
return c;
}
Iterator<UIComponent> kids = c.getFacetsAndChildren();
while (kids.hasNext()) {
UIComponent found = findComponent(kids.next(), id);
if (found != null) {
return found;
}
}
return null;
}
Why not targeting the ID of the component directly in the addMessage method ?
public void lancerRequete() {}
...
FacesContext.getCurrentInstance().addMessage("errorMessage", facesMessage);
}
Finally, you should tell when to update this component by adding update attribute :
<p:commandButton ... update="errorMessage" />

selectonemenu, when editable=false, cannot submit the form

My form is working if editable is set to true but not when it's false. When false the submit action method is not even called. I need it to be false (not editable so I can store the correct value in db).
This is the menu I added.
<tr><td>
<h:outputLabel for="country">#{registering.Country}: </h:outputLabel></td>
<td><p:selectOneMenu editable="false" id="country" required="true" requiredMessage="Required" value="#{subscribeUser.user.countryBean}" converter="#{countriesConverter}" effect="fold" >
<f:selectItem itemValue="#{null}" itemLabel="#{registering.SelectCountry}" />
<f:selectItems value="#{countriesConverter.countries}" var="country" itemLabel="#{country.shortName}" itemValue="#{country}" />
</p:selectOneMenu></td><td></td><td>
<span class="error"><h:message id="countryMessage" for="country"/></span></td>
</tr>
Notice that the select one menu has editable="false" it doesn't work in that case. But if I put editable="true" it works.
here is the full form, last 2 fields are problematic:
<h:form>
<table class="registration">
<!-- username -->
<tr><td>
<h:outputLabel for="username">#{registering.Username}: </h:outputLabel></td><td>
<p:inputText id="username" value="#{subscribeUser.user.username}"
validator="#{usernameValidator.validate}" maxlength="#{values.small}">
<f:passThroughAttribute name="required" value="true"/>
<f:ajax event="blur" render="usernameCheck usernameMessage submit"></f:ajax>
</p:inputText></td><td>
<h:panelGroup id="usernameCheck">
<h:graphicImage library="images/icons" name="failed_indicator.png" rendered="#{usernameValidator.isIndicatorVisible.usernameFailed}"></h:graphicImage>
<h:graphicImage library="images/icons" name="success_indicator.png" rendered="#{usernameValidator.isIndicatorVisible.usernameSuccess}"></h:graphicImage>
</h:panelGroup></td><td>
<span class="error"><h:message id="usernameMessage" for="username"/></span></td>
</tr>
<!-- password -->
<tr><td>
<h:outputLabel for="password">#{registering.Password}: </h:outputLabel></td><td>
<p:password id="password" value="#{subscribeUser.userCredential.password}" feedback="true"
promptLabel="#{registering.PleaseEnterPass}" weakLabel="#{registering.Weak}"
goodLabel="#{registering.Good}" strongLabel="#{registering.Strong}"
requiredMessage="#{registering.reqPassword}"
validator="#{passwordValidator.validate}">
<f:passThroughAttribute name="required" value="true"/>
<f:attribute name="confirm" value="#{confirmPassword}" />
<f:passThroughAttribute name="required" value="true"/>
<f:ajax event="blur" execute="password confirmPassword" render="passwordMessage passwordCheck confpasswordCheck submit"></f:ajax>
</p:password></td><td>
<h:panelGroup id="passwordCheck">
<h:graphicImage library="images/icons" name="failed_indicator.png" rendered="#{passwordValidator.isIndicatorVisible.passwordFailed}"></h:graphicImage>
<h:graphicImage library="images/icons" name="success_indicator.png" rendered="#{passwordValidator.isIndicatorVisible.passwordSuccess}"></h:graphicImage>
</h:panelGroup>
</td><td>
<span class="error"><h:message id="passwordMessage" for="password"/></span></td>
</tr>
<!-- Confirm password -->
<tr><td>
<h:outputLabel for="confirmPassword" value="#{registering.ConfirmPass}: "/></td><td>
<p:password id="confirmPassword" required="true"
requiredMessage="#{registering.PleaseConfirmPassword}"
binding="#{confirmPassword}">
<f:passThroughAttribute name="required" value="true"/>
<f:ajax event="blur" execute="password confirmPassword" render="passwordMessage passwordCheck confpasswordCheck submit"></f:ajax>
</p:password> </td><td>
<h:panelGroup id="confpasswordCheck">
<h:graphicImage library="images/icons" name="failed_indicator.png" rendered="#{passwordValidator.isIndicatorVisible.passwordFailed}"></h:graphicImage>
<h:graphicImage library="images/icons" name="success_indicator.png" rendered="#{passwordValidator.isIndicatorVisible.passwordSuccess}"></h:graphicImage>
</h:panelGroup>
</td><td>
<span class="error"><h:message id="passwordConfMessage" for="confirmPassword" /></span></td>
</tr>
<!-- Email -->
<tr><td>
<h:outputLabel for="email">#{registering.Email}: </h:outputLabel></td><td>
<p:inputText id="email" required="true" value="#{subscribeUser.user.email}"
validator="#{emailValidator.validate}"
requiredMessage="#{registering.reqEmail}">
<f:passThroughAttribute name="required" value="true"/>
<f:passThroughAttribute name="type" value="email"/>
<f:passThroughAttribute name="maxlength" value="100"/>
<f:ajax event="blur" render="emailCheck emailMessage submit"></f:ajax>
</p:inputText></td><td>
<h:panelGroup id="emailCheck">
<h:graphicImage library="images/icons" name="failed_indicator.png" rendered="#{emailValidator.isIndicatorVisible.emailFailed}"></h:graphicImage>
<h:graphicImage library="images/icons" name="success_indicator.png" rendered="#{emailValidator.isIndicatorVisible.emailSuccess}"></h:graphicImage>
</h:panelGroup> </td><td>
<span class="error"><h:message id="emailMessage" for="email"/></span></td>
</tr>
<!-- Country -->
<tr><td>
<h:outputLabel for="country">#{registering.Country}: </h:outputLabel></td>
<td colspan="3"><p:selectOneMenu required="true" editable="true" id="country" value="#{subscribeUser.user.countryBean}" converter="#{countriesConverter}" effect="fold">
<f:selectItems value="#{countriesConverter.countries}" var="country" itemLabel="#{country.shortName}" itemValue="#{country}" />
</p:selectOneMenu></td>
</tr>
<!-- Timezone -->
<tr><td>
<h:outputLabel for="timezone">#{registering.Timezone}: </h:outputLabel></td>
<td colspan="3">
<p:selectOneMenu id="timezone" editable="true" required="true" value="#{subscribeUser.user.timezoneOffset}" converter="#{timezonesConverter}" effect="fold" >
<f:selectItems value="#{timezonesConverter.timezonesList}" var="timezone" itemLabel="#{timezone.name}" itemValue="#{timezone}" />
</p:selectOneMenu></td>
</tr>
</table>
<div class="areYouARobot" ><div class="captchaLabel">#{registering.AreYouARobot}</div>
<!-- <div class="g-recaptcha" data-sitekey="6LdFTgcTAAAAAHQeLLEKPE-of2si0GrwuZXoEAHb"></div> --></div>
<div class="submit">
<p:commandButton value="#{registering.Submit}" id="submit" action="#{subscribeUser.inscrireUser}" icon="ui-icon-disk"
disabled="#{!(usernameValidator.ok and passwordValidator.ok and emailValidator.ok)}" >
</p:commandButton></div>
</h:form>
Here is the country converter:
#ManagedBean
public class CountriesConverter implements Converter {
private List<Country> countries;
private List<String> countriesStr;
private List<Integer> countriesId;
private Country country;
#EJB
private CountriesService cs;
#PostConstruct
public void init() {
this.countries = cs.getAllCountries();
this.countriesStr = new ArrayList<String>();
this.countriesId = new ArrayList<Integer>();
for (Country c : countries) {
this.countriesStr.add(c.getShortName());
}
for (Country c : countries) {
this.countriesId.add(c.getIdCountry());
}
}
#Override
public Country getAsObject(FacesContext ctx, UIComponent component,
String submittedValue) {
if (submittedValue == null || submittedValue.isEmpty()) {
return null;
}
try {
return cs.findByName(submittedValue);
} catch (Exception e) {
return null;
}
}
#Override
public String getAsString(FacesContext fc, UIComponent uic,
Object modelValue) {
Country datCountry = (Country) modelValue;
if (datCountry == null) {
return "";
}
else if (datCountry instanceof Country) {
return datCountry.getShortName();
} else {
return null;
}
}
//get&sets
}
The country entity:
#Entity
#Table(name="countries")
#NamedQuery(name="Country.findAll", query="SELECT c FROM Country c")
public class Country implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private int idCountry;
#Column(name="calling_code")
private String callingCode;
private String cctld;
private String iso2;
private String iso3;
#Column(name="long_name")
private String longName;
private String numcode;
#Column(name="short_name")
private String shortName;
#Column(name="un_member")
private String unMember;
//bi-directional many-to-one association to User
#OneToMany(mappedBy="countryBean")
private List<User> users;
public Country() {
}
//getter & setters
}
My timezone converter:
#ManagedBean
public class TimezonesConverter implements Converter {
private List<Timezone> timezonesList;
private Map<String, Timezone> myMap;
private static final String[] timezonesStr = {
"(GMT -12:00) Eniwetok, Kwajalein",
"etcetera" };
public TimezonesConverter() {
timezonesList = new ArrayList<Timezone>();
myMap = new TreeMap<String, Timezone>();
int offset = -720;
for (String s : timezonesStr) {
Timezone timezone = new Timezone(s, offset);
timezonesList.add(timezone);
myMap.put(s, timezone);
offset += 60;
}
}
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1,
String submittedValue) {
if (submittedValue == null || submittedValue.isEmpty()) {
return null;
}
try {
return myMap.get(submittedValue);
} catch (Exception e) {
return null;
}
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1,
Object modelValue) {
// casting error here.
Timezone timezone = (Timezone) modelValue;
if (timezone == null) {
return "";
} else if (timezone instanceof Timezone) {
return timezone.getName();
} else {
return null;
}
}
//getters
}
Timezone class:
public class Timezone {
private String name;
private int offset;
public Timezone(String name, int offset) {
this.name = name;
this.value = offset;
}
//getters and setters
}
I commented the timezone thing but when uncommented it gives me this error, which makes no sens to me since the var I put in the timezone menu is a timezone object:
java.lang.ClassCastException: java.lang.Integer cannot be cast to main.java.utils.Timezone
at main.java.converters.TimezonesConverter.getAsString(TimezonesConverter.java:82)
I did a workaround for this but I'm unhappy with it:
#Override
public String getAsString(FacesContext arg0, UIComponent arg1,
Object modelValue) {
int offset = (int) modelValue;
if (modelValue == null) {
return "";
} else {
for (Timezone tz : timezonesList) {
if (tz.getOffset() == offset) {
return tz.getName();
}
}
}
return null;
}
and I switched the value in the form to :
<f:selectItems value="#{timezonesConverter.timezonesList}" var="timezone" itemLabel="#{timezone.name}" itemValue="#{timezone.offset}" />
So instead of the value being a Timezone object (that x reason was considered as an Integer and caused the cast exception), it is the int variable inside the Timezone object that is taken, and that works.
the user entity:
#Entity
#Table(name="users")
#NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private String username;
private String email;
#Column(name="is_enabled")
private int isEnabled;
#Temporal(TemporalType.DATE)
#Column(name="member_since")
private Date memberSince;
#Column(name="profile_pic")
private String profilePic;
private int reputation;
private String role;
private String status;
private int timezoneOffset;
#Column(name="warning_lvl")
private int warningLvl;
private String xxx;
//bi-directional many-to-one association to Friend
#OneToMany(mappedBy="user1")
private List<Friend> friends1;
//bi-directional many-to-one association to Friend
#OneToMany(mappedBy="user2")
private List<Friend> friends2;
//bi-directional many-to-one association to Message
#OneToMany(mappedBy="user1")
private List<Message> messages1;
//bi-directional many-to-one association to Message
#OneToMany(mappedBy="user2")
private List<Message> messages2;
//bi-directional many-to-one association to Thethread
#OneToMany(mappedBy="user1")
private List<Thethread> thethreads1;
//bi-directional many-to-one association to Thethread
#OneToMany(mappedBy="user2")
private List<Thethread> thethreads2;
//bi-directional many-to-one association to Usercfg
#OneToMany(mappedBy="user")
private List<Usercfg> usercfgs;
//bi-directional many-to-one association to Userinfo
#OneToMany(mappedBy="user")
private List<Userinfo> userinfos;
//bi-directional many-to-one association to Country
#ManyToOne
#JoinColumn(name="country")
private Country countryBean;
public User() {
}
// getters & setters
}
The reason why method is not called is, that conversion of values fails.
Country field
CountriesConverter method getAsObject should have return type Object, I expect it's not called at all now.
Country class must implement the equals and hashCode methods.
Timezone field
The timezoneOffset property of the User class must be instance of the Timezone class.
OR
Keep the timezoneOffset int, remove the converter and set the int value using the itemValue attribute. See the example:
<p:selectOneMenu id="timezone" editable="true" required="true"
value="#{subscribeUser.user.timezoneOffset}" effect="fold" >
<f:selectItems value="#{timezonesConverter.timezonesList}" var="timezone"
itemLabel="#{timezone.name}" itemValue="#{timezone.offset}" />
</p:selectOneMenu>

Resources