views:

41

answers:

3

I've an Observer TableModel which listens to some changes, performed in the database, and when so the update method below is called. My problem is, how should I prevent errors like:

java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.set(ArrayList.java:337)
at com.mysimpatico.memoplatform.persistenceui.MeaningsViewerTopComponent$DefaultTableModelImpl.update(MeaningsViewerTopComponent.java:108)

I don't see how SwingWorker would help. I've the long-running database task being performed in a separate thread, but this calls upon a method (database persisting) in an Observable class which notifies observers.

@Override
        public void update(Observable o, final Object arg) {
            final Meaning meng = (Meaning) arg;
            final int row;
            final boolean insert;
            synchronized (mengs) {
                if (mengs.contains(meng)) {
                    row = meng.getObjId();
                    mengs.set(row, meng);
                    insert = false;
                } else {
                    row = mengs.size();
                    mengs.add(row, meng); //last
                    insert = true;
                }
                try {
                    SwingUtilities.invokeAndWait(new Runnable() {

                    @Override
                    public void run() {
                        if (insert) {
                            fireTableRowsInserted(row, row);
                        } else {
                            fireTableRowsUpdated(row, row);
                        }
                    }
                });
            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            } catch (InvocationTargetException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }
A: 

One option is using a org.jdesktop.application.Task. You will need to pass the TableModel to the Task and then so a simple TableModel.insert call.

Note: The task is just a nice wrapper around a Thread.

Carlos Tasada
+2  A: 

Despite firing insert / update TableModelEvents on the event dispatch thread you're actually updating the TableModel on whichever thread is performing the notification of the database update. This is dangerous as it means:

  • The event dispatch thread could potential see the TableModel in an inconsistent state.
  • The event dispatch thread could be attempting to render the TableModel as the notification thread is altering it.

The solution should (in theory) simply be a case of moving your call to SwingUtilities.invokeAndWait to outside the block of code that begins: synchronized(mengs). Also, once you've done this you can actually removed the synchronized keyword entirely as all access to your model will be done on the EDT.

As an aside I would avoid using the Observer / Observable classes (for more information see my answer to this question); far better to define domain-specific listener interfaces and event classes (that subclass java.util.EventObject).

Adamski
What else? I still get the exception. Only the line number changed.
simpatico
You really need to provide more information in your question as an IndexOutOfBoundsException can be down to any number of reasons. Simply responding with "What else?" isn't going to motivate me :-)
Adamski
+1  A: 

Are your indexes correct?

java.lang.IndexOutOfBoundsException: Index: 1, Size: 1 

The above statement says you only have one entry in the array list. I can't tell if your code is an "add" or an "update". But remember that ResultSet indexes are 1 based not 0 based so maybe you need to subtract 1 from all your row values?

camickr
they are not. I don't use ResultSet, but my Meaning object ids start from one.
simpatico
@simpatico, if your "object ids" start from 1, and array indexes start from 0, don't you have a problem? You can't just use the id value as the row index.
camickr
indeed, I meant to say that I dont't use ResultSet but that this was part of the problem (since Meaning ids start from 1).
simpatico