Uncaught client side exception with background thread update

I have an application that was working fine in Vaadin 7 beta6. After updating to beta7, I immediately started getting a “Uncaught client side exception” error. The code in question creates a background thread to load some data when my view is instantiated. The view has a progress indicator which polls every 1 second. When the background thread completes its work, it gets a lock on the session using the code below and then swaps out the progress indicator for the now loaded data in a custom component. It appears that the exception is raised during this swap of the progress bar and the new data component.

The amount of data I’m returning is rather large so it takes a second or two. That makes me think there is some kind of race condition where the progress bar is polling while the background thread has already removed it from the UI. However, that’s what the lock is supposed to prevent, right?

I’m not entirely sure how to debug this given that the client side JS looks obfuscated. Any suggestions?


try {
      uiSession.getLock().lock();

      if (!cancelled)
        doUiUpdate();
    }
    catch (Throwable ex) {
      log.warn("Exception in background worker during "
          + "UI update. Background task may not be complete.", ex);
    }
    finally {
      complete = true;
      uiSession.getLock().unlock();
    }

-mike
12619.png
12620.png

Given that this just started to be a problem with beta7 and it worked in beta6, I’m guessing it is somehow related to http://dev.vaadin.com/ticket/10008 where the ProgressIndicator was modified.

-mike

I think there are two problems here:

  1. The ProgressIndicator doesn’t seem to be properly stopping/unregistering itself when it is removed from the UI. This means the polling continues even though the indicator has been removed. It also generates the messages in the log like:
  1. My original implementation was using the iterator on ComponentContainer in a for loop, such as:
 for (Iterator<Component> iter = column1Layout.iterator();
     iter.hasNext();) {
     Component comp = iter.next();
    
     if ( comp instanceof ProgressIndicator) {
       iter.remove();
     }
 }

Looking at the code, it appears that the iterator returned is an iterator directly into the components list. So calling iter.remove() removes it from the internal components LinkedList but doesn’t properly stop/unregister/deparent the child component. In this case the child is the progress indicator. This seems to lead to the uncaught client side exception some how (maybe combined with the continual polling from issue #1). Oddly the progress indicator doesn’t render in the UI which made me think this code was originally working.

I think the iterator returned from ComponentContainer either needs to properly implement the iterator interface where remove() would be the same as removeComponent(c) or it needs to be a read-only iterator that doesn’t allow you to modify the underlying LinkedList of child components in the component container.

I rewrote my code to be:

for (int i = column1Layout.getComponentCount() - 1; i >= 0; i--) {
      Component comp = column1Layout.getComponent(i);

      if (comp instanceof ProgressIndicator) {
        column1Layout.removeComponent(comp);
      }
    }

This clears up the client side exception, but my log is full of the RPC errors from #1.

-mike

There is a problem which causes the ProgressIndicator to continue polling even after it has been removed. Should be fixed by http://dev.vaadin.com/ticket/10130

For issue 2, calling removeComponent() outside the original iteration loop is the correct solution at the moment - first collecting the components to remove and then removing them when that iterator is no longer used. Your reverse iteration without using getComponentIterator() also works with the current framework code but is a little more fragile.

I do agree that the documentation of getComponentIterator() should be updated and/or the iterator should be modified to a read-only or to match/use removeComponent().

Could you
create a ticket
about this?

Thanks. Ticket filed: http://dev.vaadin.com/ticket/10139

-mike