Francesco
Francesco

Reputation: 1047

Serializing an object which contains a list of other objects

Background: I am implementing a game which needs to serialize model objects (events) to be able to send them over the network to clients playing the game.

Problem: One of my model classes is EventShowCards, which subclasses Event (declared to be serializable).

public class EventShowCards extends Event {
    private final Player player;
    private final List<ItemCard> cards;

    public EventShowCards(Player player, List<ItemCard> cards) {
        super();
        this.player = player;
        this.cards = cards;
    }

    public Player getPlayer() {
        return player;
    }

    public List<ItemCard> getCards() {
        return cards;
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

However, when I serialize the object and send it to the client, the client receives the object and list of ItemCards is empty. No exceptions are thrown.

Event as shown by the server (before serialization):

Event as shown by the client (after serialization):

In order to serialize/deserialize I am using a standard ObjectOutputStream/ObjectInputStream

Anyone has any idea of what could be happening here? Thanks.

EDIT

As request I am posting the code of the ItemCard (and Card):

ItemCard.java

public abstract class ItemCard extends Card {

    /**
     * By default a card ca be played independently from the game state, subclasses that have more complicated rules
     * must override this method.
     */
    public boolean canBePlayed(GameStateTurn gameState) {
        return true;
    }

    protected void emitEventCardPlayed(Player cardPlayer, GameState gameState)  {
        notifyObservers(new EventCardPlayed(cardPlayer, this));
    }

}

Card.java

public abstract class Card extends ConcreteObservable<Event> implements CardBehavior, Serializable {
    protected Deck<? extends Card> deck; // The deck to which this card belongs

    public Card() {
        super();
    }

    public void setDeck(Deck<? extends Card> deck) {
        this.deck = deck;
    }

    public void discard() {
        deck.discard(this);
    }

    @Override
    public void preEffect(Player cardPlayer, GameState gameState) {
        // By default cards have no preEffects
    }

    @Override
    public void postEffect(Player cardPlayer, GameState gameState) {
        // By default after a card is played it is discarded
        discard();
    }

    @Override
    public String toString() {
        String className = this.getClass().getSimpleName();
        return cardNameFromClassName(className);
    }

    private String cardNameFromClassName(String className) {
        StringBuilder sb = new StringBuilder();
        for (Character c: className.toCharArray()) {
            if (Character.isUpperCase(c)) {
                sb.append(" ").append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return "\"" + sb.substring(1) + "\"";
    }
}

EDIT 2

And Deck.java

public class Deck<T extends Card>
        extends ConcreteObservable<Event>
        implements Observer<Event>, Serializable {...}

EDIT 3

The List of item cards used to initialize the EventShowCards was an already created list from another model object of my application, passed as-is. Creating another ArrayList (copying that object) somehow solved my problem.

Upvotes: 1

Views: 4455

Answers (1)

GingerHead
GingerHead

Reputation: 8230

The List can contain unlimited number of object types.
As you have your EventShowCards serialized (through Event class), you need also to force your ItemCardclass to be serializable in order to be marshalled and unmarshalled when needed correctly.

EDIT

java.util.List doesn't implement Serializable, this is why your list is not serialized.
use other collections which are serializable like ArrayList

Upvotes: 1

Related Questions