Search code examples
javaserializationobject-graph

Java Serialization of referenced objects is "losing values"?


Good day,

I am having an interesting problem that I cannot understand. I have a class called "HomeScreenManager" which maintains a LinkedList<String> called chat. The HomeScreenManager instance lives on the server and is in charge of keeping track of the connections and the chat log. I then created a class called "ProtocolHomeScreen" which is a class with a LinkedList<String> called chat and implements Serializable. When it comes time to update all the clients with the chat, I want to send out a ProtocolHomeScreen. So I create a brand new instance of the ProtocolHomeScreen and I say that it's linked list of strings "gets" the HomeScreen's linked list. So in other words, the linked list that I want to serialize was created in a different class, but I am pointing to it with another instance. The problem is that the data does not get sent, only an empty LinkedList appears on the other side. I've done the debugger line by line and inspected all the variables and right before I call writeObject everything appears to be fine, but then on the client side, when I receive the ProtocolHomeScreen instance, the linked list is empty! (its not null though) Any ideas? Thank you!

public class HomeScreenManager implements ObjectMessageHandler, Serializable
{
protected LinkedList<User> users;
protected LinkedList<String> chat;
protected LinkedList<String> sessions;

public HomeScreenManager()
{
    chat = new LinkedList<String>();
    users = new LinkedList<User>();
    sessions = new LinkedList<String>();
}
protected void handleChat(String message)
{
    chat.add(message);

    ProtocolHomeScreen p = new ProtocolHomeScreen(this);

    for(User u:users)
    {
        u.connection.WriteObject(p); //At this point in time, p has the correct data, but when I deserialize p, the chat list is empty...
    }
}

Then here is the protocol class...

public class ProtocolHomeScreen implements Serializable
{
    public LinkedList<String> chat;
    public LinkedList<String> players;
    public LinkedList<String> sessions;


    public ProtocolHomeScreen(HomeScreenManager hms)
    {
        players = new LinkedList<String>();
        for(User u:hms.getUsers())
        {
            players.add(u.getUsername());
        }
        sessions = hms.getSessions();
        chat = hms.getChat();

        chat = new LinkedList<String>();

        for(String s: hms.getChat())
        {
            chat.add(s);
        }

    }

}

Edit

This is the code on the client side... note that the player's LinkedList comes across just fine, but I think that has something to do with the fact that I created a new instance in the constructor of the ProtocolHomeScreen (on the server side)

else if(obj instanceof ProtocolHomeScreen)
        {       
            ProtocolHomeScreen phs = (ProtocolHomeScreen) obj;

            sessionModel.removeAllElements();
            playersModel.removeAllElements();
            chatOutput.setText("");
            for(String s:phs.players)
                playersModel.addElement(s);

            for(String s:phs.sessions)
                sessionModel.addElement(s); 

            for(String s:phs.chat)
            {
                chatOutput.setText(chatOutput.getText()+s);
            }

        }

Solution

  • You need to look at ObjectOutputStream.reset() and why it exists. Any given object is only sent once over an ObjectOutputStream unless you reset() the stream or use writeUnshared().