0

I have simplify my problem as much as possible. Basically, a Map is not been printed correctly after I make some modifications on it.

I have the following xhtml code:

<c:forEach items="#{personController.groupedPersons}" var="personG">
    <p>
        <h:commandButton action="#{personController.removePersonGroup(personG.key)}" type="submit" value="Remove">
            <f:ajax render="@form" />
        </h:commandButton>
    </p>
    <p>#{personG.key}</p>
    <p>#{personG.value.size()}</p>
</c:forEach>

This iterates over a Map and prints its information. For each key, there is a button that allows removing it from the Map.

With this code in my personController bean (which is @ViewScoped and implements Serializable):

private HashMap<Integer, List<Person>> groupedPersons;

public void removePersonGroup(Integer age) {
    groupedPersons.remove(age);
}

My testing data has key=20 and 3 values (Person) and key=30 and 1 value (Person). The first time I load the page and print the map it works fine.

  • 1st test: I press the button for the 2nd group (key 30). It removes the group and prints the Map just fine, with the remaining group. Then press the button for the 1st group (key 20). It removes the group and prints the Map just fine, which is empty.
  • 2nd test: I reload the page. I press the button for the 1st group (key 20). My traces shows that removePersonGroup() works fine and groupedPersons has only the single element of key=30. However, when ajax refreshes the form, the XHTML shows #{personG.key} = 20 (which has been removed) and #{personG.value.size()} = null (nothing is shown, the value is empty). What am I doing wrong? I cannot find the problem

UPDATE

After doing the 2nd test and having the wrong deta displayed in the XHTML, when I refresh the form with another button and refresh the whole page, now the XHTML shows the actual data correctly! So there must be something (concurrency related?) that is making the XHTML show the wrong data.

user1156544
  • 1,725
  • 2
  • 25
  • 51
  • An ajax refresh of (parts of) a page does not re-run the c:foreach. See http://stackoverflow.com/questions/3342984/jstl-in-jsf2-facelets-makes-sense. So everything you see is exactly as is should be. Just don't use a c:foreach here – Kukeltje Nov 07 '16 at 18:03
  • I see. I tried but it cannot iterate over Map (I believe this will be possible from JSF 2.3 on). In theory, it makes sense that the c:foreach is not re-run, but the contents are actually modified (!). And in some situations I get the right results (test1 for example), so it is re-run somehow.That is confusing. I will try a custom EL function to try ui:repeat and update this – user1156544 Nov 07 '16 at 18:47
  • no, it is not re-run in test 1 I think. You most likely did not have ajax there and then you get a full page refresh, including a new (albeit the same) view. – Kukeltje Nov 07 '16 at 18:53
  • It is the same code (ajax in both) and with test1 it removes the second element and leaves the 1st one (as expected) and with test2 it shows the first element name with no size. Actually, if I remove ajax I get exactly the same result, only that my scroll goes to the top and the URL is emptied of parameters – user1156544 Nov 07 '16 at 19:22
  • care to create an [mcve] then? – Kukeltje Nov 07 '16 at 21:21

0 Answers0