RPCとシリアライズのテスト

XML-RPCシリアライズの機能を加えて、こんなテストコードができた。オブジェクトが文字通りマシンを超えて生き続けるのは、なんだか面白い。
今のところ既知のクラスしか送れないけど、Javaにはネットワーク上にあるパッケージを透過的にダウンロードする機能があったはずなので、それと組み合わせるとあらゆるオブジェクトがネットワーク上を移動することができるようになったりして。自己増殖するオブジェクトとか新しいクラスを合成するオブジェクトなんかが現れると、これはもう生物と呼べるかもしれない。(通信経路のノイズで突然変異したり)

  • Master.java(要求を出して操作する側)
import java.util.Vector;
import java.util.Hashtable;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.beans.XMLEncoder;
import org.apache.xmlrpc.XmlRpcClient;
import org.apache.xmlrpc.XmlRpcException;

public class Master {

    public static void persistent(Object obj, OutputStream stream) {
        XMLEncoder encoder = new XMLEncoder(stream);
        encoder.writeObject(obj);
        encoder.close();
    }

    public static String persistentToString(Object obj) {
        OutputStream stream = new ByteArrayOutputStream();
        persistent(obj, stream);
        return stream.toString();
    }

    public static void persistentToFile(Object obj, String filename) {
        try {
            persistent(obj, new FileOutputStream(filename));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    private String serverUrl = "http://localhost:18080/";
    private String handlerName = "test";

    private XmlRpcClient server;

    public Master() throws MalformedURLException {
        server = new XmlRpcClient(serverUrl);
    }

    public Master(String serverUrl) throws MalformedURLException {
        this.serverUrl = serverUrl;
        server = new XmlRpcClient(serverUrl);
    }

    public void sendObject(Object obj) {
        Vector params = new Vector();
        params.addElement(persistentToString(obj));

        Object result = executeRPC("test", params);
        System.out.println(result.toString());
    }

    Object executeRPC(String methodName, Vector params) {
        try {
            String procedureName = handlerName + "." + methodName;
            return server.execute(procedureName, params);
        } catch (XmlRpcException e) {
            System.err.println("Master: XML-RPC Fault #" +
                               e.code + ": " +
                               e.toString());
            System.exit(0);
            // no reachable.
            return null;
        } catch (IOException e) {
            System.err.println("Master: IOException: " +
                               e.toString());
            System.exit(0);
            // no reachable.
            return null;
        }
    }

}
  • Slave.java(要求を受けて操作される側)
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.net.InetAddress;
import java.util.Vector;
import javax.swing.JFrame;
import java.beans.XMLDecoder;
import org.apache.xmlrpc.WebServer;
import org.apache.xmlrpc.XmlRpcHandler;

public class Slave implements XmlRpcHandler {

    private int port = 18080;
    private String handlerName = "test";
    private WebServer server;

    public Slave() {
        server = new WebServer(port);
        server.addHandler(handlerName, this);
    }

    public Object realize(String serializedObject) {
        InputStream stream = new ByteArrayInputStream(serializedObject.getBytes());
        XMLDecoder d = new XMLDecoder(stream);
        return d.readObject();
    }

    public Object execute(String method, Vector params) throws Exception {

        System.out.println("Slave: execute");

        if (!method.equals("test.test")) {
            throw new Exception("I do not have the method: " + method);
        }

        String serializedObject = (String)params.get(0);
        JFrame frame = (JFrame)realize(serializedObject);

        String hostName = InetAddress.getLocalHost().getHostName();

        frame.setTitle("Shown by slave @ " + hostName + ".");
        frame.setVisible(true);

        return new Boolean(true);
    }

    public void run() {
        System.out.println("Slave: running...");
        server.start();
    }

    public static void main (String[] args) {
        Slave slave = new Slave();
        slave.run();
    }

}
  • PersistentTest.java(テストのためのクラス)
import java.net.InetAddress;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JTextField;

public class PersistentTest implements ActionListener {

    public static JFrame getFrame(String url) {
        PersistentTest test;
        test= new PersistentTest(url);
        return test.frame;
    }

    private Master master;
    private JFrame frame;

    public PersistentTest(String url) {
        frame = new JFrame();

        frame.setTitle("PersistentTest");
        frame.setBounds(100, 100, 200, 100);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        Container container = frame.getContentPane();
        container.setLayout(new BorderLayout());

        JButton button = new JButton("OK");
        button.addActionListener(this);

        container.add(new JTextField("Hello, Java World!"),
                      BorderLayout.CENTER);

        container.add(button, BorderLayout.SOUTH);

        try {
            if (url != null) {
                master = new Master(url);
            } else {
                master = new Master();
            }
        } catch (java.net.MalformedURLException e) {
        }
    }

    public void actionPerformed(ActionEvent ae) {
        master.sendObject(frame);
    }

    public static void main(String[] args) {
        try {
            String url = null;
            if (args.length > 0) {
                url = args[0];
            }
            JFrame frame = PersistentTest.getFrame(url);

            String hostName = InetAddress.getLocalHost().getHostName();
            frame.setTitle("Shown by master @ " + hostName + ".");

            frame.setVisible(true);
        } catch (java.net.UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

それはそうと、今話題のDependency Injection(DI)って、この例の中でPersistentTestがやってるようなこととは違うのかな? このページを読んでも、いまいちこのパターンが理解できていない。