/* * Copyright 2000-2016 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.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.v7.data.Item; import com.vaadin.v7.data.Property; import com.vaadin.v7.data.util.IndexedContainer; import com.vaadin.v7.ui.Table; import com.vaadin.v7.ui.Table.CacheUpdateException; import com.vaadin.v7.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; } @Override 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() { clearTableOnError.addValueChangeListener(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() { @Override 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"; } }