3

I know this is a common error, and that there is a lots of questions about it, but I must create new one.

Here is my jsf page:

<h:form id="clientCreatingForm">
    <p:selectOneMenu id="city" value="#{kkmBean.client.address.city}" style="width: 263px;" 
          converter="cityConveter" required="true" requiredMessage="You must choose one city">
          <f:selectItems value="#{kkmBean.cityList}" var="city" itemLabel="#{city.cityName}" itemValue="#{city.cityID}"/>
     </p:selectOneMenu>


     <p:commandButton value="Save client" type="button" onclick="confirm.show()" style="margin-top: 20px; margin-left: 30px; width: 180px;" />
     <p:commandButton value="Reset fields" type="reset" style="margin-top: 20px; margin-left: 30px; width: 180px;"/>

          <p:confirmDialog message="Are you sure, you want to save client?" 
               header="Save client" severity="info" widgetVar="confirm">

               <p:commandButton value="Yes, I am sure." oncomplete="confirm.hide()" 
                                         action="#{kkmBean.saveClient}" update=":warnings" style="font-size: 12px;"/>
               <p:commandButton value="No, I don't!" onclick="confirm.hide()" type="button" style="font-size: 12px;"/>
          </p:confirmDialog>
</h:form>

Here is managed bean:

@ManagedBean(name = "kkmBean")
@SessionScoped
public class CreatingClientManager implements Serializable {

/** Creates a new instance of CreatingClientManager */
public KreiranjeKorisnikaManager() {
    client= new Client();
    client.setAddress(new Address());
    cityList = new LinkedList<City>();
    cityList = Communication.getInstance().getCitySessionBeanRemote().getCities();
  }

private Client client;
private List<City> cityList;

public String startCreatingClent() {

    return "creating-client";
  }

/**
 * @return the client
 */
public Klijent getClient() {
    return client;
  }

/**
 * @param client the client to set
 */
public void setClient(Client client) {
    this.Client = client;
  }

/**
 * @return the cityList
 */
public List<Grad> getCityList() {
    return cityList;
  }

/**
 * @param cityList the cityList to set
 */
public void setCityList(List<City> cityList) {
    this.cityList = cityList;
  }

public String saveClient() {
    System.out.println("i am in saveClient method");
    String message = Communication.getInstance().getClientSessionBeanRemote.saveClient(client);
    FacesContext context = FacesContext.getCurrentInstance();
    kontekst.addMessage(message, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success: ", message));
    return null;
  }
}

And finally converter:

   @FacesConverter(forClass=City.class, value="cityConverter")
   public class CityConverter implements Converter {

   @Override
   public Object getAsObject(FacesContext context, UIComponent component, String value) {
      Integer cityID = Integer.valueOf(value);
      CreatingClientManager kkm = (CreatingClientManager) ((HttpSession)context.getExternalContext().getSession(true)).getAttribute("kkmBean");
      List<Grad> cityList = kkm.getCityList();
      for (int i = 0; i < cityList.size(); i++) {
          City city = cityList.get(i);
          if(city.getCityID().equals(cityID)) {
              System.out.println(city.getCityName());
              return city;
          }
      }
      return null;
  }

  @Override
  public String getAsString(FacesContext context, UIComponent component, Object value) {
      return value.toString();
  }
}

Of course the problem is in selectOneMenu. When I submit form, i got this annoying error.

I was debugging converter and the line before return grad, i print grad.getImeGrada() and everything is fine, the name (Ime) of found city (grad) is printed. Am I missing something?

p.s. Sorry on my English, I hope that you understand what is my problem.

Almost forgot to mention that i override equals and hashCode methods, and i am sure it is ok.

CallanSM
  • 303
  • 2
  • 10
  • 20
  • Programming in English instead of Bosnian or an arbitrary non-English language would make the code much quickier interpretable to the worldwide audience... After reading the code 3 times I gave up (but I could conclude that the `Converter` is bad). At least, the `Validation error: Value not valid` on a `` simply means that the selected value doesn't match any of the available items in the list. Perhaps the `equals()` method of your `Grad` class is broken. This very same kind of answer has been posted in a zillion of questions already. – BalusC Aug 17 '11 at 17:41
  • 1
    @BalusC thank you on your effort. I hope that my code is easier to understand now, when i "translated" it. – CallanSM Aug 17 '11 at 18:33
  • 1
    Much appreciated :) I see the problem. I'll post an answer. – BalusC Aug 17 '11 at 18:47
  • Here is equals method: `@Override public boolean equals(Object object) { if (!(object instanceof City)) { return false; } City other = (City) object; if ((this.cityID == null && other.cityID != null) || (this.cityID != null && !this.cityID.equals(other.cityID))) { return false; } return true; } ` Hope you will handle with code written like this. – CallanSM Aug 17 '11 at 18:50

1 Answers1

10

The way how you specified the itemValue of <f:selectItems> and implemented the getAsString() of the converter is not right.

When the selected value is submitted, JSF will convert the cityID to City by getAsObject() of the converter. Then, JSF will validate the City against the itemValue of the <f:selectItems> to see if it is really part of the list (this is to avoid hackers which modifies/tampers requests with a different value). However, since itemValue is cityID which is an Integer the comparison fails for every item of the list. Hence the Value not valid error.

You need to change itemValue to be City instead and change getAsString() to return the cityID:

<p:selectOneMenu id="city" value="#{kkmBean.client.address.city}" style="width: 263px;" 
      converter="cityConveter" required="true" requiredMessage="You must choose one city">
      <f:selectItems value="#{kkmBean.cityList}" var="city" itemLabel="#{city.cityName}" itemValue="#{city}"/>
 </p:selectOneMenu>

and

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
    City city = (City) value;
    return city.getCityID() != null ? String.valueOf(city.getCityID()) : null;
}

Summarized: the type of the itemValue must be exactly the same as the type of the dropdown value and the converter must convert between exactly that type and string.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Words can not describe how grateful I am to you. I am beginner in jsf, but I didn't expect that problem like this will take two days to me, and you solve it in few minutes. Once more, thank you very, very much. – CallanSM Aug 17 '11 at 19:06
  • @BalusC : I am getting error as `java.lang.String cannot be cast to com.sac.beans` because in `Object getAsObject`, `value` is STRING. How to overcome this? – Fahim Parkar Oct 14 '12 at 11:58
  • @BalusC : Can you take a look at [my question](http://stackoverflow.com/questions/12874394/targetcars-validation-error-value-is-not-valid) – Fahim Parkar Oct 14 '12 at 12:01