]> source.dussan.org Git - vaadin-framework.git/commitdiff
Merge of (#10312) to Vaadin 7.
authorAnna Koskinen <anna@vaadin.com>
Tue, 29 Jan 2013 14:35:27 +0000 (16:35 +0200)
committerAnna Koskinen <anna@vaadin.com>
Fri, 1 Feb 2013 13:04:22 +0000 (15:04 +0200)
Cache update exception handling to Table.

Change-Id: I882e78c3a2eb1ceaab484be748b6890ee321c290

server/src/com/vaadin/ui/Table.java
uitest/src/com/vaadin/tests/components/table/TableWithBrokenGeneratorAndContainer.html [new file with mode: 0644]
uitest/src/com/vaadin/tests/components/table/TableWithBrokenGeneratorAndContainer.java [new file with mode: 0644]

index e73c6d7188cfd78dc66d99bd7e9e3ea67ee8fbe0..10752140dbda156e59ccebc15512dca6ee402476 100644 (file)
@@ -557,6 +557,8 @@ public class Table extends AbstractSelect implements Action.Container,
      */
     private boolean keyMapperReset;
 
+    private List<Throwable> exceptionsDuringCachePopulation = new ArrayList<Throwable>();
+
     /* Table constructors */
 
     /**
@@ -1646,6 +1648,55 @@ public class Table extends AbstractSelect implements Action.Container,
 
         setRowCacheInvalidated(true);
         markAsDirty();
+        maybeThrowCacheUpdateExceptions();
+
+    }
+
+    private void maybeThrowCacheUpdateExceptions() {
+        if (!exceptionsDuringCachePopulation.isEmpty()) {
+            Throwable[] causes = new Throwable[exceptionsDuringCachePopulation
+                    .size()];
+            exceptionsDuringCachePopulation.toArray(causes);
+
+            exceptionsDuringCachePopulation.clear();
+            throw new CacheUpdateException(this,
+                    "Error during Table cache update", causes);
+        }
+
+    }
+
+    /**
+     * Exception thrown when one or more exceptions occurred during updating of
+     * the Table cache.
+     * <p>
+     * Contains all exceptions which occurred during the cache update.
+     * </p>
+     * 
+     */
+    public static class CacheUpdateException extends RuntimeException {
+        private Throwable[] causes;
+        private Table table;
+
+        public CacheUpdateException(Table table, String message,
+                Throwable[] causes) {
+            super(message);
+            this.table = table;
+            this.causes = causes;
+        }
+
+        /**
+         * Returns the cause(s) for this exception
+         * 
+         * @return the exception(s) which caused this exception
+         */
+        public Throwable[] getCauses() {
+            return causes;
+        }
+
+        public Table getTable() {
+            return table;
+        }
+
     }
 
     /**
@@ -2036,9 +2087,19 @@ public class Table extends AbstractSelect implements Action.Container,
                 cells[CELL_HEADER][i] = String.valueOf(i + firstIndex + 1);
                 break;
             default:
-                cells[CELL_HEADER][i] = getItemCaption(id);
+                try {
+                    cells[CELL_HEADER][i] = getItemCaption(id);
+                } catch (Exception e) {
+                    exceptionsDuringCachePopulation.add(e);
+                    cells[CELL_HEADER][i] = "";
+                }
+            }
+            try {
+                cells[CELL_ICON][i] = getItemIcon(id);
+            } catch (Exception e) {
+                exceptionsDuringCachePopulation.add(e);
+                cells[CELL_ICON][i] = null;
             }
-            cells[CELL_ICON][i] = getItemIcon(id);
         }
 
         GeneratedRow generatedRow = rowGenerator != null ? rowGenerator
@@ -2056,7 +2117,12 @@ public class Table extends AbstractSelect implements Action.Container,
             boolean isGenerated = isGeneratedRow || isGeneratedColumn;
 
             if (!isGenerated) {
-                p = getContainerProperty(id, colids[j]);
+                try {
+                    p = getContainerProperty(id, colids[j]);
+                } catch (Exception e) {
+                    exceptionsDuringCachePopulation.add(e);
+                    value = null;
+                }
             }
 
             if (isGeneratedRow) {
@@ -2089,7 +2155,12 @@ public class Table extends AbstractSelect implements Action.Container,
                         if (isGeneratedColumn) {
                             ColumnGenerator cg = columnGenerators
                                     .get(colids[j]);
-                            value = cg.generateCell(this, id, colids[j]);
+                            try {
+                                value = cg.generateCell(this, id, colids[j]);
+                            } catch (Exception e) {
+                                exceptionsDuringCachePopulation.add(e);
+                                value = null;
+                            }
                             if (value != null && !(value instanceof Component)
                                     && !(value instanceof String)) {
                                 // Avoid errors if a generator returns
@@ -2098,10 +2169,20 @@ public class Table extends AbstractSelect implements Action.Container,
                                 value = value.toString();
                             }
                         } else if (iscomponent[j]) {
-                            value = p.getValue();
+                            try {
+                                value = p.getValue();
+                            } catch (Exception e) {
+                                exceptionsDuringCachePopulation.add(e);
+                                value = null;
+                            }
                             listenProperty(p, oldListenedProperties);
                         } else if (p != null) {
-                            value = getPropertyValue(id, colids[j], p);
+                            try {
+                                value = getPropertyValue(id, colids[j], p);
+                            } catch (Exception e) {
+                                exceptionsDuringCachePopulation.add(e);
+                                value = null;
+                            }
                             /*
                              * If returned value is Component (via fieldfactory
                              * or overridden getPropertyValue) we expect it to
@@ -2114,7 +2195,12 @@ public class Table extends AbstractSelect implements Action.Container,
                                 listenProperty(p, oldListenedProperties);
                             }
                         } else {
-                            value = getPropertyValue(id, colids[j], null);
+                            try {
+                                value = getPropertyValue(id, colids[j], null);
+                            } catch (Exception e) {
+                                exceptionsDuringCachePopulation.add(e);
+                                value = null;
+                            }
                         }
                     }
                 }
@@ -3049,6 +3135,7 @@ public class Table extends AbstractSelect implements Action.Container,
                     indexInRowbuffer, itemId);
         }
         target.endTag("urows");
+        maybeThrowCacheUpdateExceptions();
     }
 
     private void paintPartialRowAdditions(PaintTarget target,
@@ -3096,6 +3183,7 @@ public class Table extends AbstractSelect implements Action.Container,
         target.addAttribute("firstprowix", firstIx);
         target.addAttribute("numprows", count);
         target.endTag("prows");
+        maybeThrowCacheUpdateExceptions();
     }
 
     /**
diff --git a/uitest/src/com/vaadin/tests/components/table/TableWithBrokenGeneratorAndContainer.html b/uitest/src/com/vaadin/tests/components/table/TableWithBrokenGeneratorAndContainer.html
new file mode 100644 (file)
index 0000000..c2481e6
--- /dev/null
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:9999/" />
+<title>TableWithBrokenGeneratorAndContainer</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">TableWithBrokenGeneratorAndContainer</td></tr>
+</thead><tbody>
+<tr>
+       <td>open</td>
+       <td>/run/com.vaadin.tests.components.table.TableWithBrokenGeneratorAndContainer?restartApplication</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+       <td>item1/prop1</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]</td>
+       <td>item2/prop1</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]</td>
+       <td>item3/prop1</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[4]/domChild[0]</td>
+       <td>Generated item1/Gen</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[4]/domChild[0]</td>
+       <td>Generated item2/Gen</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[4]/domChild[0]</td>
+       <td>Generated item3/Gen</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VCheckBox[0]/domChild[0]</td>
+       <td>12,6</td>
+</tr>
+<tr>
+       <td>click</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td>
+       <td></td>
+</tr>
+<!--error indicator should be present-->
+<tr>
+       <td>assertCSSClass</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td>
+       <td>v-errorindicator</td>
+</tr>
+<!--error notification should not be present-->
+<tr>
+       <td>assertElementNotPresent</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::Root/VNotification[0]</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]</td>
+       <td>item2/prop1</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]</td>
+       <td>item3/prop1</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[4]/domChild[0]</td>
+       <td>Generated item1/Gen</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[4]/domChild[0]</td>
+       <td>Generated item2/Gen</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[4]/domChild[0]</td>
+       <td>Generated item3/Gen</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VCheckBox[0]/domChild[0]</td>
+       <td>9,6</td>
+</tr>
+<tr>
+       <td>click</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[1]</td>
+       <td></td>
+</tr>
+<!--error indicator should be present-->
+<tr>
+       <td>assertCSSClass</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td>
+       <td>v-errorindicator</td>
+</tr>
+<!--error notification should not be present-->
+<tr>
+       <td>assertElementNotPresent</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::Root/VNotification[0]</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]</td>
+       <td>item2/prop1</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]</td>
+       <td>item3/prop1</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[4]/domChild[0]</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[4]/domChild[0]</td>
+       <td>Generated item2/Gen</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[4]/domChild[0]</td>
+       <td>Generated item3/Gen</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VCheckBox[0]/domChild[0]</td>
+       <td>9,8</td>
+</tr>
+<tr>
+       <td>click</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[1]</td>
+       <td></td>
+</tr>
+<!--error notification-->
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::Root/VNotification[0]/HTML[0]/domChild[0]</td>
+       <td>Problem updating table. Please try again later</td>
+</tr>
+<!--table should be empty-->
+<tr>
+       <td>assertElementNotPresent</td>
+       <td>vaadin=runcomvaadintestscomponentstableTableWithBrokenGeneratorAndContainer::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+       <td></td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/uitest/src/com/vaadin/tests/components/table/TableWithBrokenGeneratorAndContainer.java b/uitest/src/com/vaadin/tests/components/table/TableWithBrokenGeneratorAndContainer.java
new file mode 100644 (file)
index 0000000..9c5ce9d
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.table;
+
+import java.lang.reflect.InvocationTargetException;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.event.ListenerMethod.MethodException;
+import com.vaadin.server.ErrorEvent;
+import com.vaadin.server.ErrorHandler;
+import com.vaadin.server.ServerRpcManager.RpcInvocationException;
+import com.vaadin.server.VaadinSession;
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Table.CacheUpdateException;
+import com.vaadin.ui.Table.ColumnGenerator;
+
+public class TableWithBrokenGeneratorAndContainer extends TestBase {
+
+    private CheckBox brokenContainer = new CheckBox("Broken container");
+    private CheckBox brokenGenerator = new CheckBox("Broken generator");
+    private CheckBox clearTableOnError = new CheckBox("Clear Table on Error");
+
+    /**
+     * Container which throws an exception on every fifth call to
+     * {@link #getContainerProperty(Object, Object)}.
+     * 
+     * @author Vaadin Ltd
+     * @version @VERSION@
+     * @since 7.0
+     * 
+     */
+    public class BrokenContainer extends IndexedContainer {
+        private int counter = 0;
+
+        public BrokenContainer() {
+            super();
+        }
+
+        @Override
+        public Property getContainerProperty(Object itemId, Object propertyId) {
+            if (counter++ % 5 == 0
+                    && Boolean.TRUE.equals(brokenContainer.getValue())) {
+                throw new RuntimeException(getClass().getSimpleName()
+                        + " cannot fetch the property for " + itemId + "/"
+                        + propertyId + " right now");
+            }
+            return super.getContainerProperty(itemId, propertyId);
+        }
+    }
+
+    public class BrokenColumnGenerator implements ColumnGenerator {
+        private int brokenInterval;
+        private int counter = 0;
+
+        public BrokenColumnGenerator(int brokenInterval) {
+            this.brokenInterval = brokenInterval;
+        }
+
+        public Object generateCell(Table source, Object itemId, Object columnId) {
+            if (counter++ % brokenInterval == 0
+                    && Boolean.TRUE.equals(brokenGenerator.getValue())) {
+                throw new IllegalArgumentException("Broken generator for "
+                        + itemId + "/" + columnId);
+            } else {
+                return "Generated " + itemId + "/" + columnId;
+            }
+        }
+
+    }
+
+    @Override
+    protected void setup() {
+        brokenContainer.setImmediate(true);
+        brokenGenerator.setImmediate(true);
+        clearTableOnError.setImmediate(true);
+        clearTableOnError.addValueChangeListener(new ValueChangeListener() {
+
+            public void valueChange(ValueChangeEvent event) {
+                Boolean value = clearTableOnError.getValue();
+                setErrorHandler(value != null ? value : false);
+            }
+        });
+        final Table table = new Table("Semi-broken table");
+        table.setContainerDataSource(createBrokenContainer(10, 4));
+        table.addGeneratedColumn("Gen", new BrokenColumnGenerator(4));
+        table.setPageLength(20);
+
+        Button refreshTableCache = new Button("Refresh table cache",
+                new Button.ClickListener() {
+
+                    public void buttonClick(ClickEvent event) {
+                        table.markAsDirty();
+                        table.refreshRowCache();
+                    }
+                });
+        addComponent(refreshTableCache);
+        addComponent(brokenContainer);
+        addComponent(brokenGenerator);
+        addComponent(clearTableOnError);
+        addComponent(table);
+    }
+
+    protected void setErrorHandler(boolean enabled) {
+        if (enabled) {
+            VaadinSession.getCurrent().setErrorHandler(new ErrorHandler() {
+
+                @Override
+                public void error(ErrorEvent event) {
+                    Throwable t = event.getThrowable();
+                    if (t instanceof RpcInvocationException) {
+                        t = t.getCause();
+                        if (t instanceof InvocationTargetException) {
+                            t = t.getCause();
+                            if (t instanceof MethodException) {
+                                t = t.getCause();
+                                if (t instanceof CacheUpdateException) {
+                                    Table table = ((CacheUpdateException) t)
+                                            .getTable();
+                                    table.removeAllItems();
+                                    Notification
+                                            .show("Problem updating table. Please try again later",
+                                                    Notification.Type.ERROR_MESSAGE);
+                                }
+                            }
+                        }
+                    }
+                }
+            });
+        } else {
+            VaadinSession.getCurrent().setErrorHandler(this);
+        }
+    }
+
+    private BrokenContainer createBrokenContainer(int rows, int cols) {
+        BrokenContainer container = new BrokenContainer();
+        for (int j = 1; j <= cols; j++) {
+            container.addContainerProperty("prop" + j, String.class, null);
+        }
+        for (int i = 1; i <= rows; i++) {
+            Item item = container.addItem("item" + i);
+            for (int j = 1; j <= cols; j++) {
+                item.getItemProperty("prop" + j).setValue(
+                        "item" + i + "/prop" + j);
+            }
+        }
+        return container;
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 10312;
+    }
+
+    @Override
+    protected String getDescription() {
+        return "A Table should not show 'Internal Error' just because a column generator or container throws an exception during filling of the cache";
+    }
+
+}