package com.esotericsoftware.kryonet.rmi; import java.io.IOException; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryonet.Client; import com.esotericsoftware.kryonet.Connection; import com.esotericsoftware.kryonet.KryoNetTestCase; import com.esotericsoftware.kryonet.Listener; import com.esotericsoftware.kryonet.Server; public class RmiTest extends KryoNetTestCase { public void testRMI () throws IOException { Server server = new Server(); register(server.getKryo()); startEndPoint(server); server.bind(tcpPort); final ObjectSpace serverObjectSpace = new ObjectSpace(); final TestObjectImpl serverTestObject = new TestObjectImpl(4321); serverObjectSpace.register((short)42, serverTestObject); server.addListener(new Listener() { public void connected (final Connection connection) { serverObjectSpace.addConnection(connection); runTest(connection, 12, 1234); } public void received (Connection connection, Object object) { if (!(object instanceof MessageWithTestObject)) return; MessageWithTestObject m = (MessageWithTestObject)object; System.out.println(serverTestObject.value); System.out.println(((TestObjectImpl)m.testObject).value); assertEquals(4321f, m.testObject.other()); stopEndPoints(2000); } }); // ---- Client client = new Client(); register(client.getKryo()); ObjectSpace clientObjectSpace = new ObjectSpace(client); final TestObjectImpl clientTestObject = new TestObjectImpl(1234); clientObjectSpace.register((short)12, clientTestObject); startEndPoint(client); client.addListener(new Listener() { public void connected (final Connection connection) { RmiTest.runTest(connection, 42, 4321); } public void received (Connection connection, Object object) { if (!(object instanceof MessageWithTestObject)) return; MessageWithTestObject m = (MessageWithTestObject)object; System.out.println(clientTestObject.value); System.out.println(((TestObjectImpl)m.testObject).value); assertEquals(1234f, m.testObject.other()); stopEndPoints(2000); } }); client.connect(5000, host, tcpPort); waitForThreads(); } static public void runTest (final Connection connection, final int id, final float other) { new Thread() { public void run () { TestObject test = ObjectSpace.getRemoteObject(connection, id, TestObject.class); RemoteObject remoteObject = (RemoteObject)test; // Default behavior. RMI is transparent, method calls behave like normal // (return values and exceptions are returned, call is synchronous) test.moo(); test.moo("Cow"); assertEquals(other, test.other()); // Test that RMI correctly waits for the remotely invoked method to exit remoteObject.setResponseTimeout(5000); test.moo("You should see this two seconds before...", 2000); System.out.println("...This"); remoteObject.setResponseTimeout(1000); // Try exception handling boolean caught = false; try { test.asplode(); } catch(UnsupportedOperationException ex) { caught = true; } assertTrue(caught); // Return values are ignored, but exceptions are still dealt with properly remoteObject.setTransmitReturnValue(false); test.moo("Baa"); test.other(); caught = false; try { test.asplode(); } catch(UnsupportedOperationException ex) { caught = true; } assertTrue(caught); // Non-blocking call that ignores the return value remoteObject.setNonBlocking(true); remoteObject.setTransmitReturnValue(false); test.moo("Meow"); assertEquals(0f, test.other()); // Non-blocking call that returns the return value remoteObject.setTransmitReturnValue(true); test.moo("Foo"); assertEquals(0f, test.other()); assertEquals(other, remoteObject.waitForLastResponse()); assertEquals(0f, test.other()); byte responseID = remoteObject.getLastResponseID(); assertEquals(other, remoteObject.waitForResponse(responseID)); // Non-blocking call that errors out remoteObject.setTransmitReturnValue(false); test.asplode(); assertEquals(remoteObject.waitForLastResponse().getClass(), UnsupportedOperationException.class); // Call will time out if non-blocking isn't working properly remoteObject.setTransmitExceptions(false); test.moo("Mooooooooo", 3000); // Test sending a reference to a remote object. MessageWithTestObject m = new MessageWithTestObject(); m.number = 678; m.text = "sometext"; m.testObject = ObjectSpace.getRemoteObject(connection, (short)id, TestObject.class); connection.sendTCP(m); } }.start(); } static public void register (Kryo kryo) { kryo.register(TestObject.class); kryo.register(MessageWithTestObject.class); kryo.register(StackTraceElement.class); kryo.register(StackTraceElement[].class); kryo.register(UnsupportedOperationException.class); ObjectSpace.registerClasses(kryo); } static public interface TestObject { public void asplode(); public void moo (); public void moo (String value); public void moo (String value, long delay); public float other (); } static public class TestObjectImpl implements TestObject { public long value = System.currentTimeMillis(); private final float other; public TestObjectImpl (int other) { this.other = other; } public void asplode() { throw new UnsupportedOperationException("Why would I do that?"); } public void moo () { System.out.println("Moo!"); } public void moo (String value) { System.out.println("Moo: " + value); } public void moo (String value, long delay) { System.out.println("Moo: " + value); try { Thread.sleep(delay); } catch (InterruptedException e) { e.printStackTrace(); } } public float other () { return other; } } static public class MessageWithTestObject { public int number; public String text; public TestObject testObject; } }