selectOneMenu shows after submit always the last i

2019-07-20 01:16发布

问题:

Info

  • JSF 2.0
  • Primefaces 3.4
  • Both objects are People objects

I have a simple drop down menu that is contained within a form that submits the selection on form submit (AJAX call):

<h:form>

....

                    <p:selectOneMenu converter="personconverter"
                        value="#{searchperson.viewPerson.relatedTo}" filter="true"
                        filterMatchMode="startsWith">
                        <f:selectItems value="#{searchperson.people}" var="person"
                            itemLabel="#{person.fullName}" itemValue="#{person}" />
                    </p:selectOneMenu>
....
                    <p:commandButton value="Save"
                        actionListener="#{searchperson.updatePerson}" />
</h:form>

When I submit the request to the server, the object tied to the selectOneMenu is passed correctly AND I am able to update my backend with this change.

When the page is re-rendered, the value in p:selectOneMenu:

(value="#{searchperson.viewPerson.relatedTo}")

Does not render the new change that was JUST submitted. It renders the last Person object in the people list.

Here are the other pieces:

Converter:

@FacesConverter("personconverter")
public class PersonConverter implements Converter {

@Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String value) {

    People pApi = new People();
    Person per = new Person();

    try {
        per = pApi.getPerson(Long.parseLong(value));
    }
    catch(Exception e) {
        e.printStackTrace();
    }
    return per;
}

@Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {

    return String.valueOf(((Person) arg2).getId());
}

}

Object class

@Override
public boolean equals(Object object) {
    return true; //just to pass through temporarily
}

@Override
public int hashCode() {
    return 0;
}

face-config.xml

<converter>
    <converter-for-class>com.obj.Person</converter-for-class>
    <converter-class>com.converter.PersonConverter</converter-class>
</converter

回答1:

Your implementations of equals() and hashCode() are severely broken. This way every instance of Person is considered equal with each other and hence JSF won't be able to identify the right selected item based on the list of available items. You must implement them at least according their contracts.

Fix it accordingly, given that it has an id property representing the unique identifier:

@Override
public boolean equals(Object other) {
    return (id != null && other != null && getClass() == other.getClass())
         ? id.equals(((Person) other).id)
         : (other == this);
}

@Override
public int hashCode() {
    return (id != null) 
         ? (getClass().hashCode() + id.hashCode()) 
         : super.hashCode();
}


回答2:

I know that BalusC is the best answer to resolve this question; but I have encountered same problem and I will only explain it to help other to understand the problem by example.

Before corrected it, I use following Java server code

@Override
public boolean equals(Object o) 
    {
    if (this == o) return true;
    if (getClass() != o.getClass()) return false;

    if (o == null)
        {
        return (nId == null);
        }

    PostLabellingMeetingEntity that = (PostLabellingMeetingEntity) o;

    if (nId == null)
        {
        return (that.nId == null);
        }

    return (!nId.equals(that.nId));
    }

With error not corrected, I can use SelectOneMenu to select an item; but after saving the page and displaying it again, the saved item is nver displayed and last item of the list is always displayed.

The error is simply that I have only a "!" in return statement that is totally incorrect.

I replace it by

//2018-09-04:BS: big BUG
//return (!nId.equals(that.nId));
return (nId.equals(that.nId));

and my problem has been solved :-)

In resume: a bad character can bug completly an application even some parts of widget continue to work correclty.