I’m adding features to my competition management application, and I’ve recently run into a new kind of error.
Does anyone have any idea of what could be causing this ? I’m doing some pretty funky stuff, such as having events go to several Applications, and relying on the progress indicator hack (I have a countdown timer update every half second), but I fail to see any causal link.
The problem is intermittent (occurs every once in a while).
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at com.vaadin.terminal.gwt.server.CommunicationManager.getDirtyVisibleComponents(CommunicationManager.java:1223)
at com.vaadin.terminal.gwt.server.CommunicationManager.paintAfterVariablechanges(CommunicationManager.java:401)
at com.vaadin.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:314)
at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:425)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:568)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Unknown Source)
I’m not sure about this, but it looks like you’re updating the state of components while they are being “painted” (sent) to the client. This can happen if you update UI components from different threads and don’t synchronize on your Application object.
If it is the case that you’re using multiple threads, make sure that you synchronize on your Application instance before making the changes.
ConcurrentModificationException occurs when modifying a collection in one thread while it is being iterated in another. In this case, it seems the collection in question is the set of dirty paintables and the modification is likely to take place in CommunicationManager.repaintRequested().
CommunicationManager synchronizes its accesses to the Application instance. Check what access to UI components you background thread is doing (e.g. directly or indirectly calling requestRepaint() or setVisible()) and synchronize such accesses to the Application instance.
Yup. did a little test. this code causes a ConcurrentModificationException.
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
String a = "a";
String b = "b";
String c = "c";
String d = "d";
list.add(a);
list.add(b);
list.add(c);
list.add(d);
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String string = it.next();
if (string.equals("b")) {
list.remove(c);
}
}
}
Anyhow, back to the real topic - I guess Jonatan is right. Vaadin is iterating the components in some paint function, which triggers your code and does changes to the components. Listeners can do this.
Depending on what this means exactly, it might be the culprit…
For instance, attaching listeners to some instance that’s shared between application instances (e.g. static Container) might cause this. The reason/fix is the one mentioned already: synchronize using the application instance before touching UI stuff.
Do you think something like this might be the cause?
Jens’ example is a common mistake, the proper way to remove from a list is to call the remove method of the iterator which is provided for that purpose. Unfortunately there is no corresponding “iterator.add” that I know of.
Sync on application is likely the way to go; I probably have useless leftover requestRepaint requests from when I was trying to figure things out as well. Will keep you posted.
Awesome support from the forums, again. My countdown stopwatch thread was updating a label and requesting repaint. Have not seen reoccurrence of problem after adding a synchronization point around my request to repaint.