以对象模型作为参数启动java程序

时间:2009-07-19 18:44:11

标签: java remoting

服务器侦听端口,等待来自客户端的传入请求(客户端实际上是一个ejb)。这些请求将完整的对象模型作为参数传递(例如,员工列表,每个员工的任务列表等)。

现在,服务器必须在同一台机器上的新JVM实例中启动另一个java程序,并将此对象模型作为参数。

这个其他java程序应该是一个独立的java程序,但我不能将对象模型作为参数传递给main方法(void main(String[] args))。

那该怎么办?我正在寻找一个“简单”的解决方案,例如最好没有数据库或文件以保持持久性。 独立程序实际上是CPU密集型的,不能由应用程序服务器托管。

THX。

6 个答案:

答案 0 :(得分:4)

运行应用程序并捕获其输入/输出流,然后通过它流式传输序列化对象模型。新应用程序应该反序列化来自System.in的输入。

概念的例子(我只想确保我的示例有效,抱歉延迟):

package tests;

import java.io.File;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class AppFirst {
    public static void main(String[] args) throws Exception {
        ProcessBuilder pb = new ProcessBuilder("java", "-cp", 
            "./bin", "tests.AppSecond");
        pb.directory(new File("."));
        pb.redirectErrorStream(true);
        Process proc = pb.start();

        ObjectOutputStream out = new ObjectOutputStream(
            proc.getOutputStream());
        ObjectInputStream oin = null;

        for (int i = 0; i < 1000; i++) {
            out.writeObject("Hello world " + i);
            out.flush();
            if (oin == null) {
                oin = new ObjectInputStream(proc.getInputStream());
            }
            String s = (String)oin.readObject();
            System.out.println(s);
        }
        out.writeObject("Stop");
        out.flush();

        proc.waitFor();
    }
}

package tests;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class AppSecond {
    public static void main(String[] args) throws Exception {
        ObjectInputStream oin = null;
        ObjectOutputStream out = new ObjectOutputStream(System.out);
        while (true) {
            if (oin == null) {
                oin = new ObjectInputStream(System.in);
            }
            String s = (String)oin.readObject();
            if ("Stop".equals(s)) {
                break;
            }
            out.writeObject("Received: " + s);
            out.flush();
        }
    }
}

修改:添加了循环版本。请注意,OOS需要一个技巧,因为它立即开始读取传入的流(并阻止您的应用程序如果您在错误的步骤执行它 - 它应该被包装 AFTER 第一个对象被发送到子进程)。

答案 1 :(得分:1)

您可以序列化对象并将其写入文件系统。然后,您可以在运行时读取该序列化对象。或者,您可以使用JMS将该对象作为字节流传输。

More on serialization

More on JMS。我一直使用ActiveMQ,这是一个满足我JMS需求的Apache项目。它易于使用和高度scalabe。哦是的,它是免费的。

答案 2 :(得分:1)

看看RMI。您的服务器可以启动新服务,然后将其自身发布并导出到本地注册表。然后,您的新服务可以将对象模型作为远程扩展方法的参数接收。应该非常简单,不需要文件访问或额外的服务,也不会比任何其他答案更重要。

答案 3 :(得分:0)

一种方法是原始JVM打开一个用于侦听的套接字,新的JVM实例运行一个程序,该程序连接到该套接字并通过套接字接收参数(Java的默认序列化可能已经足够好了)。这样,您只需要将套接字端口号作为参数传递给main,而不需要文件/数据库。同样的方法也可用于在JVM之间传递其他命令。

答案 4 :(得分:0)

无论哪种方式,您都无法传递内存中存在的对象模型。如果你想传递对象模型,你将不得不找到一种方法来编码和解码你可以传递的东西。

由于数据已经通过EJB发送,因此对象序列化是显而易见的选择,尽管XML,JSON等没有任何问题。

您还需要将服务器程序中的对象提供给新调用的JVM。如果对象模型足够小,则可以将序列化对象作为命令行参数传递给java程序。您也可以像George IV建议的那样,将其写入文件系统,然后告诉您的新应用程序在哪里可以找到包含序列化数据的文件。你可以使用JMS。网页服务。套接字。

但是如果您的服务器应用程序已经基于EJB,那么最简单的方法就是让您的新应用程序在EJB层上作为EJB客户端调用,以请求您正在查找的数据。

答案 5 :(得分:0)

序列化方法很好。此外,您需要的是根对象,以便对调用的相关对象进行一些引用。我过去做的是序列化一个完整的对象图,让root对象实现一些接口,如Runnable,然后在接收节点上将这个根对象强制转换为Runnable并执行{{1} } 在上面。