Error passing object and invoking method

148 views
Skip to first unread message

Daniel

unread,
Nov 30, 2010, 1:31:13 AM11/30/10
to kryonet-users
Hi I am trying to create a game in which I need to pass the Board
"object" from the server to the client every time the board is updated
with a new move from the player. The board is a JPanel that contains
all the pieces and information. I have registered the board class in
kryonet but it is serializing wrong I believe and seems like the
server can not invoke the update board method on my client which
receives the board object from the server and displays it.

Here is the error code....

Exception in thread "Server" java.lang.RuntimeException: Error
invoking method: monopolynetworked.IPlayer.updateBoard
at
com.esotericsoftware.kryonet.rmi.ObjectSpace.invoke(ObjectSpace.java:
181)
at com.esotericsoftware.kryonet.rmi.ObjectSpace
$1.received(ObjectSpace.java:64)
at
com.esotericsoftware.kryonet.Connection.notifyReceived(Connection.java:
262)
at com.esotericsoftware.kryonet.Server.update(Server.java:191)
at com.esotericsoftware.kryonet.Server.run(Server.java:320)
at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
com.esotericsoftware.kryonet.rmi.ObjectSpace.invoke(ObjectSpace.java:
179)
... 5 more
Caused by: java.lang.NullPointerException
at
com.esotericsoftware.kryo.serialize.StringSerializer.put(StringSerializer.java:
29)
at monopolynetworked.Network$1.write(Network.java:45)
at monopolynetworked.Network$1.write(Network.java:42)
at
com.esotericsoftware.kryo.serialize.SimpleSerializer.writeObjectData(SimpleSerializer.java:
17)
at
com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:480)
at com.esotericsoftware.kryonet.rmi.ObjectSpace
$InvokeMethod.writeObjectData(ObjectSpace.java:395)
at
com.esotericsoftware.kryo.serialize.CustomSerializer.writeObjectData(CustomSerializer.java:
28)
at
com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:480)
at
com.esotericsoftware.kryonet.TcpConnection.send(TcpConnection.java:
184)
at
com.esotericsoftware.kryonet.Connection.sendTCP(Connection.java:67)
at com.esotericsoftware.kryonet.rmi.ObjectSpace
$RemoteInvocationHandler.invoke(ObjectSpace.java:301)
at $Proxy0.updateBoardRecieving(Unknown Source)
at monopolynetworked.Player.updateBoard(Player.java:48)
... 10 more


My update method in the client....

public void updateBoardRecieving(final Board newBoard) {


EventQueue.invokeLater(new Runnable() {

public void run() {

System.out.println("hi updating");
board = newBoard;
boardPanelHolder.add(board);
validate();

}
});
}
}



And the server calling the update

public void updateBoard() {
System.out.println("hi");
for (Player player : players) {
System.out.println(player.playerName);
player.frame.updateBoardRecieving(board);
}
}


Any help would be appreciated.

-Daniel



Nate

unread,
Nov 30, 2010, 5:06:41 AM11/30/10
to kryone...@googlegroups.com
Hi Daniel,

The first inner class in your class named monopolynetworked.Network calls StringSerializer.put with a null value. A String object value must be passed to this method, null is not accepted. Create a StringSerializer instance field on your class or call kryo.getSerializer(String.class) and call writeData, which can accept null.

-Nate





--
You received this message because you are subscribed to the "kryonet-users" group.
http://groups.google.com/group/kryonet-users

Daniel Brooks

unread,
Nov 30, 2010, 5:19:36 PM11/30/10
to kryone...@googlegroups.com

Thanks Nate I was able to get past that error buy setting the Boards component name, but now I'm not quite sure how to fix the serializer error I am receiving:

Exception in thread "Server" java.lang.RuntimeException: Error invoking method: monopolynetworked.IPlayer.updateBoard
        at com.esotericsoftware.kryonet.rmi.ObjectSpace.invoke(ObjectSpace.java:181)
        at com.esotericsoftware.kryonet.rmi.ObjectSpace$1.received(ObjectSpace.java:64)
        at com.esotericsoftware.kryonet.Connection.notifyReceived(Connection.java:262)
        at com.esotericsoftware.kryonet.Server.update(Server.java:191)
        at com.esotericsoftware.kryonet.Server.run(Server.java:320)
        at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at com.esotericsoftware.kryonet.rmi.ObjectSpace.invoke(ObjectSpace.java:179)
        ... 5 more
Caused by: java.lang.ClassCastException: monopolynetworked.Board cannot be cast to java.lang.Class
        at monopolynetworked.Network$1.write(Network.java:43)
        at com.esotericsoftware.kryo.serialize.SimpleSerializer.writeObjectData(SimpleSerializer.java:17)
        at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:480)
        at com.esotericsoftware.kryonet.rmi.ObjectSpace$InvokeMethod.writeObjectData(ObjectSpace.java:395)
        at com.esotericsoftware.kryo.serialize.CustomSerializer.writeObjectData(CustomSerializer.java:28)
        at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:480)
        at com.esotericsoftware.kryonet.TcpConnection.send(TcpConnection.java:184)
        at com.esotericsoftware.kryonet.Connection.sendTCP(Connection.java:67)
        at com.esotericsoftware.kryonet.rmi.ObjectSpace$RemoteInvocationHandler.invoke(ObjectSpace.java:301)
        at $Proxy0.updateBoardRecieving(Unknown Source)
        at monopolynetworked.Player.updateBoard(Player.java:48)
        ... 10 more




I think that I am serializing it wrong, but I can't find any documentation on how to do this the right way. Here is the code I m using to register it with kryo which I found on the forums:

    kryo.register(Board.class, new SimpleSerializer<Class>() {

            public void write(ByteBuffer buffer, Class c) {
                StringSerializer.put(buffer, c.getName());
            }

            public Class read(ByteBuffer buffer) {
                String className = StringSerializer.get(buffer);
                try {
                    return Class.forName(className);
                } catch (ClassNotFoundException ex) {
                    throw new SerializationException("Unable to find class: " + className, ex);
                }
            }
        });

Any help would be appreciated..

-Daniel

Nate

unread,
Nov 30, 2010, 6:26:48 PM11/30/10
to kryone...@googlegroups.com
Hi Daniel,

Oh boy. :D

The documentation you are looking for is here:
http://code.google.com/p/kryo/
And here:
http://kryo.googlecode.com/svn/api/index.html

The SimpleSerializer methods write() an object to bytes and read() bytes to create an object. When you register a serializer for your Board class with Kryo, the object being written/read should be an instance of Board, not an instance of Class. IE, use new SimpleSerializer<Board> and not new SimpleSerializer<Class>.

In your write() method you need to write the data for each field that makes up a Board instance. In the read() method you need to create a new instance of your class, read the data for each field, and assign it to your instance. This is the manual way of serializing an object using Kryo.

Kryo has serializers that have various generic mechanisms to write and read data for objects without having to write code manually for each field. For networking, the serializer that is usually used is FieldSerializer:
http://kryo.googlecode.com/svn/api/index.html?com/esotericsoftware/kryo/serialize/FieldSerializer.html

If your Board class extends JPanel, it won't be easy to use FieldSerializer because JPanel has a bunch of fields that FieldSerializer will find and want to serialize. You can tell FieldSerializer to ignore specific fields or ignore all private fields. However, you would be better off decoupling your UI from your data, and then you could more easily send your data.

You could go even further and only send updates to the game board, rather than sending the entire game board every time anything changes. However, it is generally best to get something working first, then later you can work on improving the design.

-Nate
Reply all
Reply to author
Forward
0 new messages