Question

I have implemented a custom Table Model as follows:

public class MyTableModel extends AbstractTableModel {
    ...
    ...
    @Override
    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();
    }
    ...
    ...
}

I am getting NullPointerException thrown by the above method, when I display a JTable having the above TableModel.

I think that the exception is due to some empty cells in the database table.

If the exception is due to empty cells in the database table, then how to get around with this problem?

It is not mandatory for every column in the database to have some value. Some columns can contain nothing.

Was it helpful?

Solution

If cells can contain empty values, then calling getClass() on a null value will certainly give you the NPE. Sure you can check for null, but your real problem is more subtle than that.

The TableModel interface specifies that getColumnClass(int) should return "the most specific superclass for all the cell values in the column." From the looks of things, you could be returning any number of class types for a single column, effectively breaking the TableModel contract.

Typically, column types are static for a given set of table data, meaning the class for a column shouldn't change unless the underlying table data has changed. I think it's important to ask why you need to return such a specific value.

In the case where you want to render something specific for a given class type, you're better off rolling your own TableCellRenderer, and determining the Object type on a per-cell basis. From there you can do any specific rendering as needed.

OTHER TIPS

One issue is why you are getting a null for these specific coordinates. If it is legitimate and you just want nothing special to be rendered, then what you need to do is null-check and return Object.class e.g.,:

   public Class getColumnClass(int c) {
        Object o = getValueAt(0, c);
        if(o==null) return Object.class;
        return o.getClass()
    }

This will ensure that the default renderer is used, and since there is no value, nothing will be rendered.

Perhaps:

public Class getColumnClass(int c) {
        return (getValueAt(0, c) == null ? Object.class : getValue(0, c).getClass());
  }

I hope it helps you.

In addition to the answers so far: Assuming your model is backed by a List (as suggested in your previous question) you'll see an IndexOutOfBoundsException if attempting to render your JTable when the TableModel contains no rows (i.e. the List is empty). This is a nasty edge case (as I realise you're attempting to render a ResultSet - How do you know the ResultSet won't be empty?).

To avoid this, why didn't you do what I suggested originally and determine each column's class from the ResultSetMetaData?

ResultSetMetaData does NOT provide any information about the class. It does provide database-specific data types which don't automatically map over to Java classes (e.g., "cidr" or "int8" in the PostgreSQL world) so this suggestion (which didn't include any source code, by the way) isn't actually helpful.

Also, the comment "I think it's important to ask why you need to return such a specific value" by Jason Nichols shows general cluelessness about how the JTable class is used in the real world.

I'd like to find a solution to this problem where tables have zero rows, where I can still find out what the Java Class is that I should be using to render my cells for the entire column. The idea that the output can change is based in yet more cluelessness about databases -- a column data type is specified in the definition of that column, and no matter what its contents are the data type doesn't change depending on which row you're looking it.

Of course one of the challenges with databases is that column definitions may or may not permit NULL values, and anyone sub-classing JTable for this should understand this very basic premise and know how to test for this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top