"Validation Error: Value is not valid" error from f:datetimeConverter - validation

The following code creates a two radio buttons. Each option contains a date value that is successfully converted to a label of the format "yyyy-MM-dd". Once I make a selection and click the next button I get the following error "j_idt12:comDateChoice: Validation Error: Value is not valid". It seems simple enough but somethings wrong. Can any of you spot it?
I'm using JSF 2.0 in glassfish.
Backing bean
public List<SelectItem> getComDateList() {
List<SelectItem> items = new ArrayList<SelectItem>();
Calendar cal = GregorianCalendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.add(Calendar.MONTH, 1);
Date nextFirst = cal.getTime();
cal.add(Calendar.MONTH, 1);
Date followingFirst = cal.getTime();
items.add(new SelectItem(nextFirst, new SimpleDateFormat("yyyy-MM-dd").format(nextFirst)));
items.add(new SelectItem(followingFirst, new SimpleDateFormat("yyyy-MM-dd").format(followingFirst)));
return items;
}
JSF Code
<h:panelGrid columns="2">
<h:outputLabel value="#{msg.FinanceCommencementDate}" for="comDateChoice"/>
<h:selectOneRadio id="comDateChoice" value="#{signUpBean.current.commencementDate}" layout="pageDirection">
<f:convertDateTime type="date" dateStyle="short"/>
<f:selectItems value="#{signUpBean.comDateList}"/>
</h:selectOneRadio>
</h:panelGrid>

This error will occur if the selected item value didn't pass the Object#equals() check on any of the available select item values. This can happen if the getter returned a different list during the apply request values phase of the form submit request than it did during the initial request to display the form.
Because you're reconstructing the list in the getter instead of constructing once in the constructor of a view scoped bean, the Date objects will get a different timestamp on every call, it will be some minutes/seconds in the future as compared to the initial Date objects. Hence the equals() will fail.
Move this logic into the constructor of the bean and rewrite the getter so that it does what it is supposed to do: return only the data. Do not do loading logic in a getter. You should also put the bean in the view scope so that the constructor doesn't re-run when you submit the form.
#ManagedBean
#ViewScoped
public class SignUpBean {
private List<SelectItem> comDateList;
public SignUpBean() {
comDateList = new ArrayList<SelectItem>();
// Fill it here.
}
public List<SelectItem> getComDateList() {
return comDateList; // In getters, do nothing else than returning data!
}
}
Update: the converter is also a potential source of the problem. You've basically instructed it to strip off the time when rendering the HTML page. So it uses the default time when converting back to Date. Either use
<f:convertDateTime pattern="yyyy-MM-dd HH:mm:ss.SSS Z" />
or reset the time and timezone on the Calendar beforehand:
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
this way you can use just a <f:convertDateTime type="date" />

Related

How to pass a param through a Ajax request

My objective is to save the current cursor position and append new values to it for every new button we enter.To achive it i am trying to send a ajax request and update my back end coordinated every time is focus out of the input field.
I am succesfull i calling the java script function before calling by backing bean action method.But for some reason i am unable to see my request param values when ever i make a ajax request.
<p:inputText id="testing1" value="#{dropDownView.city}">
<p:ajax event="keyup" onstart="callOnAjax();" listener="#{dropDownView.assignCity()}" execute="#this" update="out1" >
<f:param value="test" name="#{articlePromo.promocionArticuloId}"/>
<h:inputHidden id="x" value="#{bean.x}" />
</p:ajax>
<script type="text/javascript">
function callOnAjax(){
$("#detailsPanel").bind("keydown keypress mousemove", function() {
var $form = jQuery(this).closest("form");
$form.find("input[id$=':x']").val($(this).caret().start);
alert("Current position: " + $(this).caret().start);
});
}
</script>
And in my dropDownView Controller
public void assignCity()
{
System.out.println("positon of x"+getX()+"position of y"+y);
FacesContext context = FacesContext.getCurrentInstance();
String id = context.getApplication().evaluateExpressionGet(context, "#{articlePromo.promocionArticuloId}", String.class);
city =country;
}
I tried all different approaches using hidden as well.But i dont see the value in my controller.I even hard coded the request param value and hidden attribute value.But still not succesfull.Any help is much appreciated.

Validation with JSF 2 only wanted on submit

I have an issue with validation, as I only want validation to take place when the submit button is clicked on the screen, not when another button is clicked.
In the displayed page option1.faces is the main file option1.xhtml, and several included files. Below are fragments of code from the main page and two of the included files:
Code in option1.xhtml:
<h:inputText size="4" maxlen="5" id="teff1" value="#{option1.teff1}">
<f:validateDoubleRange minimum="#{option1.teff1Min}" maximum="#{option1.teff1Max}"
disabled="#{simulator.validate}"/>
</h:inputText>
Code in abundances0.xhtml that is included in option1.xhtml:
<h:selectOneMenu id="abundanceSet0" value="#{abundance.abunSet0}" style="height:25px; width:180px;">
<f:selectItems value="#{abundance.abunSetMap}"/>
</h:selectOneMenu>
<p:spacer width="37" height="0"/>
<p:commandButton value="Select Set" actionListener="#{abundance.selectSet0}" update="abundances0"/>
Code in footerButtons.xhtml that is included in option1.xhtml:
<h:message for="teff1" style="color:red"/>
<h:commandButton value="Submit" disabled="#{!login.loggedIn}" action="#{simulator.submit}" onclick="resetForm()"
actionListener="#{simulator.validate}" class="button"/>
The fragments of code from the corresponding beans are here:
MyOption1Bean:
#ManagedBean(name="option1")
#SessionScoped
public class MyOption1Bean implements Serializable {
// Lots of other private variables and objects
private String teff1;
private String teff1Min;
private String teff1Max;
// Option 1 constructor to initialze limits
public MyOption1Bean() {
ResourceBundle bundle = ResourceBundle.getBundle("com.csharp.validation");
teff1Min = bundle.getString("teff1Min");
teff1Max = bundle.getString("teff1Max");
}
public String getTeff1() {
return teff1;
}
public void setTeff1(String teff1) {
this.teff1 = teff1;
}
// Lots of getters, setters, methods, etc.
}
MyAbundanceBean:
#ManagedBean(name="abundance")
#SessionScoped
public class MyAbundanceBean implements Serializable {
// Lots of other private variables and objects
public String getAbunSet0() {
return abunSet[0];
}
public void setAbunSet0(String abunSet) {
this.abunSet[0] = abunSet;
}
public Map<String,String> getAbunSetMap() {
return abunSetMap;
}
public void selectSet0(ActionEvent e) {
selectSet(0);
}
// Lots of getters, setters, methods, etc.
}
MySimulatorBean:
#ManagedBean(name="simulator")
#SessionScoped
public class MySimulatorBean implements Serializable {
// Lots of other private variables and objects
private boolean validate;
// When validate is true disabled is false so validation takes place.
public boolean isValidate() {
return !validate;
}
// When navigating away from the home page to one of the options, reset the error
// and validate flags.
public void resetError(ActionEvent event) {
error = false;
validate = false;
}
// On clicking "Submit" this enables the validate flag.
public void validate(ActionEvent event) {
validate = true;
}
// On clicking "Submit" this gets the user's input, and if succesful sends it to an output file then
// navigate to a "Success" page, otherwise return to the original page.
public String submit() {
// Code to check for errors and output data to a file.
}
// Lots of getters, setters, methods, etc.
}
In option1 (the xhtml and the bean files) the user enters a value for teff1, which must be between teff1Min and teff1Max, which are obtained from a properties file. This works correctly, and if a value for teff1 is not given or is out of range, on clicking the "Submit" button, as given in the footerButtons.xhtml, the submit fails and and the <h:message/> tag displays an error.
However, before clicking "Submit", if the input field for teff1 is empty or has a wrong value,
the <p:commandButton value="Select Set" .../> in the included abundances0.xhtml does not work. It is supposed to update a display with a chosen menu, which otherwise it does. I set the immediate
attribute of <p:commandButton value="Select Set" /> to true, but it still does not work. I only want the validation to take place when the "Submit" button is clicked, and nothing else.
I tried an alternative way: where the flag validate in the simulator bean is used to disable the validation until it is wanted. Namely, when the option1 page is visited it is false, to disabled is true, and no validation is done until the submit button is clicked, at which point it is set to true, so disabled is false. Unfortunately, this dose not work, as JSF thinks the page is valid and navigates away from it before validation is performed. This is in spite of the fact that validate() is executed before submit() in the simulator bean. This is confirmed by inserting a print statement in each of them.
Does anybody have any idea as to what is going on?, and is there an easy way of making sure that validation only takes place when the submit button is clicked? Otherwise the display is locked up, and I'm unable to make the other buttons work.
Many thanks for the clarification, and I did exactly what you suggested. I did the following:
First I put immdiate="true" in the command button that selects a menu in my abundances0.xhtml file:
<p:commandButton value="Select Set" actionListener="#{abundance.selectSet0}" update="abundances0" immediate="true"/>
then I changed the action in my abundance bean java file:
public void selectSet0(ActionEvent e) {
selectSet(0);
FacesContext.getCurrentInstance().renderResponse();
}
but it still does not work. If I click the button nothing happens unless a valid value is already in the input field for teff1 in the option1.xhtml file at the beginning. I need this button to work, together with other ones like it, regardless of what is in the input field, until the submit button is clicked. As far as I can see, I am doing everything correctly.
Icidentally, I'm using JSF 2.0 with PrimeFaces 3.4.2 and Eclipse Indigo.
The <p:commandButton> processes by default the entire form, as in process="#form".
You need to tell it to process only itself, as in process="#this".
<p:commandButton ... process="#this" />
This way all input components in the same form won't be processed (converted/validated/updated).
First of all, validation in JSF is performed in one of the Faces lifecycle, to be more specific, it's done at PROCESS_VALIDATIONS phase. The only way to skip validation is to instruct the Faces' lifecycle to skip that phase.
In JSF input & command components have an immediate attribute, which means that those with a true value for it will be processed during the APPLY_REQUEST_VALUES phase, instead of going through the whole Faces' lifecycle.
Behaviour is slightly different depending of the type of component:
input components with immediate="true" will be validated at APPLY_REQUEST_VALUES phase instead of the PROCESS_VALIDATION one.
command components with immediate="true" will be executed at APPLY_REQUEST_VALUES phase instead of the INVOKE_APPLICATION one.
So, to skip validation, a possible approach would be to have a <h:commandButton /> with immediate="true" and then, at the backing bean side invoke either FacesContext.getCurrentInstance().renderResponse() or FacesContext.getCurrentInstance().requestComplete() to tell Faces to skip the remaining lifecycle phases.
So, in your select0 method should be:
public void selectSet0(ActionEvent e) {
selectSet(0);
FacesContext.getCurrentInstance().renderResponse(); // skip the remaining phases and go straight to RENDER_RESPONSE
}
NOTE: Bear in mind that when submitting a form with an immediate command will trigger the validation in all of the immediate inputs of that form.

strange jsf panelgroup binding -> h:selectOneMenu validation Exception

lets start simple:
- an easy search form
- two h:selectOneMenu components are declared inside a form
- the second selectOneMenu, is refreshed base on selecting an item of the first selectOneMenu (with ajax)
For this, i use a central Bean in request scope, because the two selectOneMenus are declared on many other pages, so i dont need to define the two following methods multiple times:
pageSupport:
#SuppressWarnings("unchecked")
public List<BranchenRubrik> getLst_branchenRubrik() {
if(lst_branchenRubrik == null) {
Session session = hibernate.InitSessionFactory.getInstance().getCurrentSession();
Transaction tx = session.beginTransaction();
this.lst_branchenRubrik = session.createQuery("from BranchenRubrik").list();
tx.commit();
}
return lst_branchenRubrik;
}
// Loading Subkats with parameter
#SuppressWarnings("unchecked")
public List<BranchenRubrikSub> getBranchenRubrikSub(long p_parent) {
List<BranchenRubrikSub> lst_branchenRubrikSub = new ArrayList<BranchenRubrikSub>();
if(p_parent > 0) {
Session session = hibernate.InitSessionFactory.getInstance().getCurrentSession();
Transaction tx = session.beginTransaction();
lst_branchenRubrikSub = session.createQuery("from BranchenRubrikSub BRS WHERE BRS.parentRubrik.id = :p1").setLong("p1",p_parent).list();
tx.commit();
}
return lst_branchenRubrikSub;
}
VDL:
<p:selectOneMenu value="#{searchBean2.fvz.branchenRubrikID}">
<f:selectItem itemLabel="Bitte wählen" itemValue="0"/>
<f:selectItems value="#{pageSupport.lst_branchenRubrik}" var="rubrik" itemValue="#{rubrik.id}" itemLabel="#{rubrik.rubrik}"/>
<f:ajax render="uiBranchenSubKat"/>
</p:selectOneMenu>
<h:outputText value="Unterkategorie" />
<p:selectOneMenu id="uiBranchenSubKat" value="#{searchBean2.fvz.branchenRubrikSubID}">
<f:selectItems value="#{pageSupport.getBranchenRubrikSub(searchBean2.fvz.branchenRubrikID)}" var="brs" itemLabel="#{brs.rubrik}" itemValue="#{brs.id}"/>
</p:selectOneMenu>
this works fine, i can submit the form and all data are saved and will be re-displayed.
Now, i want to include an h:panelGroup with binding to a methode, which build a pagination menue.
If i include the h:panelGroup binding="#{searchBean2.paginationMenu}"/> then, i cant submit the form, because it says that the value for the second h:selectOneMenu is not valid.
if i remove the "h:panelGroup binding" all working as expected.
The h:panelgroup can also binded to an empty methode "return new HtmlPanelGroup()"
then, the error occurs again.
looks like, that the component binding, breaks some validation.
thanks for your time

<f:validator disabled flag not working

I've created a custom validator for my project, it simply checks the select ones value and 'validates' the value is not '0'. We have a standard (I'm sure not uncommon) of manually setting the first value of our selectOneMenu compents to:
<f:selectItem itemValue="0"
itemLabel="-- Select One --"/>
Which works fine, but then makes the component always pass the required check. So this validator simply treats this value as if there was no selection made.
SelectOneMenu example:
<h:selectOneMenu id="eligibility"
value="#{reg.eligibility}"
required="#{reg.fieldsRequired}">
<f:selectItem itemValue="0"
itemLabel="-- Select One --"/>
<f:selectItems value="#{reg.eligibilityList}" />
<f:validator validatorId="selectOneValidator"
disabled="#{!reg.fieldsRequired}"/>
Custom Validator:
#FacesValidator("selectOneValidator")
public class SelectOneValidator implements Validator {
#Override
public void validate(FacesContext context, UIComponent uiComponent, Object o) throws ValidatorException {
String val = null;
if (uiComponent instanceof HtmlSelectOneMenu) {
HtmlSelectOneMenu oneMenu = (HtmlSelectOneMenu) uiComponent;
if (oneMenu.isRequired() && !oneMenu.isDisabled()) {
if (o instanceof String) {
val = (String) o;
} else if (o instanceof Number) {
val = String.valueOf(o);
}
if ("0".equals(val)) {
FacesMessage msg = new FacesMessage();
msg.setSummary("Please select a value from the list.");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg);
}
}
}
}
}
This has worked just fine thus far, however, the current use-case I'm running into trouble.
My page has multiple SelectOneMenus one of which toggles the required and disabled attributes via an ajax call for the page. I'm not having any issues with the required="#{reg.fieldsRequired}", however; the disabled="#{!reg.fieldsRequired}" attribute on my custom validator does not seem to make a difference. I'm just thinking out loud, but when the page first loads the #{reg.fieldsRequired} expression is false. If I then change the SelectOneMenu to set this boolean value to true, then press the submit button, the disabled attribute doesn't seem to have been set. I wondered if this is simply a ajax issue and that all of components simply needed to be re-renderd so I added the #form in my ajax call: <a4j:ajax render="#form" listener="#{reg.saveActionChanged}"/> in hopes that would fix the problem, but no difference in the behavior.
Environment:
JSF 2.0.3
Tomcat 6.0.14
ajax call being made with RichFaces 4.0
Any help is most appreciated!
Sorry, I can't reproduce your problem with JSF 2.1.3. The <f:validator disabled> works as expected.
However, as a completely different alternative, you can in this particular case just make use of the standard required validator. You only need to set the item value to #{null} instead of 0.
<f:selectItem itemValue="#{null}" itemLabel="-- Select One --"/>
This way you don't need the custom validator. The message can be set as requiredMessage attribute of the input component.
<h:selectOneMenu requiredMessage="Please select a value from the list.">

Value remains in form field after it is cleared in bean in JSF2

In my JSF2 application, I have "Clear" button, which is supposed to clear all the fields. However, it doesn't always work.
My page fragment:
<h:form id="bi">
<h:inputText value="#{bean.entity.firstname}" />
<h:inputText value="#{bean.entity.surname}" />
<h:commandButton value="Clear" immediate="true" action="#{bean.clear}">
<f:ajax render="bi" />
</h:commandButton>
<h:commandButton value="Submit" action="#{bean.submit}" />
</h:form>
And clear() method in my bean:
public void clear() {
entity = new Entity();
}
If I enter values in the fields, and click "Clear", everything is cleared as expected. However, consider such scenario:
1. Enter value only in one field (both are required by JSR303 annotations on entity).
2. Click "Submit". Error message appears.
3. Click "Clear".
Entered value remains. Why is it not cleared?
Moreover, if I clear it by hand, and click "Clear", it returns to the field. I checked that it comes to the browser in partial response after clicking "Clear" button. I suspect it has something to do with view state.
Moreover, if I add validator="#{bean.validate}" to the field, it enter this validation. Even if button has immediate="true" attribute. Why? Shouldn't immediate button ommit validation?
You've run into a more or less well-known issue regarding updating components for which validation has already happened.
This post is rather old, but still relevant: http://ishabalov.blogspot.com/2007/08/sad-story-about-uiinput.html
There is a community created solution for A4J in JSF 1.2 posted here: http://community.jboss.org/thread/8446?start=15&tstart=0
But unfortunately, this doesn't work directly in JSF 2.0 and in your case it wouldn't work at all since it's A4J specific. Nevertheless it might be a source of inspiration.
Basically you need to walk the component tree and clear its state. The neatest thing is to clear exactly the state of the components that you are going to re-render. But you might take the brute-force approach and just clear all if your particular application or page can tolerate that.
I wound up having to avoid submit or action to get the form to clear properly. I used actionListener with a void bean method instead.
But then I faced the problem of conditionally needing navigation which is usually done with a String method from action. I used ExternalContext.redirect() to accomplish that which I learned from the following:
JSF PostConstruct Exception Handling - Redirect
JSF navigation redirect to previous page
my page code:
<p:commandButton value="Login" update=":loginForm"
actionListener="#{loginBean.login}"/>
my bean code:
public void login() {
RtsLDAPAD laLdap = new RtsLDAPAD();
boolean lbAuthenticated = false;
try
{
lbAuthenticated = laLdap.login(userName, password);
System.out.println(
"The Result is " + lbAuthenticated + " for " + userName);
}
catch (Exception aeRTSEx)
{
aeRTSEx.printStackTrace();
}
if (lbAuthenticated) {
try {
FacesContext.getCurrentInstance().getExternalContext().redirect("taskform.jsf");
} catch (IOException e) {
e.printStackTrace();
}
} else {
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.addMessage(null,
new FacesMessage("Login failed for " + userName + "."));
UIViewRoot uiViewRoot = facesContext.getViewRoot();
HtmlInputText inputText = null;
Password pwd = null;
inputText = (HtmlInputText) uiViewRoot.findComponent("loginForm:username");
inputText.setSubmittedValue(null);
inputText.setValue(null);
inputText.setLocalValueSet(false);
inputText.setValid(true);
pwd = (Password) uiViewRoot.findComponent("loginForm:password");
pwd.setSubmittedValue(null);
pwd.setValue(null);
pwd.setLocalValueSet(false);
pwd.setValid(true);
userName = null;
password = null;
}
}

Resources