nasty bug: Can't locate it.

Hi, I am attaching some code because I am desperate.

I have a ThreadedAction which is called when I click a button that brings data from a Database. The Data are inserted into a Jtable. Sometimes I get some mysterious exception I can't catch.

class ThreadedActionextends AbstractActionimplements Runnable{

staticfinallong serialVersionUID = 0L;

ActionEvent event;

Object source;

publicvoid actionPerformed(ActionEvent e){

event = e;

source = e.getSource();

if (worker !=null)

return;

worker =new Thread(this);

worker.start();

}

publicvoid run(){

startWaitCursor();

int i = UnitsCombo.getSelectedIndex();

[....]

elseif (source == LoadBtn)

{

QueryConstructor qc =new QueryConstructor();

Vector v;

String id;

String q1 ="";

String q2 ="";

if (selectedTab == 0)//Thermal

{

try{

id = String.valueOf(Thermal_ids.elementAt(UnitsCombo.getSelectedIndex() - 1));

q1 = qc.createSelectSupplyOfferId(id, DButon.getDate());

Vector tmp = nm.fetchDBData(q1);

if (tmp.size() > 0)

{

v = (Vector)tmp.elementAt(0);

q2 = qc.createSelectSupplyOfferBlocks((String)v.elementAt(0));

}

else

thrownew ClientException("no data in db!");

v = nm.fetchDBData(q2);

//fill table

ThermKTable.createTableModelFromResultSet(i - 1, v);

ThermKTable.loadTableModel(i - 1);

}catch (Exception x){

showErrorMessage(x.getMessage());

}

}

...

ThermKTable extends JTable and has this method which I *think* has a bad attitude

publicvoid loadTableModel(int m)

{

if (Tmodels !=null)

{

if (m >= 0)

{

try{

setModel(Tmodels[m]);

createToolTips();

updateUI();

}

catch (Exception e)

{

System.out.println("==>>"+e.getMessage());

}

}

}

}

before and after the db data selection and insertion I call these two functions which are self-explanatory

publicvoid startWaitCursor()

{

RootPaneContainer root = (RootPaneContainer)this.getTopLevelAncestor();

root.getGlassPane().setCursor(this.WAIT_CURSOR);

root.getGlassPane().setVisible(true);

}

/** Sets cursor for specified component to normal cursor */

publicvoid stopWaitCursor()

{

RootPaneContainer root = (RootPaneContainer)this.getTopLevelAncestor();

root.getGlassPane().setCursor(this.DEFAULT_CURSOR);

root.getGlassPane().setVisible(false);

}

ThreadedAction is inner class. Start and Stop wait cursor are methods of the containing class.

These kind of unexplained errors I get:

Exception in thread"AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 10 >= 8

at java.util.Vector.elementAt(Unknown Source)

at javax.swing.table.DefaultTableColumnModel.getColumn(Unknown Source)

at javax.swing.plaf.basic.BasicTableUI.paintCells(Unknown Source)

at javax.swing.plaf.basic.BasicTableUI.paint(Unknown Source)

at javax.swing.plaf.ComponentUI.update(Unknown Source)

at javax.swing.JComponent.paintComponent(Unknown Source)

at javax.swing.JComponent.paint(Unknown Source)

at javax.swing.JComponent.paintChildren(Unknown Source)

at javax.swing.JComponent.paint(Unknown Source)

at javax.swing.JViewport.paint(Unknown Source)

at javax.swing.JComponent.paintChildren(Unknown Source)

at javax.swing.JComponent.paint(Unknown Source)

at javax.swing.JComponent.paintChildren(Unknown Source)

at javax.swing.JComponent.paint(Unknown Source)

at javax.swing.JComponent.paintChildren(Unknown Source)

at javax.swing.JComponent.paint(Unknown Source)

at javax.swing.JComponent.paintChildren(Unknown Source)

at javax.swing.JComponent.paint(Unknown Source)

at javax.swing.JComponent.paintChildren(Unknown Source)

at javax.swing.JComponent.paint(Unknown Source)

at javax.swing.JComponent.paintChildren(Unknown Source)

at javax.swing.JComponent.paint(Unknown Source)

at javax.swing.JComponent.paintChildren(Unknown Source)

at javax.swing.JComponent.paint(Unknown Source)

at javax.swing.JComponent.paintChildren(Unknown Source)

at javax.swing.JComponent.paint(Unknown Source)

at javax.swing.JLayeredPane.paint(Unknown Source)

at javax.swing.JComponent.paintChildren(Unknown Source)

at javax.swing.JComponent.paint(Unknown Source)

at javax.swing.JComponent.paintWithOffscreenBuffer(Unknown Source)

at javax.swing.JComponent.paintDoubleBuffered(Unknown Source)

at javax.swing.JComponent._paintImmediately(Unknown Source)

at javax.swing.JComponent.paintImmediately(Unknown Source)

at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)

at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)

at java.awt.event.InvocationEvent.dispatch(Unknown Source)

at java.awt.EventQueue.dispatchEvent(Unknown Source)

at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)

at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)

at java.awt.EventDispatchThread.pumpEvents(Unknown Source)

at java.awt.EventDispatchThread.pumpEvents(Unknown Source)

at java.awt.EventDispatchThread.run(Unknown Source)

Unexplained errors because I get them sometimes (although doing the exact same routine) and with different IndexOutOfBounds indexes.

Any help would be much appreciated. More code can be given if requested.

null

[7979 byte] By [xpantaa] at [2007-11-27 6:53:00]
# 1
I don't understand your code but basically, there's a discrepancy between row/column size of your table model and that of your table view(GUI).
hiwaa at 2007-7-12 18:27:39 > top of Java-index,Core,Core APIs...
# 2

Thanks.

How did you come up with this thought? Is it only from the exception stack?

If there was a discrepancy then the exception would be thrown in the setModel() routine, no?

Concerning my code I am actually trying to load o model from an array of models. Each Table View contains a bunch of them. Each time I have to select one to view or create a new from database data (as in this case)

I thought the problem had to lie somewhere within the EventDispatcher (that is why I posted here).

xpantaa at 2007-7-12 18:27:39 > top of Java-index,Core,Core APIs...
# 3
> I thought the problem had to lie somewhere within the EventDispatcherNope! It's a simple Vector access issue.
hiwaa at 2007-7-12 18:27:39 > top of Java-index,Core,Core APIs...
# 4

Hi. I think I am getting closer to the error and I don't think that it is primarily GUI related but a concurrency bug and a very nasty one I might say.

I use a Runnable threaded action in order not to block the GUI (code attached above).

in this Runnable action I make a call to a NetManager Thread using this command

v = nm.fetchDBData(q2);

NetManager Thread has been started like this:

public void connect() throws Exception

{

if (socket == null){

try{

System.out.println("opening connection...to "+host+" at port "+port);

socket = new Socket(host, port);

toServer = new ObjectOutputStream(socket.getOutputStream());

fromServer = new ObjectInputStream(socket.getInputStream());

System.out.println("Connection established!");

fireClientEvent(new ClientEvent(this, ClientEvent.CONNECTION_ESTABLISHED, ""));

this.connected = true;

}catch(IOException e){

try{

if (socket != null)

socket.close();

System.out.println("Error while connecting... Server does not exist!");

this.connected = false;

fireClientEvent(new ClientEvent(this, ClientEvent.SERVER_DOES_NOT_EXIST, getHost()+":"+getPort()));

}catch(IOException x){

removeAllListeners();

x.printStackTrace();

}

}

}

else

{

fireClientEvent(new ClientEvent(this, ClientEvent.GENERIC_EVENT, "already connected: "+getHost()+":"+getPort()));

}

}

FetchData is fetching a Hashtable created at Server side like this:

public synchronized Vector fetchDBData(String query) throws ClientException, IOException{

Object obj = new Object();

Vector vec = new Vector();

if (socket != null)

{

try{

Wrapper.clear();

Wrapper.put("type", "select");

Wrapper.put("query", query);

System.out.println("Sending to Server: "+Wrapper.toString());

toServer.writeUnshared(Wrapper);

toServer.flush();

try{

obj = fromServer.readObject();

if (obj != null)

{

System.out.println("Client got "+obj.toString());

if (obj.getClass() == Hashtable.class)

{

if (((Hashtable)obj).get("type").equals("resultset"))

try{

vec = (Vector)((Hashtable)obj).get("results");

}catch(Exception e){

System.out.println(((Hashtable)obj).get("error"));

vec.addElement(e.toString());

}

}

}

}catch (EOFException eofx){

System.out.println("Clent EOF @ object input stream!");

}

return vec;

}catch(Exception e){

e.printStackTrace();

throw new ClientException("connection problem");

}finally{

//writer.close();

}

}else throw new ClientException("Server is not up!");

}

From the Hashtable I "get" a Vector of Vectors object which holds all the DB rows Server managed to "select"

This vector I pass to my JTable in order to be displayed:

with this method (also attached above)

ThermKTable.createTableModelFromResultSet(i - 1, v);

I think that Vector v is not fully "released" from the NetManager thread and when is passed to the createTableModelFromResult() method, vector is not ready.

I am not sure if I make any sense but I don't think this is a GUI error. Strange thing is also the fact that each time I get a different indexoutofbounds index indicator (x <= y)...

Even more strange is the fact that I never get those exceptions on Linux so it has to do with "locks" and "threads" which linux is handling them better than windows.

xpantaa at 2007-7-12 18:27:39 > top of Java-index,Core,Core APIs...
# 5

This is a simple Swing issue.

You are invoking ThermKTable.loadTableModel(i - 1) within your "background" thread. However this method changes the table-model in your JTable.

Swing expressly forbids you from changing most JComponents outside of the event dispatch thread.

Using something like

SwingUtilities.invokeLater (new Runnable()

{

public void run ()

{

ThermKTable.loadTableModel(i - 1);

}

});

from within your background thread should solve your problem.

--Jatinder

JSanghaa at 2007-7-12 18:27:39 > top of Java-index,Core,Core APIs...
# 6
I did and it worked! Thanks a lot!
xpantaa at 2007-7-12 18:27:39 > top of Java-index,Core,Core APIs...