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

时间:2021-07-28 00:32:12

A server listens on a port, waiting for incoming requests from clients (the client as a matter of fact is an ejb). These requests pass a complete object model as parameter (e.g. a list of Employees, each Employee a list of Tasks etc.).

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

Now the server has to start another java program in a new JVM instance on the same machine, with this object model as a parameter.

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

This other java program should be a standalone java program, but I cannot pass the object model as a parameter to the main method (void main(String[] args)).

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

So what to do? I am looking for a "simple" solution, e.g. preferably without a database or a file for persistancy. The stand alone program is really cpu intensive and cannot be hosted by an appserver.

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

Thx.

6 个解决方案

#1


Run the application and capture its in/out streams, then stream the serialized object model through it. The new application should deserialize input coming from System.in .

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

Example of the concept (I just wanted to make sure my example works, sorry for the delay):

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

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();
        }
    }
}

Edit: Added a looping version. Note that there needs to be a trick with the OOS, as it instantly starts to read the passed in stream (and blocks your app If you do it at the wrong step - it should be wrapped AFTER the first object is sent out to the child process).

编辑:添加循环版本。请注意,OOS需要一个技巧,因为它立即开始读取传入的流(并阻止你的应用程序如果你在错误的步骤执行它 - 它应该在第一个对象发送给孩子后被包裹处理)。

#2


Have a look at RMI. Your server could start up the new service which in turn publishes and exports itself to a local registry. Then your new service can receive the object model as a parameter to a Remote-extending method. Should be very simple, requires no file access or an additional service, and no more heavyweight than any of the other answers.

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

#3


You could serialize the object and write it to the file system. Then, you can read in that serialized object at runtime. Alternatively, you could use JMS to transfer that object as a stream of bytes.

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

More on serialization.

更多关于序列化。

More on JMS. I have always used ActiveMQ, an Apache project for my JMS needs. It is easy to use and highly scalabe. Oh yeah, and it's free.

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

#4


One way would be that the original JVM opens a socket for listening, and the new JVM instance runs a program that connects to that socket and receives the parameters through the socket (Java's default serialization will probably be good enough). That way you only need to pass the socket port number as a parameter to main, and no files/databases are needed. The same method can also be used to communicate other commands between the JVMs.

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

#5


Either way, you can't pass an object model as it exists in memory. If you want to pass the object model, you're going to have to find a way to encode and decode that model into something you can pass.

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

Since the data's already being sent via EJB, object serialization's the obvious choice, although there's nothing wrong with XML, JSON, etc.

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

You also need to get the object from your server program to the newly-invoked JVM. If the object model is small enough, you could pass the serialized object to the java program as a command-line argument. You could also, as George IV has suggested, write it to the file system and then tell your new application where to find the file containing the serialized data. You could use JMS. Web services. Sockets.

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

But if your server application is already EJB-based, the simplest thing to do is to have your new application invoke on the EJB layer as an EJB client to request the data you're looking for.

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

#6


The serialization approach is good enaugh. What you need in addition is the root object to carry some references to the relevant objects to the call. What I did in the past was to serialize a complete object graph and to let the root object implement some interface like Runnable and then on the receiving node cast this root object to Runnable and execute run() on it.

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

#1


Run the application and capture its in/out streams, then stream the serialized object model through it. The new application should deserialize input coming from System.in .

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

Example of the concept (I just wanted to make sure my example works, sorry for the delay):

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

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();
        }
    }
}

Edit: Added a looping version. Note that there needs to be a trick with the OOS, as it instantly starts to read the passed in stream (and blocks your app If you do it at the wrong step - it should be wrapped AFTER the first object is sent out to the child process).

编辑:添加循环版本。请注意,OOS需要一个技巧,因为它立即开始读取传入的流(并阻止你的应用程序如果你在错误的步骤执行它 - 它应该在第一个对象发送给孩子后被包裹处理)。

#2


Have a look at RMI. Your server could start up the new service which in turn publishes and exports itself to a local registry. Then your new service can receive the object model as a parameter to a Remote-extending method. Should be very simple, requires no file access or an additional service, and no more heavyweight than any of the other answers.

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

#3


You could serialize the object and write it to the file system. Then, you can read in that serialized object at runtime. Alternatively, you could use JMS to transfer that object as a stream of bytes.

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

More on serialization.

更多关于序列化。

More on JMS. I have always used ActiveMQ, an Apache project for my JMS needs. It is easy to use and highly scalabe. Oh yeah, and it's free.

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

#4


One way would be that the original JVM opens a socket for listening, and the new JVM instance runs a program that connects to that socket and receives the parameters through the socket (Java's default serialization will probably be good enough). That way you only need to pass the socket port number as a parameter to main, and no files/databases are needed. The same method can also be used to communicate other commands between the JVMs.

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

#5


Either way, you can't pass an object model as it exists in memory. If you want to pass the object model, you're going to have to find a way to encode and decode that model into something you can pass.

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

Since the data's already being sent via EJB, object serialization's the obvious choice, although there's nothing wrong with XML, JSON, etc.

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

You also need to get the object from your server program to the newly-invoked JVM. If the object model is small enough, you could pass the serialized object to the java program as a command-line argument. You could also, as George IV has suggested, write it to the file system and then tell your new application where to find the file containing the serialized data. You could use JMS. Web services. Sockets.

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

But if your server application is already EJB-based, the simplest thing to do is to have your new application invoke on the EJB layer as an EJB client to request the data you're looking for.

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

#6


The serialization approach is good enaugh. What you need in addition is the root object to carry some references to the relevant objects to the call. What I did in the past was to serialize a complete object graph and to let the root object implement some interface like Runnable and then on the receiving node cast this root object to Runnable and execute run() on it.

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