I am using 2 Tables (JTable) with their DefaultTableModels. The first table is already populated. The second table is populated for each row of the first table (using an SQL Query). My purpose is to export every line of the first table with it's respective lines of the second in an Excel File.
I am doing it with a for (for each line of 1st table), in which I write a line of the 1st table in the Excel File, then I populate the 2nd table (for this line of 1st Table), I get every line from the Table (from it's Model actually) and put it in the Excel File under the current line of 1st table. This means that if I have n lines in first table I will clear and populate again the second table n times.
All this code is called in a seperate thread.
THE PROBLEM IS: Everything works perfectly fine ecxept that I am getting some exceptions. The strange thing is that I'm not getting anything false in my result. The Excel file is perfect.
Some of the lines of the exceptions are:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 0 >= 0 at java.util.Vector.elementAt(Vector.java:427) at javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:632) at javax.swing.JComponent.paint(JComponent.java:1017) at javax.swing.RepaintManager.paint(RepaintManager.java:1220) at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:803)
I am assuming that the problem lies in the fact that the second table needs some more time to be populated before I try to get any data from it. That's why I see RepaintManager and paintDirtyRegions in my exceptions. Another thing I did is that I ran my program in debug mode and I put a breakpoint after each population of the 2nd table. Then I pressed F5 to continue for each population of 2nd table and no exception appeared. The program came to it's end without any exceptions. This is another important fact that tells me that maybe in this case I gave the table enough time to be populated.
Of course you will ask me:
If your program works fine, why do you care about the exceptions? I care for avoiding any future problems and I care to have a better understanding of Java and Java GUI and threads.
Why do you depend on a GUI component (and it's model) to get your information and why don't you recreate the resultset that populates your tables using an SQL Query and get your info from the resultset? That would be the best and the right way. The fact is that I have the tables code ready and it was easier for me to just get the info from them. But the right way would be to get everything direct from database. Anyway what I did brought out my question, a开发者_如何转开发nd answering it would help me understand more things about java. So I posted it.
The Swing API is not thread-safe except for a few method calls: repaint, revalidate, and invalidate. All other calls unless otherwise noted for a specific class must be made on the Event Dispatch Thread.
Transferring such call processing from a spawned background/worker thread can be done via SwingUtilities.invokeLater() or SwingUtilities.invokeAndWait().
There is also some specific discussion regarding both JTable and any TableModel that has been attached to an instance of it in the javax.swing package summary javadocs. Neither is thread-safe, so any calls accessing data from them must be performed on the Event Dispatch Thread.
This is the most probable cause of the exceptions you are encountering, and the different behavior that you experience when running in a debugger is a classic sign of a race condition. There is also no reliable way to hack around this via introducing your own locks, etc. Such practices invariably lead to trouble (such as deadlocks with the Event Dispatch Queue lock deep inside the Swing library) in the long run since Swing really, truly was not designed to be thread-safe.
The exception is happening because one of the table models is returning null for a getValueAt(int row,int column) call. The reason for this is probably an internal issue in swing or the data model due to the fact that you are using a secondary thread to access the data models. The swing api specifically states that you can not use a secondary thread in the way you described.
The following article provides further details on the single thread rule in swing.
http://java.sun.com/products/jfc/tsc/articles/threads/threads3.html
精彩评论