0

Trying to write a program that will allow clients to send an object to each other. I'm currently using the ObjectOuptutStream to send it across sockets and whenever I try to read or write an object from the object stream, it gives the exception: java.io.NotSerializableException. I searched online about this exception, and the solution I am getting mostly was to implement the Serializable interface on the object you are sending or reading from the stream. Which I did, but still receives this exception.

Here's the object class:

public class Event implements Serializable {

    private static final long serialVersionUID = 1L;

    Integer from;
    Vector<Integer> timestamp;

    public Event(int identifier, Vector<Integer> timestamp) {
        this.from = identifier;
        this.timestamp = timestamp;
    }

    int getFromID() {
        return from;
    }

    Vector<Integer> getTimestamp() {
        return timestamp;
    }

}

Here's the section of the Client class that is writing to other sockets

    Random rand = new Random();

    int temp;
    while (eventCount < 100) {
        System.out.println("Generating Event");
        int choice = rand.nextInt(5);
        if (choice == 0) {
            temp = timestamp.get(identifier);
            ++temp;
            timestamp.set(identifier, temp);
        } else {
            int randC = rand.nextInt(outputClients.size());
            ClientSocket cc = outputClients.get(randC);
            cc.out.writeObject(new Event(identifier, timestamp));
        }
        System.out.println("Done Generating Event");
    }

And here's the threads that are reading the object

public class ClientConnection extends Thread {
    Socket socket;
    ObjectOutputStream out;
    ObjectInputStream in;
    Random rand = new Random();
    public ClientConnection(Socket s) {
        this.socket = s;
        try {
            out = new ObjectOutputStream (socket.getOutputStream());
            in = new ObjectInputStream (socket.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // execute the event
    private void executeEvent(int from, Vector<Integer> x) {
        int temp;
        synchronized (timestamp) {
            for (int i = 0; i < timestamp.size(); ++i) {
                if (x.get(i) > timestamp.get(i)) {
                    timestamp.set(i, x.get(i));
                }
            }
            temp = timestamp.get(from);
            ++temp;
            timestamp.set(from, temp);
        }
    }

    @Override
    public void run () {
        while (true) {
            System.out.println("Reading events");
            if (!isAlive) { 
                break;
            }
            try {
                Event event = (Event) in.readObject();
                executeEvent(event.getFromID(), event.getTimestamp());
            } catch (ClassNotFoundException e) {

            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(timestamp);
        }
    }
}

And here's the Client class for full context (assuming all the appropriate packages are imported)

public class Computer {

static final int MAX_SYSTEMS = 2;                   // MAX SYSTEMS
static Vector<Integer> timestamp = new Vector<Integer>();
static int[] timestamp1 = new int[MAX_SYSTEMS];     // Time-stamp
static int identifier;                              // Computer ID
static int eventCount = 0;                          // Event Counts
static boolean isAlive = true;                      // Check if the computer is alive

Socket sockToServer;
PrintWriter outputToServer;
BufferedReader inputFromServer;
String textFromServer;

ServerSocket ss;

static ArrayList<ClientSocket> outputClients = new ArrayList<ClientSocket>();
static ArrayList<ClientConnection> inputClients = new ArrayList<ClientConnection>();

Log log;

public static void main(String[] args) throws IOException {
    new Computer("127.0.0.1", 8000);
}

public Computer(String hostname, int port) throws IOException {
    // Instantiate server socket
    int socketPort = port + identifier + 1;
    System.out.println(socketPort);
    ss = new ServerSocket(socketPort);

    System.out.println("Server Socket Instantiated");

    // Creating sockets (with streams) to write to stream
    for (int i = 0; i < MAX_SYSTEMS; ++i) {
        if (i != identifier) {
            Socket thing1 = new Socket(hostname, port + i + 1);
            ClientSocket cs = new ClientSocket (thing1);
            outputClients.add(cs);
        }
    }

    log.write("Client Sockets Instantiated\n");

    // Create threads for reading objects and updating timestamp
    for (int i = 0; i < MAX_SYSTEMS - 1; ++i) {
        ClientConnection clientConn = new ClientConnection(ss.accept());
        clientConn.start();
        inputClients.add(clientConn);
    }

    log.write("Server connected to clients");

    Random rand = new Random();

    // Writing Events

    int temp;
    while (eventCount < 100) {
        System.out.println("Generating Event");
        int choice = rand.nextInt(5);
        if (choice == 0) {
            temp = timestamp.get(identifier);
            ++temp;
            timestamp.set(identifier, temp);
        } else {
            int randC = rand.nextInt(outputClients.size());
            ClientSocket cc = outputClients.get(randC);
            cc.out.writeObject(new Event(identifier, timestamp));
        }
        System.out.println("Done Generating Event");
    }

    log.write("Computer finished generating events. Continue listening...\n");

    outputToServer.println("Finish");

    // Wait for Tear Down Message
    while (true) {
        try {
            textFromServer = inputFromServer.readLine();
            if (textFromServer.equals("Tear Down")) {
                isAlive = false;
                break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    log.write("Computer shutting off....");

    for (int i = 0; i < outputClients.size(); ++i) {
        ClientSocket sc = outputClients.get(i);
        sc.socket.close();
    }

    sockToServer.close();

}

// client socket class (organizing)
public class ClientSocket {
    Socket socket;
    ObjectOutputStream out;
    ObjectInputStream in;

    public ClientSocket(Socket s) {
        try {
            this.socket = s;
            this.out = new ObjectOutputStream(socket.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Client Socket Created");
    }
}

public class Event implements Serializable {

    private static final long serialVersionUID = 1L;

    Integer from;
    Vector<Integer> timestamp;

    public Event(int identifier, Vector<Integer> timestamp) {
        this.from = identifier;
        this.timestamp = timestamp;
    }

    int getFromID() {
        return from;
    }

    Vector<Integer> getTimestamp() {
        return timestamp;
    }

}

// send event thread
public class ClientConnection extends Thread {
    Socket socket;
    ObjectOutputStream out;
    ObjectInputStream in;
    Random rand = new Random();
    public ClientConnection(Socket s) {
        this.socket = s;
        try {
            out = new ObjectOutputStream (socket.getOutputStream());
            in = new ObjectInputStream (socket.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // execute the event
    private void executeEvent(int from, Vector<Integer> x) {
        int temp;
        synchronized (timestamp) {
            for (int i = 0; i < timestamp.size(); ++i) {
                if (x.get(i) > timestamp.get(i)) {
                    timestamp.set(i, x.get(i));
                }
            }
            temp = timestamp.get(from);
            ++temp;
            timestamp.set(from, temp);
        }
    }

    @Override
    public void run () {
        while (true) {
            System.out.println("Reading events");
            if (!isAlive) { 
                break;
            }
            try {
                Event event = (Event) in.readObject();
                executeEvent(event.getFromID(), event.getTimestamp());
            } catch (ClassNotFoundException e) {

            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(timestamp);
        }
    }
}   
}

TL;DR Trying to read and write object through sockets using Object(Output/Input)Stream object. When I do so, I get the NotSerializableException, even though I implemented the Serializable interface in the class that was being written and read from the stream.

All help is appreciated!

(edit: stacktrace)

java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: timetableexchange.Computer
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.defaultReadFields(Unknown Source)
    at java.io.ObjectInputStream.readSerialData(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at timetableexchange.Computer$ClientConnection.run(Computer.java:239)
Caused by: java.io.NotSerializableException: timetableexchange.Computer
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at timetableexchange.Computer.<init>(Computer.java:128)
    at timetableexchange.Computer.main(Computer.java:39)
java.io.NotSerializableException: timetableexchange.Computer
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
    at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
    at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at timetableexchange.Computer.<init>(Computer.java:128)
    at timetableexchange.Computer.main(Computer.java:39)
7
  • Include the full stacktrace. Commented Nov 18, 2018 at 22:50
  • Did you try implementing the ‘readObject’ and ‘writeObject ‘ methods? Commented Nov 18, 2018 at 23:04
  • @StephenC Sorry about that. included the stacktrace in original post. Commented Nov 19, 2018 at 0:24
  • @JasonArmstrong I don't know what you mean. I added the readobject and writeobject to read and write objects respectively. Do you mean they need to be implemented by the Serializable interface? Commented Nov 19, 2018 at 0:25
  • I didn’t see them implemented in the Event class above. Also, another thing to consider is the Externalizable interface. Commented Nov 19, 2018 at 0:28

1 Answer 1

1

Now that you have supplied the stacktrace .... I see the problem!

You have created Event as an inner class of Computer. That means that an Event has an implicit link to the enclosing Computer instance ... which will be serialized along with the Event instance.

But Computer is not Serializable.

A (probably incorrect) solution would be to make Computer implement Serializable. But that means you would send an instance of Computer with every separately serialized Event ... which is why it is probably wrong.

A better solution would be to declare Event as static so that it doesn't have a reference to the enclosing Computer. As far as I can see, it doesn't need to be an "inner" class. It could just be a "nested" class, or even a top-level class.

Advice: When you use nested and inner classes, make sure that you indent them correctly ... to make it easier for other people to spot what is going on.

Sign up to request clarification or add additional context in comments.

1 Comment

You are absolutely right! Thank you so much! It would make sense since the event class is part of the computer class, the computer class would probably needed to implement the Serializable interface. Now that I moved the Event Class to the highest-level, it worked! Thank you so much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.