views:

630

answers:

2

Hi,

I want to have a facelet page with a formular and a dropdown menu. With the dropdown menu the user shoul select a POJO of the type Lieferant:

public class Lieferant extends AbstractPersistentWarenwirtschaftsObject {

    private String firma;

    public Lieferant(WarenwirtschaftDatabaseLayer database, String firma) {
        this(database, null, firma);
    }

    public Lieferant(WarenwirtschaftDatabaseLayer database, Long primaryKey, String firma) {
        super(database, primaryKey);
        this.firma = firma;
    }

    public String getFirma() {
        return firma;
    }

    @Override
    public String toString() {
        return getFirma();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((firma == null) ? 0 : firma.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Lieferant other = (Lieferant) obj;
        if (firma == null) {
            if (other.firma != null)
                return false;
        } else if (!firma.equals(other.firma))
            return false;
        return true;
    }

}

Here is the facelet code that I wrote:

<h:selectOneMenu> 

tag. This tag should display a list of POJOs (not beans) of the type Lieferant. Here is the facelet code:

<h:selectOneMenu id="lieferant" value="#{lieferantenBestellungBackingBean.lieferant}">
 <f:selectItems var="lieferant" value="#{lieferantenBackingBean.lieferanten}" itemLabel="#{lieferant.firma}" itemValue="#{lieferant.primaryKey}" />
 <f:converter converterId="LieferantConverter" />
</h:selectOneMenu>

Here is the refenrenced managed backing bean

@ManagedBean
@RequestScoped
public class LieferantenBackingBean extends AbstractWarenwirtschaftsBackingBean {

    private List<Lieferant> lieferanten;

    public List<Lieferant> getLieferanten() {
        if (lieferanten == null) {
            lieferanten = getApplication().getLieferanten();
        }
        return lieferanten;
    }

}

As far as I know, I need a custom converter, to swap beetween POJO and String representations of the Lieferant objects. Here is what the converter looks like:

@FacesConverter(value="LieferantConverter")
public class LieferantConverter implements Converter {

 @Override
 public Object getAsObject(FacesContext context, UIComponent component, String value) {
  long primaryKey = Long.parseLong(value);
  WarenwirtschaftApplicationLayer application = WarenwirtschaftApplication.getInstance();
  Lieferant lieferant = application.getLieferant(primaryKey);
  return lieferant;
 }

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

}

The page loads without any error. When I fill out the formular and submit it, there is an error message displayed on the page:

Bestellung:lieferantenBestellungForm:lieferant: Validierungsfehler: Wert ist keine gültige Auswahl
translated: validation error: value is not a valid selection

Unfortunaltely it does not say which value it is talking about. The converter seems to work correctly.

I found this similar question from stackoverflow and this article about selectOneMenu and converters, but I was not able to find the problem in my code. Why is

List<SelectItem> 

used in the example from the second link. Gives the same error for me.

Any help would be appreciated. Thanks in advance.

+1  A: 

validation error: value is not a valid selection

This error means that the selected item does not match any of the select items in the list. In your case this can have two causes: either Object#equals() is wrongly implemented, or the getter behind <f:selectItems> doesn't return the same list in the subsequent request (during submitting the form) as it did during the initial request (before submitting the form, during selecting the value).

To exclude the one or other: you can easily test Object#equals() with a "plain vanilla" testcase and you can test the consistency of the list by putting the bean in session scope.

To be clear, your converter looks fine and seems to work fine (else you wouldn't be able to get this kind of error message; the conversion step was thus completed successfully).

BalusC
Thanks for answering. I fixed it in the meanwhile on my own.
c0d3x
You're welcome.
BalusC
A: 

I was realy shure that the converter was working correctly, but the final error was in the converter. Maybe this happened someway during hours of debugging. Here is the fixed getAsString method of the converter. N

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
    if (value != null && value instanceof Lieferant) {
        Lieferant lieferant = (Lieferant) value;
        return "" + lieferant.getPrimaryKey();
    }
    return "";
}

Now it returns the primaryKey which is used as the value of the selectOneMenu list. Additionally I changed this attribute from the selectItems tag:

 itemValue="#{lieferant}"

Right now I am not shure if this last change was neccessary. But now the lieferants are converted correctly.

c0d3x