Vaadin 7 ConcurrentModificationException while updating Grid from other thr

Hi,

I’ve been struggling with this issue for a couple of days now. It happens occasionally when users are added or removed from Grid using methods grid.getContainerDataSource().removeItem(user) or grid.getContainerDataSource().addItem(user). My project is set up with Vaadin CDI so the View containing the Grid is a @CDIView and it implements BroadcastListner interface as described here https://vaadin.com/docs/v8/framework/articles/BroadcastingMessagesToOtherUsers.html When I add a new user a service method responsible for adding a user to database is invoked. If transaction succeeds Broadcaster broadcasts a notification so that other user can see the changes.
It is implemented like that:

	public void onUserAdded(@Observes(during=TransactionPhase.AFTER_SUCCESS) UserAddedEvent evt) {
		Broadcaster.broadcast(new UserAddedNotification(evt.getUserId(), evt.getUsername(), evt.getPassword()));
	}
	
	public void onUserDeleted(@Observes(during=TransactionPhase.AFTER_SUCCESS) UserDeletedEvent evt) {
		Broadcaster.broadcast(new UserDeletedNotification(evt.getUserId()));
	}

And in the view that is supposed to receive the notification I have:

	@Override
	public void receiveBroadcast(AbstractNotification notification) {
		getUI().access(() -> {
			if (notification instanceof UserChangedNotification) {
				updateUsersGrid((UserChangedNotification) notification);
			}
		});
	}

UserAdded and UserDeleted notifications inherit from UserChangedNotification and the method updateUsersGrid has the logic for adding or deleting items from Grid.
In the Broadcaster I am using a SingleThreadExecutor as suggested, the static method broadcast(AbstractNotification notification) is synchronized and the code in the View is enclosed in UI.access(). I’ve been experimenting with manual locking like VaadinSession.getCurrent().getLockInstance().lock() but with no success. I have assertions enabled on my server, but i don’t get any AssertionError when exception happens. From time to time when I add/delete a user a ConcurrentModificationException is thrown with a following stacktrace:

21:37:15,814 ERROR [org.jboss.threads.errors]
 (default task-3) Thread Thread[default task-3,5,main]
 threw an uncaught exception: java.lang.RuntimeException: java.util.ConcurrentModificationException
	at io.undertow.servlet.spec.ServletContextImpl.invokeRunnable(ServletContextImpl.java:1029)
	at io.undertow.servlet.spec.AsyncContextImpl.onAsyncComplete(AsyncContextImpl.java:614)
	at io.undertow.servlet.spec.AsyncContextImpl.access$100(AsyncContextImpl.java:73)
	at io.undertow.servlet.spec.AsyncContextImpl$3.run(AsyncContextImpl.java:316)
	at io.undertow.servlet.spec.AsyncContextImpl$6.run(AsyncContextImpl.java:485)
	at io.undertow.servlet.spec.AsyncContextImpl$TaskDispatchRunnable.run(AsyncContextImpl.java:604)
	at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.util.ConcurrentModificationException
	at java.util.HashMap$HashIterator.nextNode(HashMap.java:1442)
	at java.util.HashMap$KeyIterator.next(HashMap.java:1466)
	at io.undertow.servlet.util.IteratorEnumeration.nextElement(IteratorEnumeration.java:44)
	at org.atmosphere.cpr.AtmosphereRequest.getAttributeNames(AtmosphereRequest.java:1049)
	at org.jboss.weld.module.web.context.beanstore.http.RequestBeanStore.getAttributeNames(RequestBeanStore.java:47)
	at org.jboss.weld.contexts.beanstore.AttributeBeanStore.getPrefixedAttributeNames(AttributeBeanStore.java:239)
	at org.jboss.weld.contexts.beanstore.AttributeBeanStore.fetchUninitializedAttributes(AttributeBeanStore.java:120)
	at org.jboss.weld.contexts.beanstore.AttributeBeanStore.attach(AttributeBeanStore.java:107)
	at org.jboss.weld.module.web.context.http.HttpRequestContextImpl.associate(HttpRequestContextImpl.java:65)
	at org.jboss.weld.module.web.context.http.HttpRequestContextImpl.associate(HttpRequestContextImpl.java:41)
	at org.jboss.weld.module.web.servlet.HttpContextLifecycle.requestInitialized(HttpContextLifecycle.java:243)
	at org.jboss.weld.module.web.servlet.WeldInitialListener.requestInitialized(WeldInitialListener.java:152)
	at io.undertow.servlet.core.ApplicationListeners.requestInitialized(ApplicationListeners.java:246)
	at io.undertow.servlet.spec.AsyncContextImpl.setupRequestContext(AsyncContextImpl.java:706)
	at io.undertow.servlet.spec.AsyncContextImpl.access$700(AsyncContextImpl.java:73)
	at io.undertow.servlet.spec.AsyncContextImpl$7.run(AsyncContextImpl.java:619)
	at io.undertow.servlet.spec.ServletContextImpl$2.call(ServletContextImpl.java:181)
	at io.undertow.servlet.spec.ServletContextImpl$2.call(ServletContextImpl.java:178)
	at io.undertow.servlet.spec.ServletContextImpl.invokeRunnable(ServletContextImpl.java:1027)
	... 10 more

At this point I don’t know how this can be solved. The app is run on Wildfly 17 and my UI class is annotated with @Push(transport = Transport.WEBSOCKET_XHR). Without using @Push the exception is gone, but the Grid is obviously not updated instantly. Can some Vaadin expert provide support please?

I think your exception happends due this issue https://github.com/Atmosphere/atmosphere/issues/2277

Multiple requests may be processed by different threads accessing the same attribute list

https://github.com/vaadin/atmosphere/blob/2.2.13/modules/cpr/src/main/java/org/atmosphere/cpr/AtmosphereRequest.java#L1049

The newer version of Atmosphere is fixed to process them synchronized

https://github.com/vaadin/atmosphere/blob/2.4.30/modules/cpr/src/main/java/org/atmosphere/cpr/AtmosphereRequestImpl.java#L899

Unfortunately this fix is not included in version that is used in Vaadin 7. Vaadin 8 uses 2.4.30, so it is not affected.

Thank you very much for your response. Assuming that this is my issue, if I understood correctly I would have to upgrade Atmosphere or migrate my project to Vaadin 8. Not sure which option is easier, but I found an article about migrating from Vaadin 7 to 8 https://vaadin.com/docs/v8/framework/migration/migrating-to-vaadin8.html so I think I’ll try this one.

Yes, upgrading Atmosphere in Vaadin 7 is not trivial, there are some API changes in 2.4. series, which would require changes in Vaadin 7 code that integrates it.

I managed to successfully migrate my project to Vaadin 8 and I can confirm that this problem is gone. The issue was intermittent, but for the moment I am not able to reproduce it. Tatu, thank you again for your advice.