Hi!

When I try to run the code tableModel.setQuery("select l_code, l_title, l_description from Lists"); , then I receive the following error:

java.lang.ArrayIndexOutOfBoundsException: 0 >= 0
        at java.util.Vector.elementAt(Vector.java:427)
        at SystClasses.QueryTableModel.getValueAt(QueryTableModel.java:72)
        at SystClasses.QueryTableModel.getColumnClass(QueryTableModel.java:53)
        at javax.swing.table.TableRowSorter.useToString(TableRowSorter.java:224)
        at javax.swing.DefaultRowSorter.updateUseToString(DefaultRowSorter.java:607)
        at javax.swing.DefaultRowSorter.sort(DefaultRowSorter.java:556)
        at javax.swing.DefaultRowSorter.allChanged(DefaultRowSorter.java:816)
        at javax.swing.DefaultRowSorter.modelStructureChanged(DefaultRowSorter.java:826)
        at javax.swing.JTable.tableChanged(JTable.java:4364)
        at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:280)
        at SystClasses.QueryTableModel.setQuery(QueryTableModel.java:110)
        at SystClasses.Form.createAdminTable(Form.java:747)
        at SystClasses.Form.access$1300(Form.java:54)
        at SystClasses.Form$20.actionPerformed(Form.java:698)
        at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
        at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
        at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
        at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
        at java.awt.Component.processMouseEvent(Component.java:6263)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
        at java.awt.Component.processEvent(Component.java:6028)
        at java.awt.Container.processEvent(Container.java:2041)
        at java.awt.Component.dispatchEventImpl(Component.java:4630)
        at java.awt.Container.dispatchEventImpl(Container.java:2099)
        at java.awt.Component.dispatchEvent(Component.java:4460)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
        at java.awt.Container.dispatchEventImpl(Container.java:2085)
        at java.awt.Window.dispatchEventImpl(Window.java:2478)
        at java.awt.Component.dispatchEvent(Component.java:4460)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)

The QueryTableModel is:

class QueryTableModel extends AbstractTableModel {
  Vector cache; // will hold String[] objects
  int colCount;
  String[] headers;
  String url; String databasename;
  String login; String pass;
  Connection db;
  static Statement statement;

  public QueryTableModel(String url, String databasename, String login, String pass) {
    cache = new Vector();
    initDB(url, databasename, login, pass);
  }

  public static Statement getStatement() {
      return statement;
  }

  @Override
  public String getColumnName(int i) {
    return headers[i];
  }

  public int getColumnCount() {
    return colCount;
  }

  @Override
  public Class getColumnClass(int col) {
    return getValueAt(0, col).getClass();
  }

  @Override
  public int getRowCount() {
    return cache.size();
  }

  public void deleteData() {
    int rows = getRowCount();
    if (rows == 0) {
        return;
    }
    cache.clear();
    fireTableRowsDeleted(0, rows - 1);
  }

  @Override
  public Object getValueAt(int row, int col) {
    Object str = ((Object[]) cache.elementAt(row))[col];
    if (str != null)
        return str;
    else return "";
  }
...
}

So, what is wrong here? Thanks!

Well, you didn't post the relevant part of your QueryTableModel class: tableModel.setQuery() , but it looks like your default row sorter isn't very happy about an empty data vector.

I don't think you're handling an empty result set quite right in your model.

Edited 6 Years Ago by Ezzaral: n/a

Thank you. How could I handle an empty result set in a correct way?

setQuery is as follows:

public void setQuery(String q) {
    cache = new Vector();
    try {
      // Execute the query and store the result set and its metadata
      ResultSet rs = statement.executeQuery(q);
      ResultSetMetaData meta = (ResultSetMetaData) rs.getMetaData();
      colCount = meta.getColumnCount();

      // Now we must rebuild the headers array with the new column names
      headers = new String[colCount];
      for (int h = 1; h <= colCount; h++) {
        headers[h - 1] = meta.getColumnName(h);
      }

      while (rs.next()) {
        String[] record = new String[colCount];
        for (int i = 0; i < colCount; i++) {
          record[i] = rs.getString(i + 1);
        }
        cache.addElement(record);
      }
      fireTableChanged(null); // notify everyone that we have a new table.
    } catch (Exception e) {
      cache = new Vector(); // blank it out and keep going.
      e.printStackTrace();
    }
  }

yes, you are right about the row sorter. If I run the program without a row sorter, then it works. However, if I use:

sorter = new TableRowSorter<QueryTableModel>(tableModel);
tableAttributesFormTypes.setRowSorter(sorter);

...then it fails. But how could I improve my code?

The DefaultRowSorter is blowing up when it tries to determine the column class in your model, because you are using the value of the first element to determine the class here

@Override
  public Class getColumnClass(int col) {
    return getValueAt(0, col).getClass();
  }

That's all fine and well when there is an element at index 0 to examine - not so much when the vector is empty.

You could try to return either a null or Object.class in that case. I'm not sure which one will may the default row sorter happy. You'll have to experiment or dig into its code.

@Override
  public Class getColumnClass(int col) {
    return cache.size()>0 ? getValueAt(0, col).getClass() : null;
  }

Oh, thank you very much!!! return cache.size()>0 ? getValueAt(0, col).getClass() : null; helped to solve the problem!

This question has already been answered. Start a new discussion instead.