All child windows remove.

I welcome!

Has faced such problem. There is a panel with tabs and set of floating affiliated windows, the for each tab.

Tab switching should be accompanied, in - the first, removal of all windows “not belonging” to it, and also forming of all of what in its activity have been created earlier.

I try to delete so in the main class inheriting Windows class -


...
Set<Window> childWindows = window.getChildWindows();
for(Window w : childWindows)
   window.removeWindow(w);
...

One window from two successfully leaves, however the others remain and there is an exception:


SEVERE: Terminal error:
com.vaadin.event.ListenerMethod$MethodException
Cause: java.util.ConcurrentModificationException
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:510)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:162)
	at com.vaadin.ui.AbstractComponent.fireEvent(AbstractComponent.java:1166)
	at com.vaadin.ui.TabSheet.fireSelectedTabChange(TabSheet.java:834)
	at com.vaadin.ui.TabSheet.setSelectedTab(TabSheet.java:560)
	at com.vaadin.ui.TabSheet.changeVariables(TabSheet.java:626)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariableBurst(AbstractCommunicationManager.java:1297)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1217)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.doHandleUidlRequest(AbstractCommunicationManager.java:733)
	at com.vaadin.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:296)
	at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:483)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:394)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.util.ConcurrentModificationException
	at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(Unknown Source)
	at java.util.LinkedHashMap$KeyIterator.next(Unknown Source)
	at java.util.Collections$UnmodifiableCollection$1.next(Unknown Source)
	at com.intellex.windows.DashboardWin$1.selectedTabChange(DashboardWin.java:282)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:490)
	... 28 more

I try to delete in a separate stream -


...
public class WndsClearer implements Runnable {
	private Window window;
	
	public WndsClearer(Window window) {
		this.window = window;
	}
	
	public void run() {
		 Set<Window> childWindows = window.getChildWindows();
		 for(Window w : childWindows)
			 window.removeWindow(w);
	}
}

...
WndsClearer c = new WndsClearer(getWindow());
Thread t = new Thread(c);
t.start();
...

Exception:


Exception in thread "Thread-7" java.util.ConcurrentModificationException
	at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(Unknown Source)
	at java.util.LinkedHashMap$KeyIterator.next(Unknown Source)
	at java.util.Collections$UnmodifiableCollection$1.next(Unknown Source)
	at com.intellex.components.WndsClearer.run(WndsClearer.java:16)
	at java.lang.Thread.run(Unknown Source)

What will advise? While wrote, has thought of collections, safe to streams, but the nature of the phenomenon isn’t absolutely clear.
11675.jpg

And hasn’t understood, at what here ConcurrentModificationException…
Has found an alternative variant - to write down windows in HashMap with key, corresponding to this or that bookmark,
and to delete approximately so:


private int tabPosition = -1;
...
if(tabPosition != -1) {					 
   ArrayList windows = (ArrayList)userWorkSpace.get(tabsheet.getTab(tabPosition));
   if(null != windows) for(Object w : windows) removeWindow((Window)w);
...

To restore, accordingly -


...
tabPosition = tabsheet.getTabPosition(tab);

ArrayList windows = (ArrayList)userWorkSpace.get(tab);
if(null != windows) for(Object w : windows) addWindow((Window)w);
...
Vector<Window> wcopy = new Vector<Window>();
Set<Window> childWindows = window.getChildWindows();
for(Window w : childWindows) {
    wcopy.add(w);
}
while(wcopy.size() > 0) {
    window.removeWindow(wcopy.remove(0));
}

I welcome you, Syam.S !

The elegant decision! Thanks!
However why it is not possible to delete a window without intermediate containers?
I used HashMap, you - Vector, result one, but such code -


...
Set<Window> childWindows = getWindow().getChildWindows();				 
for(Window w : childWindows) {
   getWindow().removeWindow(w);
}				 
				 
...

Generates -


08.05.2011 20:30:05 com.vaadin.Application terminalError
SEVERE: Terminal error:
com.vaadin.event.ListenerMethod$MethodException
Cause: java.util.ConcurrentModificationException
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:510)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:162)
	at com.vaadin.ui.AbstractComponent.fireEvent(AbstractComponent.java:1166)
	at com.vaadin.ui.TabSheet.fireSelectedTabChange(TabSheet.java:834)
	at com.vaadin.ui.TabSheet.setSelectedTab(TabSheet.java:560)
	at com.vaadin.ui.TabSheet.changeVariables(TabSheet.java:626)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariableBurst(AbstractCommunicationManager.java:1297)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1217)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.doHandleUidlRequest(AbstractCommunicationManager.java:733)
	at com.vaadin.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:296)
	at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:483)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:394)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.util.ConcurrentModificationException
	at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(Unknown Source)
	at java.util.LinkedHashMap$KeyIterator.next(Unknown Source)
	at java.util.Collections$UnmodifiableCollection$1.next(Unknown Source)
	at com.intellex.windows.DashboardWin$1.selectedTabChange(DashboardWin.java:285)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:490)
	... 27 more

However one window leaves, as it is strange. If to walk around tabs leave all. :smiley:

This is mostly a Java issue rather than a Vaadin issue.
The getChildWindows() here returns either the internal collection of windows or a collection that is backed by it. You should not modify it directly, but it can get modified when you add/remove windows. (Note: you should not trust that this will always be so; some future version may return a copy.)

The enhanced for loop “for (Window w: childWindows)” internally creates an iterator (more accurately an Enumeration, which does not permit any modifications while enumerating), and modifying the collection being iterated will invalidate the iteration. If using an Iterator, modifications may be possible to do through the Iterator (depending on the collection and the iterator implementations).

Whenever using an iteration-based loop and modifying the underlying collection while iterating (either in the loop or from another thread), use a copy of the original list or make the modifications through the iterator.

I welcome you, Henri Sara!

Yes, you are right - iterators from a package java.util generate an exception if the data set has changed after creation of iterator.
Perhaps, it makes sense to return not Set, but data sets from java.util.concurrent?

For example, the code resulted further works:


...
CopyOnWriteArraySet<Window> synchSet = new CopyOnWriteArraySet();
synchSet.addAll(getWindow().getChildWindows());
for(Window w : synchSet) {
   getWindow().removeWindow(w);
}
...

it’s fine! :smiley:

However -


...
Set<Window> synchSet = Collections.synchronizedSet(getWindow().getChildWindows());
synchronized(synchSet) {
   for(Window w : synchSet) {
      getWindow().removeWindow(w);
   }
}
...

will produce ConcurrentModificationException.

You don’t need the extra functionality and overhead from CopyOnWriteArraySet here - e.g. the following does the same much more efficiently:

for(Window w : new ArrayList(getWindow().getChildWindows())) {
   getWindow().removeWindow(w);
}

If you do want to use CopyOnWriteArraySet, you could also give the collection as a constructor parameter.

synchronizedSet() only guards against concurrent modifications by other threads (and you need to synchronize iteration as done in the example), not the same thread.

Whew! Many thanks for the help! :smiley:

Perhaps, so it would be more effective?


ArrayList<Window> arrayList = new ArrayList(getWindow().getChildWindows());
for(Window w : arrayList) {
   getWindow().removeWindow(w);
}

These two versions are exactly the same after compilation (except for some metadata for debugger).

But after parse - absolutely isn’t present :smiley:


for(Window w : new ArrayList(getWindow().getChildWindows())) {
   getWindow().removeWindow(w);
}					 


Type mismatch: cannot convert from element type Object to Window

Should be so -


for(Window w : new ArrayList<Window>(getWindow().getChildWindows()))  {
   getWindow().removeWindow(w);
}