2

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
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
user2124871
  • 803
  • 3
  • 9
  • 25

2 Answers2

3

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();
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Ah - THANK you. I'm relatively new to JSF, so I sort of looked over the purpose of those two methods. And your explanation for why I saw what I did makes perfect sense. Much appreciated. – user2124871 Apr 24 '13 at 18:38
  • You're welcome. It's not necessarily related to JSF. It's a fundamental part of basic Java. See also http://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html – BalusC Apr 24 '13 at 18:40
  • Extra PS - Your blogs/entries have been a great addition to my learning. – user2124871 Apr 24 '13 at 18:40
0

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.

schlebe
  • 3,387
  • 5
  • 37
  • 50
  • Better to improve the accepted answer Either by directly adding code or sometimes even better to add references to related Stackoverflow questions. That is all higly appreciated in Stackoverflow. – Kukeltje Sep 06 '18 at 14:43
  • Hell Kukeltje. As you know, I like to talk :-) But I don't undertand the second part and I have some reticences to modify (or complete) the post of another user (as Balus that is very "Balaise" = "strapping in IT" in french). And StackOverflow gamification push me to create another post in expecting to gain some point ;-) Another thing. I like when the answer is short. For this other reason I think it is not interesting to complete BalusC answer. The users can continue to vote for the best answer and some time can vote for me if my example is interesting. This is my point of view. – schlebe Sep 07 '18 at 05:58