Using Messaging API For Remote Code Execution

Messaging API gives you an easy and powerful tool for remote code execution. The short overview of the API is in Messaging chapter.

All you will need to do is to define specific message class or classes (should be shared between client and server).

The client side can issue messages using:

Java: MessageSender#send(message)

The server side should register a message listener:

Java: Configuration#setMessageRecipient(MessageRecipient)

Message recipient should define a response to the different messages received in

Java: processMessage(ObjectContainer objectContainer, Object message)

method. ObjectContainer parameter gives full control over the database.

Let's reset our database and try updating using special UpdateServer message.

RemoteExample.java: setObjects
01public static void setObjects(){ 02 new File(Util.YAPFILENAME).delete(); 03 ObjectContainer db = Db4o.openFile(Util.YAPFILENAME); 04 try { 05 for (int i = 0; i < 5; i++) { 06 Car car = new Car("car"+i); 07 db.set(car); 08 } 09 db.set(new RemoteExample()); 10 } finally { 11 db.close(); 12 } 13 checkCars(); 14 }
RemoteExample.java: updateCarsWithMessage
01public static void updateCarsWithMessage() { 02 ObjectServer server = Db4o.openServer(Util.YAPFILENAME, 0); 03 server.ext().configure().messageLevel(0); 04 // create message handler on the server 05 server.ext().configure().setMessageRecipient(new MessageRecipient() { 06 public void processMessage(ObjectContainer objectContainer, 07 Object message) { 08 // message type defines the code to be executed 09 if (message instanceof UpdateServer) { 10 Query q = objectContainer.query(); 11 q.constrain(Car.class); 12 ObjectSet objectSet = q.execute(); 13 while (objectSet.hasNext()) { 14 Car car = (Car) objectSet.next(); 15 car.setModel("Updated2-" + car.getModel()); 16 objectContainer.set(car); 17 } 18 objectContainer.commit(); 19 } 20 } 21 }); 22 try { 23 ObjectContainer client = server.openClient(); 24 // send message object to the server 25 MessageSender sender = client.ext().configure().getMessageSender(); 26 sender.send(new UpdateServer()); 27 client.close(); 28 } finally { 29 server.close(); 30 } 31 checkCars(); 32 }

You can also put some information in the message being sent (UpdateServer class).

The advantage of this method is that having predefined message types you can make any changes to the handling code only on the server side. In the situations with many distributed clients it can really save you lots of time on support.