Sunday, 31 March 2013

How to fix “form: xxxxxx: Validation Error: Value is not valid" problem

“form: xxxxxx: Validation Error: Value is not valid"

I got this error message while working on prime-showcase-p342-pm094.  The example was a multi-select case with ajax update.  I updated the primefaces jar to 3.5 and the problem continued.

 I will first provide the troubled example code here.  Than a workout by using the standard JSF2 solution.  Then, I will change the code and provide an othe solution.  As the last solution I will use this approach and return back to primefaces multiselect and ajax solution.  I will do these in two consequent blog entries.

 


 I will provide only the xhtml and java files, you can place them in the starting example that I have provided in the previous blog entry.  Primeshowcase example is ustomized but the logic is the same.

The primefaces multiselect and ajax version that does not work:

 
 

arsSelect.xhtml
--------------------

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      xmlns:h=http://java.sun.com/jsf/html
      xmlns:f=http://java.sun.com/jsf/core
      xmlns:p="http://primefaces.org/ui">
<h:head><title>PrimeFaces ARS Test</title>
</h:head>
<h:body>

<div align="center">

<h1 class="ui-widget-header ui-corner-all" align="center">PrimeFaces ARS Test</h1>
 
<br/>

<p:fieldset legend="Multiple Selects">

<h:form id="form">

    <!-- p:growl id="msgs" showDetail="true"/-->
    <p:messages id="msgs" />
                      
       <p:panel header="Double Combo" style="margin-bottom:10px;">

        <h:panelGrid columns="2" cellpadding="5">

            <p:selectOneMenu id="continent" value="#{arsBean.continent}">

                <f:selectItem itemLabel="Select Continent" itemValue="" />

                <f:selectItems value="#{arsBean.continents}" />

                <p:ajax update="form:countries"

                        listener="#{arsBean.handleContinentChange}" />

            </p:selectOneMenu>

 
            <p:selectOneMenu id="countries" value="#{arsBean.country}">

                <f:selectItem itemLabel="Select Country" itemValue="" />

                <f:selectItems value="#{arsBean.countries}" />

            </p:selectOneMenu>

        </h:panelGrid>

        <p:separator />
          

             <p:commandButton value="Submit" update="msgs" actionListener="#{arsBean.displayLocation}" id="btnSubmit"/>

 
       </p:panel>

</h:form>

</p:fieldset>

<br/>

 
</div>
 
</h:body></html>

ArsBean.java
------------------
package ars.primefaces.ajax;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.bean.ManagedBean;

import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class ArsBean implements Serializable {

                private String continent
                private String country;
            
                private Map<String,String> continents = new HashMap<String, String>();

                private Map<String,Map<String,String>> countryDetailsData = new HashMap<String, Map<String,String>>();              

                private Map<String,String> countries = new HashMap<String, String>();

                public ArsBean() {
                               continents.put("Europe", "Europe");
                               continents.put("Asia", "Asia");
                               continents.put("America", "America");
                           
                               Map<String,String> countryDetailsEurope = new HashMap<String, String>();
                               countryDetailsEurope.put("Germany", "Germany");
                               countryDetailsEurope.put("Britain", "Britain");
                               countryDetailsEurope.put("France", "France");                    

                               Map<String,String> countryDetailsAmerica = new HashMap<String, String>();
                               countryDetailsAmerica.put("US", "US");
                               countryDetailsAmerica.put("Canada", "Canada");
                               countryDetailsAmerica.put("Mexico", "Mexico");                            

                               Map<String,String> countryDetailsAsia = new HashMap<String, String>();
                               countryDetailsAsia.put("Turkey", "Turkey");
                               countryDetailsAsia.put("Russia", "Russia");
                               countryDetailsAsia.put("China", "China");      
                     
                               countryDetailsData.put("Europe", countryDetailsEurope);
                               countryDetailsData.put("America", countryDetailsAmerica);
                               countryDetailsData.put("Asia", countryDetailsAsia);
                }
              
                public String getContinent() {
                               return continent;
                }
 
                public void setContinent(String continent) {
                               this.continent = continent;
                }

                public String getCountry() {
                               return country;
                }

                public void setCountry(String country) {
                               this.country = country;
                }

                public Map<String, String> getContinents() {
                               return continents;
                }

                public void setContinents(Map<String, String> continents) {
                               this.continents = continents;
                }
            
                public Map<String, Map<String, String>> getCountryDetails() {
                               return countryDetailsData;
                }

                public void setCountryDetails(Map<String, Map<String, String>> countryDetailsData) {
                               this.countryDetailsData = countryDetailsData;
                }
              
                public Map<String, String> getCountries() {
                               return countries;
                }

                public void setCountries(Map<String, String> countries) {
                               this.countries = countries;
                }
              
                public void handleContinentChange() {
                              
                               if(continent !=null && !continent.equals(""))
                                               countries = countryDetailsData.get(continent);
                               else
                                               countries = new HashMap<String, String>();
                              
                               country=countries.entrySet().iterator().next().getKey();
                               System.out.println(country);
                               System.out.println(countries);
                }
              
    public void displayLocation() {
        FacesMessage msg = new FacesMessage("Selected", "Continent:" + continent + ", Country: " + country);

        FacesContext.getCurrentInstance().addMessage(null, msg);
    }
}

A turnaround solution using JSF2 original multiselect and AJAX solution worked perfact:

 

 
The basic difference is in the tags and also “AjaxBehaviorEvent evt” as a parameter.  Here is the new code:

arsSelect2.xhtml
----------------------

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      xmlns:h=http://java.sun.com/jsf/html
      xmlns:f=http://java.sun.com/jsf/core
      xmlns:p="http://primefaces.org/ui">

<h:head><title>PrimeFaces ARS Test</title>
</h:head>

<h:body>

<div align="center">

<h1 class="ui-widget-header ui-corner-all" align="center">PrimeFaces ARS Test</h1>

<br/>

<p:fieldset legend="Multiple Selects">

<h:form id="form">

    <!-- p:growl id="msgs" showDetail="true"/-->
    <p:messages id="msgs" showDetail="true"/>
                          
       <p:panel header="Double Combo" style="margin-bottom:10px;">
        <h:panelGrid columns="2" cellpadding="5">
          Continent:
               <h:selectOneMenu id="continent" value="#{arsBean2.continent}">
                 <f:selectItems value="#{arsBean2.continents}"/>
                 <f:ajax render="countries" listener="#{arsBean2.handleContinentChange2}" />
               </h:selectOneMenu>

                    <br/>Country:
                      <h:selectOneMenu value="#{arsBean2.country}"
                                       id="countries">
                        <f:selectItems value="#{arsBean2.countries}"/>
                      </h:selectOneMenu>
        </h:panelGrid>

        <p:separator />
          
             <p:commandButton value="Submit" update="msgs" actionListener="#{arsBean2.displayLocation}" id="btnSubmit"/>

       </p:panel>

</h:form>

</p:fieldset>

<br/>

</div>

</h:body></html>

arsBean2.java
-------------------
package ars.primefaces.ajax;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class ArsBean2 implements Serializable {

                private String continent;
                private String country;
             
                private Map<String,String> continents = new HashMap<String, String>();
 
                private Map<String,Map<String,String>> countryDetailsData = new HashMap<String, Map<String,String>>();
              
                private Map<String,String> countries = new HashMap<String, String>();

                public ArsBean2() {
                               continents.put("Europe", "Europe");
                               continents.put("Asia", "Asia");
                               continents.put("America", "America");
                            
                               Map<String,String> countryDetailsEurope = new HashMap<String, String>();
                               countryDetailsEurope.put("Germany", "Germany");
                               countryDetailsEurope.put("Britain", "Britain");
                               countryDetailsEurope.put("France", "France");
                           
                               Map<String,String> countryDetailsAmerica = new HashMap<String, String>();
                               countryDetailsAmerica.put("US", "US");
                               countryDetailsAmerica.put("Canada", "Canada");
                               countryDetailsAmerica.put("Mexico", "Mexico");
                             
                               Map<String,String> countryDetailsAsia = new HashMap<String, String>();
                               countryDetailsAsia.put("Turkey", "Turkey");
                               countryDetailsAsia.put("Russia", "Russia");
                               countryDetailsAsia.put("China", "China");
                             
                               countryDetailsData.put("Europe", countryDetailsEurope);
                               countryDetailsData.put("America", countryDetailsAmerica);
                               countryDetailsData.put("Asia", countryDetailsAsia);
                }
               
                public String getContinent() {
                               return continent;
                }

                public void setContinent(String continent) {
                               this.continent = continent;
                }

                public String getCountry() {
                               return country;
                }

                public void setCountry(String country) {
                               this.country = country;
                }

                public Map<String, String> getContinents() {
                               return continents;
                }

                public void setContinents(Map<String, String> continents) {
                               this.continents = continents;
                }
            
                public Map<String, Map<String, String>> getCountryDetails() {
                               return countryDetailsData;
                }

                public void setCountryDetails(Map<String, Map<String, String>> countryDetailsData) {
                               this.countryDetailsData = countryDetailsData;
                }
            
                public Map<String, String> getCountries() {
                               return countries;
                }

                public void setCountries(Map<String, String> countries) {
                               this.countries = countries;
                }
             
                public void handleContinentChange2(AjaxBehaviorEvent evt) {
                             
                               if(continent !=null && !continent.equals(""))
                                               countries = countryDetailsData.get(continent);
                               else
                                               countries = new HashMap<String, String>();
                      
                               country=countries.entrySet().iterator().next().getKey();
                               System.out.println(country);
                               System.out.println(countries);
                }
            
    public void displayLocation() {
        FacesMessage msg = new FacesMessage("Selected", "Continent:" + continent + ", Country: " + country);

        FacesContext.getCurrentInstance().addMessage(null, msg);
    }
}

I will provide a solution which uses primefaces multiselect and ajax call in the next blog.