Reputation: 4585
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: java.lang.reflect.Constructor
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at javax.swing.event.EventListenerList.readObject(EventListenerList.java:272)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:991)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:498)
at javax.swing.JComponent.readObject(JComponent.java:5478)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:991)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1685)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1341)
at java.io.ObjectInputStream.access$300(ObjectInputStream.java:205)
at java.io.ObjectInputStream$GetFieldImpl.readFields(ObjectInputStream.java:2126)
at java.io.ObjectInputStream.readFields(ObjectInputStream.java:537)
at java.awt.Container.readObject(Container.java:3712)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:991)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at javax.swing.event.EventListenerList.readObject(EventListenerList.java:272)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:991)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1866)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1964)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1888)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at projectserver.SQLHandler.listener(SQLHandler.java:156)
at projectserver.SQLHandler.<init>(SQLHandler.java:27)
at projectserver.Client.run(Client.java:82)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.io.NotSerializableException: java.lang.reflect.Constructor
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1180)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1528)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1528)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at javax.swing.event.EventListenerList.writeObject(EventListenerList.java:257)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:962)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1480)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1528)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:438)
at javax.swing.JComponent.writeObject(JComponent.java:5525)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:962)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1480)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1362)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1170)
at java.io.ObjectOutputStream.access$300(ObjectOutputStream.java:161)
at java.io.ObjectOutputStream$PutFieldImpl.writeFields(ObjectOutputStream.java:1687)
at java.io.ObjectOutputStream.writeFields(ObjectOutputStream.java:478)
at java.awt.Container.writeObject(Container.java:3681)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:962)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1480)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at javax.swing.event.EventListenerList.writeObject(EventListenerList.java:257)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:962)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1480)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1528)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1416)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1174)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at projectclient.ConnectionPane.sendToServer(ConnectionPane.java:131)
at projectclient.AddRecordFrame.btnAddRecordActionPerformed(AddRecordFrame.java:144)
at projectclient.AddRecordFrame.access$000(AddRecordFrame.java:20)
at projectclient.AddRecordFrame$2.actionPerformed(AddRecordFrame.java:94)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6504)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6269)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4860)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2713)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:680)
at java.awt.EventQueue$4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
I'm not sure what code you need, so comment and I'll post. I can't reproduce this problem all the time, but sometimes it goes away after a reboot and other times it doesn't. I really don't know what's causing it. Is there something in AbstractTableModel
that isn't serializable? I have checked that I have no nulls in my table, and there are no static members in the SQLTableModel
class:
package projectcommon;
import java.io.Serializable;
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
/**
* This class is used by both the server and client, and it defines how the data
* from the database is organised and stored. Because it is serializable it
* provides an easy means of communicating data with the server.
*
* @author Logan Dam
*/
public class SQLTableModel extends AbstractTableModel implements Serializable {
/**
* The variable used to store the table's column names.
*/
String[] colNames;
/**
* The variable used to store the table's data.
*/
ArrayList<Object[]> data;
/**
* An array defining the datatypes for the columns in the table.
*/
Class<?>[] types;
/**
* A variable defining whether the user using the table is an admin or not.
*/
private boolean isAdmin;
/**
* An array defining which columns in the table are editable.
*/
private boolean[] isEditable;
/**
* A boolean variable that dictates whether the table is editable or not.
* This is only used in special cases, such as when adding a new record to
* the database.
*/
private boolean addFrame = false;
/**
* Initialises a new {@code SQLTableModel} object based on predetermined data.
*
* @param colNames A {@code String} array containing the table's column names
* @param types A {@code Class} array containing the table's data types.
* @param data An {@code ArrayList} object containing the table's data.
* @param isAdmin A {@code boolean} dictating whether the user is an admin or not.
* @param isEditable A {@code boolean} array that defines which columns are editable
* in the table.
*/
public SQLTableModel(String colNames[], Class<?>[] types, ArrayList<Object[]> data, boolean isAdmin, boolean[] isEditable) {
this.colNames = colNames;
this.types = types;
this.data = data;
this.isAdmin = isAdmin;
this.isEditable = isEditable;
}
/**
* Get the data type of the given column.
* @param columnIndex the index of the column.
* @return A {@code Class} object representing the given column's type.
*/
@Override
public Class<?> getColumnClass(int columnIndex) {
// System.out.println("columnindex " + columnIndex + ": " + types[columnIndex]);
return types[columnIndex];
}
/**
* Get a column's name by index.
* @param column the index of the column.
* @return A {@code String} object containing the column's name.
*/
@Override
public String getColumnName(int column) {
return colNames[column];
}
/**
* Gets all the column names in the table.
* @return a {@code String} array containing all the column names in the table.
*/
public String[] getColumnNames() {
return this.colNames;
}
/**
* Get the data contained at the specified cell.
* @param rowIndex the row the cell lies in.
* @param columnIndex the column the cell lies in.
* @return an {@code Object} containing the data in the specified cell.
*/
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
// System.out.println("rowindex: " + rowIndex);
// System.out.println("columnIndex: " + columnIndex);
// System.out.println("column length: "+ colNames.length);
// System.out.println("num rows: "+ + data.size());
//
// for (int i = 0; i < colNames.length; i++) {
// System.out.println("Column " + i + ": "+ colNames[i]);
//
// }
// for (int i = 0; i < data.size(); i++) {
// System.out.println("row " + i + ": " + data.get(i));
//
// }
return this.data.get(rowIndex)[columnIndex];
}
/**
* Gets the number of columns in the table.
* @return the number of columns in the table.
*/
@Override
public int getColumnCount() {
return colNames.length;
}
/**
* Gets the number of rows in the table.
* @return the number of rows in the table.
*/
@Override
public int getRowCount() {
return data.size();
}
/**
* Sets the value of the specified cell.
* @param aValue the new value to set the cell to.
* @param rowIndex the row the cell lies in.
* @param columnIndex the column the cell lies in.
*/
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Object[] update = this.data.get(rowIndex);
update[columnIndex] = aValue;
this.data.set(rowIndex, update);
fireTableCellUpdated(rowIndex, columnIndex);
}
/**
* Gets an entire row of data.
* @param row the index of the row to fetch.
* @return an {@code Object} array containing the row's data.
*/
public Object[] getRowData(int row) {
return data.get(row);
}
/**
* Gets all the data types for each column in the table.
* @return A {@code Class} array containing the types for each column.
*/
public Class<?>[] getTypes() {
return types;
}
/**
* Only used in special cases, sets whether the table is editable at all or not.
* @param addFrame [@code boolean} defining if the table is editable.
*/
public void setAddFrame(boolean addFrame) {
this.addFrame = addFrame;
}
/**
* Checks whether the specified cell is editable or not.
* @param rowIndex The row the cell lies within.
* @param columnIndex The column the cell within.
* @return True if the cell is editable, otherwise false.
*/
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (addFrame) {
if (isAdmin) {
if (isEditable[columnIndex]) {
//System.out.println("col " + columnIndex + " editable: true");
return true;
} else {
//System.out.println("col " + columnIndex + " editable: false");
return false;
}
} else {
//System.out.println("col " + columnIndex + " editable: false");
return false;
}
} else {
return false;
}
}
/**
* Adds a row of data to the table.
* @param data The row to be added.
*/
public void add(Object[] data) {
this.data.add(data);
fireTableRowsInserted(this.data.size(), this.data.size());
}
/**
* Checks if the table is empty.
* @return true if the table is empty, otherwise false.
*/
public boolean isDataEmpty() {
return this.data.isEmpty();
}
}
The commented bits were used for debugging when I was creating my class, this class hasn't changed in a while so they're not really necessary any more.
EDIT: sendToServer()
is just there so I don't have to type out flush()
and reset()
every time I write something to the stream:
static void sendToServer(Object obj) throws IOException {
out.writeObject(obj);
out.flush();
out.reset();
}
where out is the ObjectOutputStream
established with the server on connection.
EDIT 2: this is where I send an instance of the SQLTableModel to the server:
ConnectionPane.sendToServer("add");
ConnectionPane.sendToServer(lblTableName.getText());
ConnectionPane.sendToServer(addTable.getModel());
String response = (String) ConnectionPane.in.readObject();
if (response.equals("done")) {
closeFrame();
}
And this is the bit that receives it on the server side:
else if (cmd.equals("add")) {
String tableName = (String) client.in.readObject();
String exec = "add " + tableName + " (";
SQLTableModel data = (SQLTableModel) client.in.readObject(); //this is where the exception is thrown
...
addTable
is an empty table with column names that the user fills information in. Once that's done they click add and that's where it sends that table model over.
Upvotes: 1
Views: 962
Reputation: 200158
at projectclient.ConnectionPane.sendToServer(ConnectionPane.java:131)
you invoke the serialization of some object that eventually results in the serialization of EventListenerList
. That object's code tries to transitively serialize a java.lang.reflect.Constructor
and that's what fails. However, this is the root cause, and the proximate cause is an exception while deserializing. The serialization was aborted with an exception, but apparently you didn't detect it at the write side and you are seeing the exception as transferred to the reading side.
As you explain in your edit, sendToServer
serializes its argument. Then the problem lies with projectclient.AddRecordFrame.btnAddRecordActionPerformed(AddRecordFrame.java:144)
which decides what object to send to the server.
If you are indeed trying to serialize the whole SQLTableModel
, that is obviously a misguided approach since that's a Swing GUI class and contains a whole lot of bookkeeping code—among others, the EventListenerList
that is failing in your case. You probably only want to transfer the table's contents, which is a collection under your control—the ArrayList<Object[]> data
. Send only that collection to the server.
Upvotes: 3
Reputation: 81684
Just looking at your stack trace, this line is telling:
at javax.swing.event.EventListenerList.writeObject(EventListenerList.java:257)
In other words, the AbstractTableModel
keeps a list of arbitrary event listener objects, which could be of any class, Serializable
or not, and when the AbstractTableModel
is serialized, an attempt is made to serialize those event listeners as well. This will fail when the listeners themselve are not Serializable
. That may explain why it's a transient problem, as event listeners can come and go as the program runs.
But there are definitely other issues as well: in particular, you haven't made any special arrangements to serialize the contents of the data
array, and the objects it contains aren't guaranteed to be Serializable
themselves.
Upvotes: 2