0
votes

I'm working on a group project and we've run into a problem with the serialization part of our software. We have the class protocol:



    import java.io.Serializable;

    import javax.swing.table.TableModel;

    public class Protocol implements Serializable{


        private static final long serialVersionUID = 3474882407641871963L;
        private int state;//0 = logged out 
        //1=logged in waiting for search 
        //2= search query sent
        private String output;
        private TableModel searchResults;

        public Protocol(int state){
            this.output = "";
            this.state = 0;
            this.searchResults = null;
        }

        public void setState(int s) {
            this.state = s;
        }

        public void setOutput(String o) {
            this.output = o;
        }

        public void setSearchResults(TableModel results) {
            this.searchResults = results;
        }

        public String getOutput() {
            return this.output;
        }

        public int getState(){
            return this.state;
        }
        public TableModel getSearchResults(){
            return this.searchResults;
        }


    }

We also have the SearchResult class:


    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;

    import javax.swing.event.TableModelListener;
    import javax.swing.table.TableModel;

    /**
     * An implementation of the TableModel interface that utilises a List of DataRow objects to
     * store the data.
     * 
     * @version 13/03/2014
     * @author Jake Darby
     * 
     * @see DataRow
     * @see TableModel
     */
    public class SearchResult implements TableModel 
    {
        private final List DATA;
        private static final int NUM_COLUMNS = 8;
        private final int NUM_ROWS;

        /**
         * Constructor that generates a SearchResult object from a set of Results of a query to the 'products' table
         * 
         * @param data The results of an SQL query of the 'products' table
         * @throws SQLException
         * 
         * @see ResultSet
         */
        public SearchResult (ResultSet data) throws SQLException
        {
            super();
            DATA = DataRow.generate(data);
            NUM_ROWS = DATA.size();
        }

        /**
         * Constructor creates an empty TableModel
         */
        public SearchResult()
        {
            super();
            DATA = new ArrayList();
            NUM_ROWS = 0;
        }

        @Override
        public int getRowCount() 
        {
            return NUM_ROWS;
        }

        @Override
        public int getColumnCount() 
        {
            return NUM_COLUMNS;
        }

        @Override
        public String getColumnName(int columnIndex) 
        {
            switch(columnIndex)
            {
            case 0:
                return "ID";
            case 1:
                return "Name";
            case 2:
                return "Price";
            case 3:
                return "Pack Quantity";
            case 4:
                return "Quantity in Stock";
            case 5:
                return "VAT";
            case 6:
                return "Order Date";
            case 7:
                return "Expiry Date";
            default:
                return null;
            }
        }

        @Override
        public Class getColumnClass(int columnIndex) 
        {
            switch(columnIndex)
            {
            case 0:
            case 3:
            case 4:
                return Integer.class;
            case 1:
            case 2:
            case 6:
            case 7:
                return String.class;
            case 5:
                return Boolean.class;
            default:
                return null;
            }
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) 
        {
            return false;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) 
        {
            DataRow row = DATA.get(rowIndex);
            switch(columnIndex)
            {
            case -1:
                return row.getPrice();
            case 0:
                return row.getID();
            case 1:
                return row.getName();
            case 2:
                return String.format("£%d.%02d", row.getPrice()/100, row.getPrice()%100);
            case 3:
                return row.getPackQuantity();
            case 4:
                return row.getQuantity();
            case 5:
                return row.getVAT();
            case 6:
                return row.getOrderDate() == null ? "N/A" : row.getOrderDate();
            case 7:
                return row.getExpiryDate() == null ? "N/A" : row.getExpiryDate();
            default:
                return null;
            }
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) 
        {/*No implementation*/}
        @Override
        public void addTableModelListener(TableModelListener l) 
        {/*No implementation*/}

        @Override
        public void removeTableModelListener(TableModelListener l) 
        {/*No implementation*/}

        @Override
        public String toString()
        {
            String result = "";
            for (int i = 0; i 

The problem arises when we write the Protocol class over a client-server socket connection. The issue is that the TableModel object in the Protocol class becomes null at some point in the serialization/de-serialization process, and nothing we have done has yet fixed this.

We have so far tried:

- implementing Serializable in SearchResult (I don't believe that it should be necessary due to TableModel implementing Serializable)

- changing the TableModel field variable to a SearchResult field variable in Protocol

Any help would be most appreciated.

1
Don't post your entire code. Take your time and create minimal example we could use to reproduce your problem. There is also a chance that while creating such example you will figure out your problem yourself.Pshemo
Your SearchResult class isn't serializableNick Holt
@NickHolt: OP has tried implementing Serializable in SearchResult as given in the pointsAndyFaizan
I don't see how you're serializing the class. Are you using ObjectOutputStream?mttdbrd
Is the serialization/deserialization happening in the same JVM? Given you've set the serialVersionUID on Protocol it's possible that you have two different versions of the class (if you're using 2 JVMs). One version of the class without the searchResults field being used on serializing side and another version of the class with the searchResults field being used on the serializing side, hence the field remains nullNick Holt

1 Answers

1
votes

This code correctly serializes and de-serializes the object:

//write out the object
FileOutputStream fos = new FileOutputStream("out.myobj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Protocol p = new Protocol(4);
p.setState(5);
oos.writeObject(p);
oos.close();

//read it in
FileInputStream fis = new FileInputStream("out.myobj");
ObjectInputStream ois = new ObjectInputStream(fis);
Protocol x = (Protocol)ois.readObject();
ois.close();
System.out.println(x.getState());

Output:

5

In this case, it's something with how you write the object to the stream.

FYI: TableModel is an interface that does not implement Serializable. Implementing Serializable is necessary here only for Protocol. If you're instead writing out the class implementing TableModel, then that one needs to implement Serializable too.

See the docs:

http://docs.oracle.com/javase/7/docs/api/javax/swing/table/TableModel.html