55 votes

Communication entre deux applications de bureau Java distinctes

Je cherche à développer deux applications de bureau Java distinctes (mais liées).

Je veux qu'une application puisse déclencher l'autre, en lui transmettant des données qui peuvent ensuite être éditées et renvoyées, c'est-à-dire que la communication sera bidirectionnelle. Si l'autre application est déjà en cours d'exécution, je veux qu'elles communiquent simplement, c'est-à-dire que je ne veux pas simplement passer des arguments par la ligne de commande, etc.

D'une manière générale, quelles stratégies/techniques dois-je envisager pour y parvenir ?

1 votes

Excellente question. L'avez-vous déjà mise en œuvre ?

0 votes

Pas encore... il s'agissait d'une recherche initiale pour un projet à venir :)

1 votes

Les personnes qui votent la réouverture peuvent-elles exprimer leur raisonnement ?

24voto

mhaller Points 10002

Pour montrer à quel point il est facile de permettre à deux applications de communiquer entre elles, regardez cette démonstration de tableau de bord réseau utilisant JGroups. Il suffit de lancer deux instances et de commencer à déposer des fichiers dans l'une d'elles. La seconde instance affichera instantanément les mêmes fichiers.

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

        });
    }

}

0 votes

Salut @mhaller Je voulais savoir s'il y a une raison spécifique pour laquelle vous avez utilisé throws sur main comme main est une méthode spécifique, nous l'entourons de try catch . Veuillez préciser.

0 votes

@Vishrant - j'étais juste paresseux. Il est permis d'utiliser throws pour la méthode principale, cela ne fait pas de différence. Je déclare aussi souvent throws Exception pour les tests unitaires, afin de ne pas avoir à traiter individuellement toutes les exceptions vérifiées.

0 votes

Merci de votre réponse, j'utilise principalement throws lorsqu'il y a un conteneur comme dans struts mais pendant que j'écris main dans mon application (qui est une méthode spécifique et non une méthode commune) j'utilise try catch pour traiter Exception à ma façon. Oui, en utilisant throws sur main fait une différence si une méthode Exception se produit dans main il sera envoyé à la méthode JVM et votre programme s'arrêtera, également JVM poignées jetées Exception à sa manière. throws est un concept de re-throwing Exception qui est utilisé dans Common Methods (méthodes qui sont utilisées par de nombreuses classes).

23voto

iirekm Points 2338

Cela dépend de la manière dont vous souhaitez communiquer avec ces deux programmes :

  • Si vous n'avez besoin que de sémaphores inter-processus, créez un fichier quelque part dans /tmp et verrouillez-le.

  • Si vous n'avez besoin que d'une messagerie synchrone interprocessus (appel de procédure à distance), RMI devrait être le plus simple.

  • Si vous avez besoin d'une messagerie interprocessus asynchrone, JMS devrait être le plus simple.

  • Si vous avez besoin de mémoire partagée inter-processus, utilisez des fichiers mappés.

  • Si vous avez besoin de tout cela, Terracotta (http://www.terracotta.org/ ) est le moyen le plus simple : Les programmes Java sur différentes JVM sur le même ordinateur ou même sur des ordinateurs différents se voient les uns les autres comme s'ils étaient exécutés dans une JVM sur une seule machine. La division d'un programme en plusieurs autres ne nécessite même pas de modification du code - il suffit d'écrire un fichier de configuration XML.

19voto

BalusC Points 498232

Ils pourraient chacun écouter sur un Socket . Ce tutoriel est bon pour commencer.

0 votes

Est-ce que c'est la façon habituelle de faire ou RMI ? Ou plutôt, quelle est la différence ?

0 votes

@Pacerier - Les sockets sont un moyen de transmettre des octets à une pile réseau. RMI permet d'appeler des méthodes d'objets qui existent dans une JVM différente, l'échange de données est opaque à RMI mais peut toujours utiliser des sockets en dessous.

0 votes

Ic, donc les sockets sont les meilleurs alors puisque c'est simple et rapide.

10voto

Xepoch Points 4018

Vous devriez également envisager le bon vieux RMI classique.

0 votes

Est-ce l'approche habituelle lorsque je veux avoir deux processus différents ?

0 votes

C'est la manière élémentaire de faire passer des objets Java d'une JVM à l'autre (souvent sous forme de processus différents). Vous pouvez également partager des références d'objets pour agir sur des objets distants dans l'autre JVM. Bien sûr, toute l'histoire des EJB et les frameworks tentent, sans succès, de faire abstraction de RMI, mais il s'agit d'une véritable approche des objets partagés entre plusieurs JVM. Pour être honnête, il s'agit d'un moyen d'invoquer des méthodes distantes, mais la plupart des méthodes renvoient ou se voient passer des objets de toute façon.

6voto

pgras Points 7202

Jetez un coup d'œil à JavaGroups Cela résoudra votre problème de communication et vous aidera également à détecter si l'autre application est en cours d'exécution. Si l'application n'est pas en cours d'exécution, vous devrez lancer une nouvelle JVM pour elle avec java.lang.Runtime.exec()...

1 votes

+1 pour JGroups, je l'adore. Pour info, vous savez que cette page a 10 ans et que ce même code a été adopté par JBoss depuis des années maintenant ? Voir jgroups.org

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X