POURQUOI JWS ?

Les avantages :

- Déploiement à distance des logiciels
- Mise à jour automatique
- Exécution sur le poste client
- Pas d'éxécutable / désinstallation et de raccourcis à gérer

Le principe :

- On installe le logiciel à partir d'un serveur web (apache ou équivalent)
- La mise à jour se fait à chaque connexion s'il y a besoin
- Un raccourci est créé sur le bureau et dans le menu démarrer

1. Le nécessaire

Il vous faut un serveur web, le plus simple qu'il existe suffit.
Apache dans sa version minimale ou IIS sont plus que suffisants.
S'il en existe un en place, il servira à cette tâche.

1.1. Le Serveur

Commençons par mettre en place notre serveur.

Vous utilisez APACHE :

Pour activer la reconnaissance des fichiers .jnlp, il vous faudra éditer le fichier mime.types .
Installation classique sous Windows : C:\Program Files\Apache Group\Apache2\conf\mime.types

Ajouter dans le fichier la ligne : application/x-java-jnlp_file jnlp

Vous utilisez IIS :
Il faut ajouter un type de fichier.

Image non disponible

Rien de plus côté serveur.

1.2. Le logiciel

Attachons nous maintenant au logiciel.
Dans ce tutorial, je vais utiliser une Jframe avec un petit mot.

Ce sera un logiciel exécutable uniquement à partir d'internet, sans création de raccourcis, sans accès aux ressources systemes... bref le strict minimum.

Image non disponible
 
Sélectionnez

package prog;

import javax.swing.JFrame;
import javax.swing.JLabel;

public class HelloYou extends JFrame{

private static final long	serialVersionUID	= 1L;

	public static void main( String[] args ){
		new HelloYou();
	}
	
	
	public HelloYou(){
		super("Hello You");		
		getContentPane().add(new JLabel("Hello YOU!"));		
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLocationRelativeTo(null);
		pack();		
		setVisible(true);		
	}
}
				


Compilez et faites-en un jar.

Particularité :

Tout n'est pas merveilleux, voici un défaut de JWS , toutes les données dont vous avez besoin doivent être contenues dans des archives JAR. Heureusement ça ne change pas grand chose dans la majorité des logiciels, c'est même plus propre ( c'est devenu une habitude chez moi ).

En pratique (cas d'une image) :

 
Sélectionnez

ImageIcon jpg = new ImageIcon( "modele" + File.separator + "terrain" + File.separator + "land.jpg" );
devient
ImageIcon jpg = new ImageIcon( ImageIcon.class.getResource( "modele/terrain/land.jpg" ) );
				

2. Ajouter au serveur


Pour rendre notre application accessible, il va nous falloir créer un fichier .JNLP, ce fichier est au format xml, donc compréhensible. Vous trouverez plus loin un exemple ainsi que la totalité des balises jnlp.

Créer un fichier logiciel.jnlp :

 
Sélectionnez

<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0+" codebase="http://localhost/prog/" href="logiciel.jnlp">

	<information>
		<title>Mon Logiciel par JNLP</title>
		<vendor>Johann Sorel</vendor>
		
	</information>

	<resources>
		<j2se version="1.5+" href="http://java.sun.com/products/autodl/j2se"/>
		<jar href="http://localhost/prog/prog.jar"/>
	</resources>

	<application-desc main-class="prog.HelloYou" />

</jnlp>
			

Créer la page web :

 
Sélectionnez

<html>
	<head>
		<title>Mon Logiciel</title>
	</head>

	<body>
		Mon Programme a déployer :
		<br>
		<a href="logiciel.jnlp">PROG</a>
	</body>

</html>
			

Ajoutez la page web, le fichier jnlp et prog.jar dans le même dossier (ajustez les chemins d'accès selon votre serveur).


Et voilà, rien de plus.
Bien sûr, ce n'est que la version minimaliste.

3. Allons plus loin


Java Web Start peut paraître très simpliste, détrompez-vous, il y a possibilité de le rendre très performant et très avantageux ! Aussi bien pour l'entreprise sur un intranet que pour un développeur seul qui veut partager ses logiciels sur internet.

Pour mieux comprendre toutes les possibilités de Java Web Start, voici un fichier jnlp classique.

 
Sélectionnez

<?xml version="1.0" encoding="utf-8"?>

<jnlp spec="1.0+" codebase="http://localhost/jnlp/" href="alter.jnlp">
			
 
Sélectionnez

    <information>
		<title>Alter-SIG</title>
		<vendor>Johann Sorel</vendor>
		<homepage href="http://localhost/jnlp/"/>
		
		<description>Alter-SIG</description>
		<description kind="short">Logiciel 3D SIG Java, technologie de
            déploiement JWS/JNLP</description>
		<description kind="tooltip">Alter-SIG</description>
		
		<icon href="http://localhost/jnlp/icon.gif" width="64"
            height="64"/>
		<offline-allowed />
	</information>
			
 
Sélectionnez

	<security>
		<all-permissions />
	</security>			
			
 
Sélectionnez

	<resources>
		<j2se version="1.5+"
            href="http://java.sun.com/products/autodl/j2se" 
            initial-heap-size="128m" 
            max-heap-size="1024m" />

		<jar href="altersig.jar" main="true" download="eager" />
		<jar href="data.jar" />
		<jar href="lib/jsl.jar" />
		<jar href="lib/looks-2.0.4.jar" />		

            <extension name="unAutresource" version="1" href="/3Dengine.jnlp"/>

	</resources>
	
	<resources os="Windows">
		<nativlib href="lib/winnativ.dll.jar" />		
	</resources>

      <resources os="Linux">
		<nativlib href="lib/linuxnativ.so.jar" />		
	</resources>
			
 
Sélectionnez

	<application-desc main-class="asig.load.Boot">
		<argument>-jconsole disable</argument>
		<argument>show</argument>
	</application-desc>
			
 
Sélectionnez

	</jnlp>
			

Voici donc un fichier jnlp d'un logiciel de taille « normal ». Mais il y a plus de balises encore.

4. Voyons le résultat


Si tout est bien fait on obtient les écrans suivants lors de l'execution (résultat avec JRE 1.6.0, les écrans sont légèrement différents selon les JRE).

Image non disponible

Celui-ci témoigne que votre serveur est bien configuré, et que votre fichier jnlp va être traité par la machine virtuelle java.


Image non disponible

Si vous en êtes à vos premiers pas avec Java Web Start et que vous travaillez en local, il arrive que cet écran s'affiche.


Vient ensuite le moment le plus important, si votre fichier jnlp est bien structuré.

Image non disponible

Cet ecran demande la confirmation de l'installation à l'utilisateur.
Comme on le voit, signer un logiciel ne garanti pas qu'il est honnête, à la charge de l'utilisateur de savoir ce qu'il fait.
Mais voir cette écran est rassurant, il prouve que la machine virtuelle java veille à la sécurité.

Image non disponible

A l'inverse voici le genre d'ecran que produit un fichier jnlp mal configuré.
Ici on peut lire, en cliquant sur « détail » qu'il s'agit de notre archive « prog.jar » qui n'est pas signée.
N'hésitez pas a aller sur l'onglet « Exception », les exceptions en java sont compréhensibles et précises. (un point fort du Java)

Image non disponible

Après avoir réglé les petits problèmes s'il y en avait, le chargement doit se faire normalement et le logiciel va démarrer.

5. L'intégralité des balises

Image non disponibleOBLIGATOIRE (une seule balise possible)
Image non disponibleOBLIGATOIRE ( 1 ou N balises)
Image non disponibleOPTIONEL (0 ou une balise)
Image non disponibleOPTIONEL (0 ou N balises)


<?xml version="1.0" encoding="utf-8"?>
Image non disponibleversion : version xml du fichier
Image non disponibleencoding : encodage utilisé


<jnlp spec="1.0+" codebase="http://localhost/jnlp/" href="alter.jnlp">
Image non disponiblespec : version du fichier jnlp
Image non disponiblecodebase : chemin des fichiers
Image non disponiblehref : nom complet du fichier jnlp


5.1. information

<information locale="fr_FR">
Image non disponibleLa balise information contient la description de l'application.
Image non disponibleLocale : précise le pays, la langue, la culture cf: annexe 1

<title>AlterSIG</title>
Image non disponibletitre de l'application

<vendor>Johann Sorel</vendor>
Image non disponiblenom du ou des développeurs/vendeurs

<homepage href="http://localhost/jnlp/"/>
Image non disponiblesite de l'application
Image non disponiblehref : url de l'application, adresse du site

<description>Alter-SIG</description>
<description kind="short">Logiciel 3D SIG Java, technologie de déploiement JWS/JNLP</description>
<description kind="tooltip">Alter-SIG</description>
Image non disponibledescription de l'application
Image non disponiblekind : one-line / short / tooltip

<icon href="http://localhost/jnlp/icon.gif" width="64" height="64"/>
<icon href="http://localhost/jnlp/icon32.jpg" width="32" height="32"/>
Image non disponibleicône utilisé pour les raccourcis
Image non disponiblehref : url de l'icone au format JPEG ou GIF
Image non disponibleversion : version de l'image
Image non disponiblewidth : largeur de l'image
Image non disponibleheight : hauteur de l'image
Image non disponiblekind : default / selected / disabled / rollover : type d'utilisation de l'image
Image non disponibledepth : profondeur de couleur, généralement 8,16,24,32
Image non disponiblesize : poids de l'image en octets

<shortcut online="true">
Image non disponibleAjouter un raccourci pour le logiciel
Image non disponibleonline : visible uniquement si connexion au site mère présente
<desktop />
Image non disponibleRaccourci sur le bureau
<menu submenu="nomlogiciel"/>
Image non disponibleRaccourci dans le menu démarrer
</shortcut>

<offline-allowed />
Image non disponiblepermet a l'application de se lancer sans avoir de connexion au site

</information>

5.2. applet-desc


<applet-desc main-class="maclasse.class" name="Prog" width=320 height=200>
Image non disponibleDescription de l'applet (s'il sagit d'un applet uniquement)
Image non disponiblemain-class : nom de la classe principale
Image non disponiblename : nom de l'applet
Image non disponiblewidth : largeur de l'applet en pixel
Image non disponibleheight : hauteur de l'applet en pixel
Image non disponibledocumentbase : url pour les fichiers utilisés

<param name="variableA" value="Monsieur Jean">
Image non disponibled'éventuels paramètres pour l'applet
Image non disponiblename : nom du paramètre
Image non disponiblevalue : valeur du paramètre

</applet-desc>

5.3. application-desc


<application-desc main-class="maclasse.class" >
Image non disponibleDescription de l'application (s'il sagit d'une application uniquement)
Image non disponiblemain-class : nom de la classe principale, on peut sauter ce paramètre si la classe principale est dans la première archive jar et qu'elle contient un fichier manifest avec la classe principale

<argument>un argument</argument>
Image non disponibleD'éventuels arguments pour l'application, ces arguments sont passés à la méthode main de l'application

</application-desc>

5.4. component-desc


<component-desc/>
Image non disponibleSpécifier une extension de composant

5.5. installer-desc

<installer-desc main-class="classedinstallation.class"/>
Image non disponibleSpécifiez une classe pour l'installation ou la désinstallation de l'application
Image non disponiblemain-class : nom de classe

5.6. resources


<resources os="Windows">
Image non disponibleLa balise ressources contient les informations sur les données de l'application.
Image non disponibleos : permet de spécifier pour quel système d'exploitation est destiné cette balise, on peut donc avoir des ressources différentes par système. cf: annexe 2
Image non disponiblearch : permet de spécifier une architecture processeur. cf: annexe 2
Image non disponiblelocale: précise le pays, la langue, la culture. cf: annexe 1

<j2se version="1.5+"
href="http://java.sun.com/products/autodl/j2se"
initial-heap-size="128m"
max-heap-size="1024m" />

Image non disponibleSpécifiez les caractéristiques nécessaires pour la machine virtuel java
Image non disponibleversion : 1.4+ / 1.2 1.5 : version de la JVM nécessaire. Un + pour spécifier la version minimum ou mettre un espace entre chaque version.
Image non disponiblehref : url où l'on peut télécharger la JVM
Image non disponibleinitial-heap-size : 128m / 64M / 1024K / 512k : spécifiez l'espace mémoire initial. M ou m pour mega-octects, K ou k pour kilo-octets.
Image non disponiblemax-heap-size : 128m / 64M / 1024K / 512k : spécifiez la taille mémoire maximum

<jar href="altersig.jar" main="true" download="eager" />
<jar href="data.jar" download="lazy" />
Image non disponibleSpécifiez les jars nécessaires pour l'application
Image non disponiblehref : adresse de l'archive jar
Image non disponibleversion : version de l'archive
Image non disponiblemain : true / false : permet de spécifier si cette archive est la principale. Par défaut la premiere archive mentionnée est la principale.
Image non disponibledownload : eager / lazy : eager veut dire que l'archive sera téléchargée avant le lancement de l'application, lazy qu'elle le sera si necessaire.
Image non disponibleSize : taille en octets de l'archive
Image non disponiblepart : nom du groupe d'archive auquel appartient cette archive

<nativlib href="lib/jogl_awt.dll.jar" />
<nativlib href="lib/jogl_cg.dll.jar" />
Image non disponibleSpécifiez les librairies natives nécessaires pour l'application. Il est souvent nécessaire de faire deux (ou plus) balises ressources pour spécifier des librairies natives différentes par système d'explotation. Il est nécessaire de charger dynamiquement ces librairies dans l'application ( System.loadLibrary("jogl") )
Image non disponiblehref : adresse des archives. Les librairies (.dll / .so) doivent être contenues dans des.jar
Image non disponibleversion : version de l'archive
Image non disponibledownload : eager / lazy : eager veut dire que l'archive sera téléchargée avant le lancement de l'application, lazy qu'elle le sera si necessaire.
Image non disponibleSize : taille en octets de l'archive
Image non disponiblepart : nom du groupe d'archive auquel appartient cette archive


<extension name="unAutresource" version="1" href="3Dengine.jnlp">
Image non disponibleSpécifiez d'éventuel extension nécessaire à l'application.
Image non disponiblehref : adresse du fichier jnlp
Image non disponibleversion : version de l'extension
Image non disponiblename : nom de l'extension
<ext-download ext-part="unepartie" download="lazy">
Image non disponiblePermet de définir la manière dont sera téléchargé chaque partie de l'extensions
Image non disponibleext-part : nom de la partie d'extension
Image non disponibledownload: eager / lazy : eager veut dire que l'archive sera téléchargée avant le lancement de l'application, lazy qu'elle le sera si necessaire.
Image non disponiblePart : nom du groupe où elle appartient

</extension>

<property name="user.name" value="Johann"/>
Image non disponiblePermet de donner une valeur à une propriété du système de type System.getProperty ou System.getProperties
Image non disponiblename : nom de la propriété
Image non disponiblevalue : valeur de la propriété

<package name="oracle.*" part="oracle" recursive="true"/>
Image non disponiblePermet de définir une relation entre un package (ou une classe) et un groupe
Image non disponiblename : nom du paquet
Image non disponiblepart : nom du groupe concerné
Image non disponiblerecursive : true / false : permet de préciser si le sous-package sont aussi compris dans cette relation

</resources>

5.7. security


<security>
Image non disponibleLa balise security: les sécurités à apporter pour l'application. S'il n'y a pas de précision l'applition s'éxecute dans le « bac à sable », donc comme un applet avec juste assez de droit pour son fonctionnement. Pas d'accés au disque, de communication réseau ...
<all-permissions />
Image non disponibleDéfini l'application comme ayant tous les droits d'une application normale java.
Il est nécessaire que TOUTES les archives jar soient signées (cf : signer un jar) et que l'utilisateur ait donné son accord au moment du lancement.
<j2ee-application-client-permissions/>
Image non disponibleIndique que l'application doit avoir les droits d'une application de type J2EE

</security>

</jnlp>

6. Signer une archive jar


La signature d'une archive est très importante, elle permet de savoir qui a fait l'archive de manière fiable. C'est une façon de prouver qu'il s'agit bien de votre travail. C'est une sorte de signature électronique. Elle va permettre à notre application d'avoir le droit d'accéder aux fichiers systèmes, à la communication sur le réseau ... etc ..., à l'identique d'un programme java standard.

Le principe de la signature marche sur un cryptage clé privée/clé public. La signature va ajouter quelques lignes dans le fichiers manifest ainsi que d'autre fichiers permettant de confirmer qu'il s'agit de vous et que l'archive n'a pas été modifiée après signature. Je n'en dirais pas plus sur ces sécurités, ce n'est pas le but de ce tutorial.

Il faut d'abord obtenir une clé privée associée à des clés publiques. Celles-ci vont être stockées dans une petite base de données appelée « Keystores ». Chaque clé est identifiée par un alias, généralement le nom du signataire. Un keystore peut contenir la signature de plusieurs personnes.

Pour créer un KeyStore :

keytool -genkey -keystore FichierKeyStore -alias henry
Tapez le mot de passe du Keystore : (mdpkey)
Ressaisissez le nouveau mot de passe : (mdpkey)
Quels sont vos prÚnom et nom ?
[Unknown] : henry Dupont
Quel est le nom de votre unitÚ organisationnelle ?
[Unknown] : etudiant
Quelle est le nom de votre organisation ?
[Unknown] : lupsig
Quel est le nom de votre ville de rÚsidence ?
[Unknown] : paris
Quel est le nom de votre Útat ou province ?
[Unknown] : france
Quel est le code de pays Ó deux lettres pour cette unitÚ ?
[Unknown] : fr
Est-ce CN=henry, OU=etudiant, O=lupsig, L=paris, ST=france, C=fr ?
[non] : oui

SpÚcifiez le mot de passe de la clÚ pour <henry>
(appuyez sur EntrÚe s'il s'agit du mot de passe du Keystore) : (mdphenry)
Ressaisissez le nouveau mot de passe : (mdphenry)


Un fichier « monKeyStore » a été créé.
On peut répéter cette opération pour ajouter des signatures dans le keystore.


Pour signer notre archive jar, il faut exécuter la commande :

jarsigner -keystore FichierKeyStore monarchive.jar henry
Enter Passphrase for keystore: (mdpkey)
Enter key password for henry: (mdphenry)

Warning:
The signer certificate will expire within six months.


C'est fait, votre archive est maintenant signée de votre main « virtuelle » et prête pour être autorisée à accéder aux données du système.

7. En savoir plus

Page Java Web Start de SUN :
java.sun.com/products/javawebstart/index.jsphttp://java.sun.com/products/javawebstart/index.jsp

Page des tags de sun (en anglais) :
java.sun.com/javase/6/docs/technotes/guides/javaws/developersguide/syntax.html

Un autre résumé complet sur les différents tags (en anglais) :
lopica.sourceforge.net/ref.html

Automatisation : Signer un jar avec Apache ANT :
ant.apache.org/manual/CoreTasks/signjar.html

Comment déployer une application SWT via WebStart :
lfe.developpez.com/Java/SWT/WebStart/

Documentation avancée, compléments de johann pons :
http://developers.sun.com/learning/javaoneonline/
Articles : TS-3212, TS-3133, TS-1319, TS-7904

7.1. Annexe 1

La liste complète de toutes les langues :
www.unicode.org/unicode/onlinedat/languages.html

La liste complète de toutes les régions :
www.unicode.org/unicode/onlinedat/countries.html

7.2. Annexe 2

Abréviations des systèmes d'exploitations :
http://www.vamphq.com/os.html

8. Remerciement

Correction : L.Lecocq