Vous êtes ici : InformatiqueProgrammationJava(Re)prise en main de Java et Eclipse

(Re)prise en main de Java et Eclipse

eclipse logoJe poursuis ma remise à niveau avec Java et Eclipse.

Carrément déçu par mon expérience malheureuse avec Windev express, on va développer une version Java de xplsensors. Si vous désirez installer cette application pas à pas, consultez cet article.

Au programme de cet exemple : thread, socket réseau, préférences et ant !!!

 

 

Le cahier des charges

Développer une version Java de JxPLSensor. Il s'agit d'une application qui envoie des informations sur le matériel (espace disque disponible, températures, vitesse des ventilateurs, ...) sur le réseaux XPL. Ces informations sont collectées et mise en graphiques (Domogik).

Pour faire simple, XPL est un bus domotique qui utilise le mode de transmission UDP.

Ainsi, un message XPL est diffusé à l'ensemble des acteurs du réseau (192.168.1.255 par exemple) sur le port UDP 3865. Si plusieurs acteurs doivent cohabiter sur le même hôte alors un hub est nécessaire. Les acteurs "locaux" s'adressent alors au hub, qui dispatch le message sur le réseau. De même, un message reçu par le hub sur le réseau est retransmis à tous les acteurs "locaux".

Afin d'être découvert sur le réseau XPL, un acteur doit émettre des heartbeats. Il doit également répondre aux demandes, afin par exemple, d'informer le hub qu' il est toujours en vie.

Pour finir ce cahier des charges succinct, l'application doit s'exécuter sur Windows et Linux avec/sans interface graphique.

Pour ce qui est des capteurs sous Windows, la charge de développement est conséquente. Les informations sont disponibles via le WMI et le modèle de communication inter-process COM propriétaire à Microsoft. Il faut donc passer par l'installation de bibliothèques externes et d'un développement conséquent qui sortent du cadre de cet article.

XPL / UDP

Les threads vous connaissez ? et bien vous allez connaître. Pour avoir déjà essayé de développer une application client/serveur dans un langage "linéaire", je peux vous affirmer que les threads vont vous permettre de gagner en efficacité et en performances.

Je vous parle d'un temps, que les moins de vingt ans, ne peuvent pas connaître. Basic en ce temps là ne nous proposait que le goto et le gosub :)

De plus, les machines sont (et seront de plus en plus) multi-core, technologie qui ne peut être exploité pleinement que par les applications multi-thread.

Assez de blah-blah, du code !!! Enfin des bribes de code, pour le projet eclipse complet dirigez-vous vers la fin de ce document.

public class XplHeartbeat extends Thread {
    private boolean shouldStop = false;
    private int delay = 300;
    private XplUdpClient udpClient = null;

    public XplHeartbeat(XplUdpClient udpclient, int mydelay) {
        udpClient=udpclient;
        delay=mydelay*1000;
    }

    public void stopNow() {
        shouldStop = true;
    }

    public void run() {
        while( shouldStop == false) {
            // traitement
            try {
                udpClient.sendHeartbeat("*",0);
                System.gc();
                sleep(delay);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
       }
   }
}

C'est cette classe qui émet le heartbeat à intervalle régulier. J'en profite également pour effecteur un garbage coolector, afin de réduire l'empreinte du logiciel en mémoire. Comme on peut le voir, elle passe la majorité de son temps à dormir ... une vraie marmotte. L'appel à sleep informe le système d'exploitation que le processus doit être repris dans un certain temps. Celui-ci peut ainsi distribuer le CPU aux autres processus de manière optimale.

Ce n'est pas la classe elle-même qui émet le heartbeat, c'est la classe XplUdpClient qui le fait depuis son propre thread. Pourquoi ? Tout simplement, car on doit pouvoir répondre aux heartbeats (depuis le thread XplUdpServer) et que pour répondre strictement aux spécifications XPL, cette réponse soit temporisée.

Ainsi, dans la classe XplUdpClient, on a le code suivant pour emettre le heartbeat :

public void sendHeartbeat(String target, int delayed) {
    if (delayed>0) {
        try {
            sleep(delayed);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    String XplMessage;
    XplMessage="xpl-stat" + "\n";
    XplMessage=XplMessage + "{"+"\n";
    XplMessage=XplMessage + "hop=1"+"\n";
    XplMessage=XplMessage + "source=xpl-sensor." + hostName + "\n";
    XplMessage=XplMessage + "target=" + target + "\n";
    XplMessage=XplMessage + "}" + "\n";
    XplMessage=XplMessage + "hbeat.app" + "\n";
    XplMessage=XplMessage + "{" + "\n";
    XplMessage=XplMessage + "interval=" + hbDelay + "\n";
    XplMessage=XplMessage + "port=" + serverPort + "\n";
    XplMessage=XplMessage + "remote-ip=" + serverIp.getHostAddress() + "\n";
    XplMessage=XplMessage + "}" + "\n";
    byte[] message = XplMessage.getBytes();
    DatagramPacket sendPacket =
    new DatagramPacket(message, message.length, networkIp, 3865);
    try {
        clientSocket.send(sendPacket);
        if (log!=null) log.addLog("Heartbeat sent to "+target+".");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

A l'entrée, si un délay est demandé, alors le thread s'endort ... encore ... En ensuite, on envoie le message.

Ce délai est utilisé en réponse aux demandes de heartbeat depuis la classe UdpXplServer :

 public void sendHeartbeat(String target, int delayed) {
 if (delayed>0) {
 try {
 sleep(delayed);
 } catch (InterruptedException e) {
// TODO Auto-generated catch block
 e.printStackTrace();
 }
 }
 String XplMessage;
 XplMessage="xpl-stat" + "\n";
 XplMessage=XplMessage + "{"+"\n";
 XplMessage=XplMessage + "hop=1"+"\n";
 XplMessage=XplMessage + "source=xpl-sensor." + hostName + "\n";
 XplMessage=XplMessage + "target=" + target + "\n";
 XplMessage=XplMessage + "}" + "\n";
 XplMessage=XplMessage + "hbeat.app" + "\n";
 XplMessage=XplMessage + "{" + "\n";
 XplMessage=XplMessage + "interval=" + hbDelay + "\n";
 XplMessage=XplMessage + "port=" + serverPort + "\n";
 XplMessage=XplMessage + "remote-ip=" + serverIp.getHostAddress() + "\n";
 XplMessage=XplMessage + "}" + "\n";
 byte[] message = XplMessage.getBytes();
 DatagramPacket sendPacket = 
 new DatagramPacket(message, message.length, networkIp, 3865);
          try {
 clientSocket.send(sendPacket);
 if (log!=null) log.addLog("Heartbeat sent to "+target+".");
 } catch (IOException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
     }
      }

if (sCmd.equals("request")) {
    //System.out.println("REQUEST detected");
    //System.out.println("SOURCE "+sSource);
    if (sTarget.equals("xpl-sensor."+hostname)) {
        //System.out.println("SEND HEARTBEAT ........" );
        udpClient.sendHeartbeat(sSource,0);
    } else if (sTarget.equals("*")) {
        //System.out.println("SEND HEARTBEAT ........" );
        udpClient.sendHeartbeat(sSource,1514);
    }

Ainsi quand une demande de heartbeat est formulée à l'adresse de tous les acteurs, la réponse est differée de 1514 millisecondes.

L'API Preferences

Un développeur est souvent confronté à la problématique de la sauvegarde des choix (ou des paramètres) de l'utilisateur lors du développement d'une application. Le classique fichier texte devient rapidement difficille à gérér en fonctions des différents OS.

Java, comme Windows d'ailleurs, propose un méchanisme simple pour ce faire : les préférences :

     prefs = Preferences.userNodeForPackage(XplTrayIcon.class);

On se connecte aux preferences de l'utilisateur en utilisant notre classe comme identifiant. Il est ensuite possible de "stocker" des valeurs dans les préférences :

        prefs.putBoolean("AutoStart", true);
        ...
     prefs.put("hostname",hostname.getText());
     prefs.put("udpport",udpport.getText());
     prefs.putInt("ipidx",ipaddress.getSelectedIndex());

Et de les récupèrer :

        boolean mybool = prefs.getBoolean("AutoStart", false);
        ...
        String hostname = prefs.get("hostname", "myhostname");

Et tout ça en 2 lignes de code.

A suivre ... les listes d'objets dans les préférences

La documentation de l'API Preferences est disponible ici.

Ant

Ant est à Java ce qu'est make au C : un outil pour automatiser la compilation, la distribution, l'installation, ... des projets.

Comme dans le Makefile, on découpe le projet en étapes plus simples : les targets :

    <target name="gui_clean" description="Clean sources">
<delete dir="${bin}"/>
    </target>

Il s'agit du classique clean qui permet de nettoyer les binaires générés lors de la compilation.Dans une target, on effectue des tasks : la liste des tâches internes est disponible sur le site officiel. Il est également possible d'installer des tâches supplémentaires.

    <target name="gui_jar" depends="gui_clean,gui_install">
        <jar destfile="dist\jxplsensor.jar" filesetmanifest="mergewithoutmain">
            <manifest>
                <attribute name="Main-Class" value="info.gallet.jxplsensor.XplTrayIcon"/>
                <attribute name="Class-Path" value="."/>
            </manifest>
            <fileset dir="bin"/>
        </jar>
    </target>

La création des jars et du manifest devient ainsi automatique.

Pour compiler le projet et générer les archives jar, il suffit de cliquer sur le fichier build.xml :

eclipse java ant menu

Si vos variables d'environnement (en particulier JAVA_HOME) sont correctement configurées, il est également possible de construire le projet en ligne de commande.

ant all

    [javac] Compiling 13 source files to /home/sebastien/devel/workspace/jxplsensorbeta/bin
    [javac] Creating empty /home/sebastien/devel/workspace/jxplsensorbeta/bin/info/gallet/jxplsensor/package-info.class
    [copy] Copying 3 files to /home/sebastien/devel/workspace/jxplsensorbeta/bin
gui_install:
   [delete] Deleting: /home/sebastien/devel/workspace/jxplsensorbeta/bin/info/gallet/jxplsensor/XplDaemon.class
gui_jar:
   [jar] Building jar: /home/sebastien/devel/workspace/jxplsensorbeta/dist/jxplsensor.jar
all:
BUILD SUCCESSFUL
Total time: 2 seconds

Téléchargement

L'application est toujours en cours de développement, vous pouvez télécharger une archive ici contenant le projet eclipse, le code source, les jars ainsi que la documentation ici :

 

Ajouter un Commentaire


Code de sécurité
Rafraîchir

Free business joomla templates