Question

I try to add tooltips to my JTable header. In this case I use TTHeader class which extends JTableHeader Java class. Everything it seems to be fine, but when I try to add new TTHeader header to my JTable, than I get NullPointerException with Unknown Source. I don't know why. TTHeader class seems to be ok. Problem is somewhere else.

Here is code with my approach. For JTable populate:

 private JPanel contentPane;
 private JScrollPane scrollPane;
 private JTable table;
 private String tooltipsSDB[] = {"SessionID", "UserID", "PatientID", "PluginID", "Date", "Time"};

 Connection conn = null;
 ResultSet rs = null;
 PreparedStatement ps = null;

 Table() {
      // Connection Component
      conn = ConnectionJDBC.ConnectDB();

      setTitle("My sample table");
      setSize(new Dimension(400, 400));
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setLocationRelativeTo(null);
      setVisible(true);

      contentPane = new JPanel();
      contentPane.setLayout(new BorderLayout(0, 0));
      setContentPane(contentPane);

      scrollPane = new JScrollPane();
      contentPane.add(scrollPane, BorderLayout.CENTER);

      table = new JTable() {
           public boolean isCellEditable(int row, int column) {
                return false;
           };
      };
      table.setAutoCreateRowSorter(true);
      // Populate JTable with data from SQL DB
      populateTable();
      scrollPane.setViewportView(table);
 }

 public void populateTable() {
      String sql = "SELECT * FROM " + ExampleDatabase + " ORDER BY " + ExampleData + " DESC";
      try {
           // Make Connection With DB
           ps = conn.prepareStatement(sql);
           rs = ps.executeQuery();
           ResultSetMetaData rsmetadata = rs.getMetaData();

           // Populate JTable
           int columns = rsmetadata.getColumnCount();
           DefaultTableModel dtm = new DefaultTableModel();
           Vector columns_name = new Vector();
           Vector data_rows = new Vector();
           for (int i = 1; i <= columns; i++) {
                columns_name.addElement(rsmetadata.getColumnName(i));
           }
           dtm.setColumnIdentifiers(columns_name);
           while (rs.next()) {
                data_rows = new Vector();
                for (int j = 1; j <= columns; j++) {
                     data_rows.addElement(rs.getString(j));
                }
                dtm.addRow(data_rows);
           }
           table.setModel(dtm);

           // Create Header For JTable
           TTHeader tth = new TTHeader(table.getColumnModel());
           tth.setToolTipStrings(tooltipsSDB);
           table.setTableHeader(tth); // On This Line I Get NullPointerException With Uknown Source

           table.repaint();
      } catch (SQLException e) {
           JOptionPane.showMessageDialog(null, "Populate table error! \n" + e);

      } 
 }

 public static void main(String args[]) {
      EventQueue.invokeLater(new Runnable() {
           public void run() {
                try {
                     new Table();
                } catch (Exception e) {
                     JOptionPane.showMessageDialog(null, e);
                }
           }
      });
 }

And TTHeader class:

String[] toolTips;

public TTHeader(TableColumnModel model) {
    super(model);
}

public String getToolTipText(MouseEvent e) {
    int col = columnAtPoint(e.getPoint());
    int modelCol = getTable().convertColumnIndexToModel(col);
    String retStr;
    try {
        retStr = toolTips[modelCol];
    } catch (NullPointerException ex) {
        retStr = "";
    } catch (ArrayIndexOutOfBoundsException ex) {
        retStr = "";
    }
    if (retStr.length() < 1) {
        retStr = super.getToolTipText(e);
    }
    return retStr;
}

public void setToolTipStrings(String[] toolTips) {
    this.toolTips = toolTips;
}

NPE appears when I choose second database from JComboBox. In JComboBox listener I call populateTable() method. Here is a more specific stacktrace:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at mypackage.TTHeader.getToolTipText(TTHeader.java:19)
at javax.swing.ToolTipManager$insideTimerAction.actionPerformed(Unknown Source)
at javax.swing.Timer.fireActionPerformed(Unknown Source)
at javax.swing.Timer$DoPostEvent.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(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)

Line nr 19:

int modelCol = getTable().convertColumnIndexToModel(col);
Was it helpful?

Solution

When you get an NPE and identified the line, the first thing you check is all occurrences of the dereferencing operator (.). The value on the left hand side(!) of such an operator will be null. (If you have multiple .s on one line, then one of those. So if your line is foo.getBar().doSomething(), either foo is null or foo.getBar() returns null. But what doSomething() returns does NOT matter.)

In this case, it will probably be the getTable() method that returns null.

Since Java 5 there have been two new, rather more sneaky possible causes of NPE:

  1. Implicit dereferencing in for (Foo foo : fooCollection), here you get an NPE if fooCollection is null.
  2. Auto-unboxing of numbers: Integer i = null; int j = i + 1; //NPE here

That's all you need to know about the debugging of NPEs in general, there's of course the even more general advice that you should either log variable values or use a debugger to execute your code step-by-step.

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