I think my solution has been incorrectly mistaken with the solution of another question. It has also been edited so it looks like the solution is the one pointed by the duplicate, but this obviously did not solve my problem, just avoided the exception raised (the surface of the problem). Since my efforts to reopen the question have been useless, I have opened a new one here.
I am getting a ConcurrentModificationException
and I am not able to solve this problem. So I remove a series of elements from a list and I get an error.
This is the error:
04-Nov-2016 15:49:50.488 SEVERE [http-nio-8080-exec-199] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [Faces Servlet] in context with path [/...] threw exception [java.util.ConcurrentModificationException] with root cause
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:886)
at java.util.ArrayList$Itr.next(ArrayList.java:836)
at com.ex.PersonController.removeGroup(...)
at ....
The Java code:
public void removeGroup(int age) {
if (person != null) {
List<Person> friends = person.getFriends();
List<Person> removeFriends = new ArrayList<>();
if (friends != null) {
for (Person p : friends) {
if (p.getAge() == age) {
removeFriends.add(p);
}
}
friends.removeAll(removeFriends);
}
}
EDIT: Note that this apparently is not solving my problem. It avoids raising an error, though, but the results displayed by JSF are not correct. Is it possible that JSF is trying to refresh while my list is not fully updated?
EDIT2: I don't think this is a duplicate. The error I got with some of my tests is gone with this or this (note that even with the .add() approach I got the same error for some reason). But JSF is still not printing what I expect. I write again the code that BalusC removed from my question with a bit more of information:
The xhtml Java code:
<c:forEach items="#{personController.groupedPersons}" var="personG">
<h:commandButton action="#{personController.removeGroup(personG.key)}" type="submit" value="Remove" >
<f:ajax render="@form" />
</h:commandButton>
#{personG.key} - #{personG.value.size()}
</c:forEach>
So the first time I execute the page, personController.groupedPersons
returns the right list of persons (a HashMap<Integer, List<Person>>
) and prints it just fine. At this point I have 2 groups: a group of 3 Person of the same age and another Person with a different age. When I click on remove the group of the 3 persons with the same age, I trace the code and with the Iterator it removes all the necessary persons without raising a ConcurrentModificationException
. The returned list of person.getFriends();
is size = 1, which is correct. Then the ajax code renders the form. personController.groupedPersons
is called again and returns 1 person as expected. I have verified and this is the return person I actually expect. But then the JSF does print the wrong #{personG.key}
(the one I removed) and null #{personG.value.size()}
.
I know it might be difficult to follow, but can you think of any explanations for this?
EDIT 3:
This is even funnier... If I delete the group that has 1 person, it is removed and then the JSF prints correctly the group with 3 persons. If I delete the group with 3 persons, they are removed and JSF prints (as I said in EDIT2) the key
of the group I just removed and size() is null. Is it possible that I am on a concurrency problem here between JSF refreshing the page at the same time as I am modifying the list? (this was originally my worry, that the ConcurrentModificationException
came from a concurrency problem between the XHTML and my managed bean, and not only within the code of the Managed Bean). That could explain why I got a ConcurrentModificationException
even when I added in the list instead of removing from it.