2つの別個の(しかし関連する)Javaデスクトップアプリケーションを開発したいと考えています。
あるアプリケーションが他のアプリケーションをトリガーし、データを渡して編集して戻すことができるようにする、つまり通信が双方向であるようにしたいのです。他のアプリケーションがすでに実行されている場合、それらに通信するだけです。つまり、コマンドラインなどで引数を渡すだけではいけません.
一般的に言えば、これを達成するためにどの戦略/手法を検討すべきですか?
2つのアプリケーションが互いに簡単に通信できることを示すために、JGroupsを使用したこのネットワーククリップボードデモをご覧ください。 2つのインスタンスを起動し、それらの1つにファイルをドロップし始めるだけです。 2番目のインスタンスは、同じファイルをすぐに表示します。
import Java.io.Serializable;
import Java.awt.*;
import Java.awt.datatransfer.*;
import javax.swing.*;
import org.jgroups.*;
public class JGroupsTest {
public static void main(String[] args) throws Exception {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500, 300);
final DefaultListModel listModel = new DefaultListModel();
final JList panel = new JList(listModel);
panel.setBackground(new Color(128, 0, 40));
panel.setForeground(new Color(240, 240, 240));
frame.add(panel);
System.setProperty("Java.net.preferIPv4Stack", "true");
final JChannel channel = new JChannel("udp.xml");
channel.connect("networkclipboard");
channel.setReceiver(new ReceiverAdapter() {
@Override
public void viewAccepted(View newView) {
frame.setTitle("Network Clipboard - " + channel.getLocalAddress());
}
@Override
public void receive(Message msg) {
listModel.addElement(msg.getObject());
}
});
panel.setTransferHandler(new TransferHandler() {
@Override
public boolean importData(JComponent comp, Transferable t) {
DataFlavor[] transferDataFlavors = t.getTransferDataFlavors();
for (DataFlavor flavor : transferDataFlavors) {
try {
Object data = t.getTransferData(flavor);
if (data instanceof Serializable) {
Serializable serializable = (Serializable) data;
Message msg = new Message();
msg.setObject(serializable);
channel.send(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return super.importData(comp, t);
}
@Override
public boolean canImport(TransferSupport support) {
return true;
}
@Override
public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
return true;
}
});
}
}
これらの2つのプログラムをどのように伝えたいかによって異なります。
プロセス間セマフォのみが必要な場合は、/ tmpのどこかにファイルを作成してロックします。
プロセス間同期メッセージング(リモートプロシージャコール)のみが必要な場合は、RMIが最も簡単です。
非同期のプロセス間メッセージングが必要な場合、JMSが最も簡単です。
プロセス間共有メモリが必要な場合は、マップされたファイルを使用します。
上記のすべてが必要な場合は、Terracotta(http://www.terracotta.org/)が最も簡単な方法です。同じコンピューターまたは異なるコンピューター上の異なるJVM上のJavaプログラムは、あたかもそれらがそうであるかのように見えます1つのマシン上の1つのJVM内で実行されます。 1つのプログラムをいくつかに分割しても、コードを変更する必要はありません。XML構成ファイルを作成するだけで十分です。
また、昔ながらの優れたRMIも考慮する必要があります。
JavaGroups をご覧ください。通信の問題を解決し、他のアプリが実行されているかどうかを検出するのにも役立ちます。アプリが実行されていない場合は、Java.lang.Runtime.exec()を使用して新しいJVMを起動する必要があります...
アプリケーションが同じマシンにある場合でも、SocketCommunicationと通信してみてください。
方法 (Sun/Javaのドキュメント)に関する詳細情報を参照できます。
「エンタープライズ」の方法は、これらのアプリをJava EEサーバーで、または少なくともSpringフレームワークで実行することです。また、おそらく非常に過剰です。
大量のデータを通信する必要がある場合、RMIが通信します。
独自のプロトコル、データ構造、エラー処理をハッキングすることを恐れない場合は、サーバーとクライアントのソケットをセットアップし、それらを介して通信できます。
共通ディレクトリ内のファイル(ファイルの書き込みまたは消去を行う独自のプロトコルを設定する)を介して、または共有データベースを介して通信する代替手段には、ある種の粗野な魅力があると思います。ローテク、非常に高速ではありませんが、非常にシンプルで信頼性があります。そして、外部から「通信」を監視するのはかなり簡単です。
単純にするために、単純にTCP sockets?
2番目のSocket通信とRMI。 RMIはもう少し複雑ですが、プログラマにとってはより直感的です。ただし、送信する情報の種類によって異なります。未加工のバイトを別のマシンにプッシュすると、RMIサーバーを実行してすべてのジャズを処理するよりも意味があります...
2つのアプリ間でどのようなコミュニケーションを行うかによって異なります。たとえば、ソケットまたはRMIを使用する場合、通信を行うには両方のアプリケーションを起動する必要があります。やりたい種類の通信がより非同期になる場合は、メッセージングベースのアプローチをより多く使用できます。
たとえば、ZooKeeperを使用すると、非常にシンプルでありながら強力なプリミティブの上に、必要なものをほぼすべて実装できます。このページ( http://hadoop.Apache.org/zookeeper/docs/current/recipes.html )では、ZooKeeperを使用してより高いレベルの構成を構築する方法について説明しています。
欠点は、別のシステムが必要なことです。たとえば、JGroupsを使用する場合は、使用しません。
お役に立てれば
探している通信のスタイル(高レイテンシ、大量のデータなど)と、このシステムが単純に2 Javaシステムを超えて拡張する可能性があるかどうか)に応じて、 Tibco SmartSocketsなどのミドルウェアソリューションを使用したメッセージングシステム。
あなたのセットアップと期待に関するこれ以上の情報が役立ちます。