I am displaying the contents of a file system using a table and a FileSystemContainer and am having a couple of issues. I am using Vaadin version 6.7.0 :
If I then add a file to the directory and then scroll quickly through the table it throws an ArrayIndexOutOfBoundsException at com.vaadin.ui.Table.paintContent.
Running a debug on the application I can see that the extra file is indeed added to the container.
If I remove a file from the directory, and do not scroll, the file remains in the table (as is expected, I assume). If I call requestRepaint() on the table, it blanks out totally. If rather than calling repaint I simply scroll quickly up and then back down, the file still appears in the table but now it has a filesize of 0. Calling .size() on the container shows that the number of files has in fact decreased.
Is this a related problem? Is there some other way I should be refreshing the table?
Thanks kindly!
Josh
Here’s my code:
public class DatabaseView extends Panel implements ValueChangeListener {
private VerticalSplitPanel verticalSplitPanel;
private File folder;
private Table fileTable;
private VerticalLayout contentArea;
private Panel topContentArea;
private Panel bottomContentArea;
private Label selectedFile = new Label();
private HorizontalLayout buttonArea;
private FilesystemContainer container;
public DatabaseView () {
setSizeFull();
addStyleName(Runo.PANEL_LIGHT);
folder = new File("/var/www/backups");
container = new FilesystemContainer(folder);
fileTable = new Table("Database Backups", container);
fileTable.setSizeFull();
fileTable.setSelectable(true);
fileTable.setImmediate(true);
fileTable.setNullSelectionAllowed(false);
fileTable.setColumnCollapsingAllowed(true);
fileTable.setColumnReorderingAllowed(true);
fileTable.setVisibleColumns(new Object[] {"Name", "Size", "Last Modified"});
fileTable.addListener((Property.ValueChangeListener) this);
verticalSplitPanel = new VerticalSplitPanel();
topContentArea = new Panel();
topContentArea.setSizeFull();
topContentArea.addStyleName(Runo.PANEL_LIGHT);
topContentArea.addComponent(selectedFile);
Label gap = new Label();
gap.setHeight("1em");
topContentArea.addComponent(gap);
buttonArea = new HorizontalLayout();
buttonArea.setWidth("50%");
topContentArea.addComponent(buttonArea);
bottomContentArea = new Panel();
bottomContentArea.setSizeFull();
bottomContentArea.addStyleName(Runo.PANEL_LIGHT);
contentArea = new VerticalLayout();
contentArea.setSizeFull();
contentArea.addComponent(topContentArea);
contentArea.addComponent(bottomContentArea);
contentArea.setExpandRatio(topContentArea, 2 * 1.0f);
contentArea.setExpandRatio(bottomContentArea, 1 * 1.0f);
contentArea.setComponentAlignment(bottomContentArea, Alignment.TOP_LEFT);
verticalSplitPanel.setFirstComponent(fileTable);
verticalSplitPanel.setSecondComponent(contentArea);
verticalSplitPanel.setSplitPosition(40);
setContent(verticalSplitPanel);
}
@Override
public void valueChange(ValueChangeEvent event) {
Property property = event.getProperty();
if (property == fileTable) {
selectedFile.setValue(((File) fileTable.getValue()).getName());
}
}
}
I still haven’t resolved my original issue (which linked a table with a FileSystemContainer) but I have since run into a similar problem when employing a TreeTable and a FileSystemContainer. Perhaps this will shed a bit more light on things.
With a normal table if I delete a file from the directory referenced by the container, an error is not thrown, but rather the file remains in the table, only now showing a filesize of “0”. With the TreeTable however, deleting a file from the underlying directory does cause and ArrayIndexOutofBoundsException:
java.lang.ArrayIndexOutOfBoundsException: 0
at com.vaadin.ui.Table.getVisibleCellsUpdateCacheRows(Table.java:1535)
at com.vaadin.ui.Table.paintPartialRowUpdates(Table.java:2552)
at com.vaadin.ui.Table.paintPartialRowUpdate(Table.java:2536)
at com.vaadin.ui.Table.paintContent(Table.java:2499)
at com.vaadin.ui.TreeTable.paintContent(TreeTable.java:450)
As with a normal Table, the TreeTable also throws the ArrayIndexOutOfBoundsException error if a file is added to the underlying directory referenced by the container.
Up until this point I have been testing with Glassfish as the application container. As a sanity check, I went ahead and ran a test on Tomcat. The results are essentially the same.
If I delete a file behind the scenes in the directory that is referenced by the filesystemcontainer and then cause a repaint (by traversing the directory tree), an internal error is thrown:
Oct 24, 2011 9:46:33 AM com.vaadin.Application terminalError
SEVERE: Terminal error:
java.lang.ArrayIndexOutOfBoundsException: 0
at com.vaadin.ui.Table.getVisibleCellsUpdateCacheRows(Table.java:1535)
at com.vaadin.ui.Table.paintPartialRowUpdates(Table.java:2552)
at com.vaadin.ui.Table.paintPartialRowUpdate(Table.java:2536)
at com.vaadin.ui.Table.paintContent(Table.java:2499)
at com.vaadin.ui.TreeTable.paintContent(TreeTable.java:450)
If I add a file behind the scenes, sometimes an error is thrown and sometimes items in the directory tree start to duplicate themselves. For example, if there is a directory called “XML” after adding a new file suddenly I see two “XML” directories. I saw this behavior in Glassfish as well.
I’ve simplified the test code to be in the Application Class. Here is is:
package com.example.vaadintest;
import java.io.File;
import com.vaadin.Application;
import com.vaadin.data.util.FilesystemContainer;
import com.vaadin.ui.TreeTable;
import com.vaadin.ui.Window;
public class VaadinTestApplication extends Application {
@Override
public void init() {
Window mainWindow = new Window("Vaadin FileSystem Test");
setMainWindow(mainWindow);
File folder = new File("/var/www/signage/images/stories/videos/test");
FilesystemContainer container = new FilesystemContainer(folder);
TreeTable fileSystemTree = new TreeTable(null,container);
fileSystemTree.setWidth("100%");
fileSystemTree.setItemCaptionPropertyId(FilesystemContainer.PROPERTY_NAME);
fileSystemTree.setItemIconPropertyId("Icon");
fileSystemTree.setVisibleColumns(new Object[]{"Name", "Size", "Last Modified"});
fileSystemTree.setColumnExpandRatio("Name",4);
fileSystemTree.setColumnExpandRatio("Size",1);
fileSystemTree.setColumnExpandRatio("Last Modified",2);
fileSystemTree.setSelectable(true);
fileSystemTree.setImmediate(true);
fileSystemTree.setNullSelectionAllowed(false);
mainWindow.addComponent(fileSystemTree);
}
}
Can anyone help me out? I feel this could be a bug, but I am a total newbie to Vaadin and I’m not sure if I’m the best person to file a bug report.
You could
create bug reports about these issues and include the test application and a link to this thread in the tickets.
Even though I suspect that the underlying issue is the same, you can create separate tickets and reference the other ticket in each.
I had exact the same problem today when i was testing CrudContainer (Addon). I Did a quick scroll on a normal table with almost 300 entrys and faced that ArrayIndexOutOfBoundsException. I was using Vaadin 6.7.1
I also came up with this error while I was trying to implement my own Container similar to your CrudContainer. It is important that your Container implementation fires ItemSetChangeEvent as mentioned in issue http://dev.vaadin.com/ticket/7836. The best way, IMHO, is to use AbstractInMemoryContainer in order to deal with such requirements.
First I’d like to send a heartfelt thanks and congratulations to the Vaadin team for fixing both of my bugs (ticket 7836 and 7837). I am very impressed with how quickly they resolved these issues!
I just wanted provide some closure here by sharing my experience:
I am using both a Table and TreeTable with a FileSystemContainer as a data source. Because modifications to the file system are being controlled directly by the Vaadin application (file deletion and upload), I am able to force a page refresh by calling the containerItemSetChange(null) method directly on the table.
If you do need true notifications for changes from the file system, you can use the new WatchService in Java 7 or some suitable third party library (jpathwatch, JNotify, JxFileWatcher, …). However, the core FilesystemContainer does not and should not depend on these at the moment.
Although it would be hard to do exact updates in the current implementation of FilesystemContainer, you could e.g. have a background thread watching for such modifications and setting a flag if anything relevant is changed to avoid a large number of small modifications each causing a full refresh, and then notify/refresh your UI components after a timeout or when needed.