Java Webstart #
Java Webstart ist eine geniale Methode, um Java-Programme zu verteilen. Hat man einmal eine JVM bei sich installiert (was auf den meisten Rechnern der Fall sein dürfte), bedarf es nur noch eines einzigen Klicks auf einen Weblink, um eine Swing-Applikation zu starten. Webstart sorgt dafür, daß alle benötigten Teile der Applikation von dem Webserver heruntergeladen (oder ggf. aktualisiert) werden und startet das Programm. Es läuft danach als eigenständiges Java-Programm, d.h. ohne den Browser weiterhin zu benötigen (und natürlich auch nicht im Browserfenster wie z.B. JavaApplets). Ds Programm läuft normalerweise in einer Sandbox, d.h. es kann auf dem Rechner des Benutzers keinen Schaden anrichten. Es kann allerdings mit dem Server, von dem es geladen wurde, weiterhin Daten austauschen. Beim zweiten Mal startet alles viel schneller, weil die Programmdateien gecacht werden.
Für den Benutzer muss man eigentlich gar nichts erklären. Draufklicken und fertig.
Ein paar Erklärungen bedarf natürlich die Erstellung eines Java Webstart-Programms. Dies möchte ich hier tun:
Funktionsweise #
Im Grunde funktioniert webstart so: Ich habe einen Link auf eine *.jnlp-Datei. Diesem Dateityp ist vom Webserver ein besonderer MIME-Type zugewiesen. Der Browser erkennt also einen speziellen Dateityp (am MIME-Type oder an der Dateiendung). Habe ich mein Java anständig installiert, weiss der Brwoser nun, daß er für diese Datei "javaws" startet. Dieses Programm ist das eigenrliche Webstart und liest nun aus der *.jnlp-Datei die Beschreibung der Applikation und welche Komponenten sie benötigt. Diese werden dann entsprechend heruntergeladen oder aus dem Cache geholt. Danach wird die Applikation normal gestartet.
Anforderungen an das Programm #
Grundsätzlich benötigen wir ein ganz gewöhnliches Swing-Programm. Hierbei gibt es im Grunde keine Einschränkungen.
Einschränkungen gibt es lediglich dort, wo die Sandbox verlassen werden soll. Wer also Dateien lokal speichern oder z.B. auf das Netzwerk zugreifen will, muss besondere Maßnahmen ergreifen. Hierzu gibt es die Möglichkeit, besondere Rechte freizugeben (der Benutzer muss dann beim Start des Programmes zustimmen) oder einige Hilfsklassen aus den Webstart-Paketen zu benutzen (z.B. Drucken läuft dann immer über einen Druckdialog, womit der Benutzer dann im Moment des Druckes zustimmt, ein "sofort Drucken" geht dann nicht). Bei normalen Programmen sollten die Sandbox-Einschränkungen nicht wichtig sein. Außerdem hinterlassen sie ein besseres Gefühl beim User. Wir leben also erstmal mit Ihnen.
Erstellung einer Distribution #
Wer ein Programm an andere verteilen will, muss immer erstmal eine Distribution davon erzeugen. Im Prinzip heisst das, ich erzeuge (automatisiert) eine ZIP-Datei, die ich jemand fremden gebe, der dann damit meine Applikation starten kann. Wer noch nicht soweit ist, sollte Webstart noch etwas aufschieben...
Ich habe mir dazu ein Ant-File "build.xml" erstellt, das
- alle meine Klassen übersetzt
- Ein Verzeichnis "dist" erstellt
- diese Klassen zusammenpackt in eine "*.jar"-Datei in "dist"
- alle benötigten Bibliotheken nach "dist/lib" kopiert
- meine sonstigen Dokumentationen nach "dist/docs" kopiert
- evtl. eine Javadoc API-Dokumentation in "dist/docs/api" erstellt
- Evtl. eine von mir vorbereitete Website nach "dist" kopiert
Erstellung der JNLP-Datei #
Nun wird's endlich "webstartig". Die Syntax des JNLP-Files ist sehr gut im Webstart Developers Guide beschrieben. Hier stelle ich deshalb nur ein einfaches Beispiel vor, das gut als Einstieg dienen kann:
<?xml version="1.0" encoding="utf-8"?> <jnlp spec="1.0+" codebase="http://localhost/~tbayen/JEmpire/docs/" href="JEmpire.jnlp"> <information> <title>JEmpire</title> <vendor>Thomas Bayen</vendor> <offline-allowed/> </information> <resources> <j2se version="1.5+"/> <jar href="../JEmpire.jar"/> <jar href="../lib/forms-1.0.7.jar"/> <jar href="../lib/junit-4.1.jar"/> <jar href="../lib/log4j-1.2.14.jar"/> <extension name="jogl" href="http://download.java.net/media/jogl/builds/archive/jsr-231-webstart-current/jogl.jnlp" /> </resources> <application-desc main-class="de.bayen.Demo" /> </jnlp>
Wie man sieht, ist die Datei fast selbsterklärend. Diese Datei kommt in "dist/docs" und dann kopiere ich das ganze "dist"-Verzeichnis in meinen Webserver. Einige Bemerkungen möchte ich dennoch loswerden:
- Die URL der endgültigen Adresse muss oben in "codebase" entsprechend angepasst werden (siehe Frage unten).
- Das "extension"-Tag bindet eine komplette externe Bibliothek ein. Dies hat den Vorteil, daß das Extension-Paket für JOGL, das Sun auf seinem Server hat, von Sun digital signiert ist. JOGL enthält nämlich native Teile, die in der Java Sandbox sonst nicht ausgeführt werden könnten. So spare ich mir ein Bestätigungsfenster beim Start der Applikation. Dies ist der dritte Weg, um die Beschränkungen durch die Sandbox zu umgehen.
- Der "application-desc" Eintrag gibt die Klasse an, die gestartet wird (die also eine statische main(...)-Methode enthält)
- Weitere Eintragungen sind durchaus sinnvoll, ich wollte das hier allerdings erstmal möglichst kurz halten.
der richtige MIME-Type #
Obige Datei darf vom Webserver nicht als Textdatei ausgeliefert werden, sondern muss den richtigen MIME-Type bekommen. Mein lokaler Apache2 hat das von ganz alleine richtig gemacht. Ansonsten ist es eine gute Idee, das im Apache fest einzustellen, wie im Developer Guide beschrieben. Wer das nicht kann, weil die Webseite bei einem Provider liegt, der das nicht erlaubt, kann im gleichen Verzeichnis eine Datei ".htaccess" erstellen mit folgendem Inhalt:
AddType application/x-java-jnlp-file .jnlp
Erstellung der Webseite #
Was jetzt noch fehlt, ist eine hübsche Webseite, um auf unsere *.jnlp-Datei zu verlinken. Dies kann man einfach mit einem Link machen und fertig. Man sollte jedoch etwas mehr Arbeit investieren und nach der Anleitung aus dem Developers Guide vorgehen. Dadurch bekommen Benutzer, die kein Java installiert haben, direkt die Gelegenheit, dies in einem Rutsch zu tun. Hierzu evtl. später mehr.
Beispiel #
Unser JEmpire-Projekt kann man unter http://jempire.javaproject.de besichtigen und auch direkt starten.
Debugging #
Zum Thema "Debugging unter Webstart" habe ich hier einige interessante Links zusammengestellt:
- Webstart Java-Console
- Webstart Tracing and Logging
- Sun Troubleshooting and debugging Guide
- unofficial Webstart FAQ
Probleme und Fragen #
Ich habe immer noch ein Problemchen mit Java Webstart und da gestern mindestens Jens sagte, er hätte Erfahrungen damit, hier meine Frage:
Ich möchte eine JNLP-Datei erzeugen, die ich an verschiedenen Orten benutzen kann. D.h. ich erzeuge ein Verzeichnis mit meiner Webstart-Applikation mit allem Drum und dran. Dieses Verzeichnis kopiere ich zum Testen nach ~/public_html. Nun kann ich unter "http://localhost/~tbayen/JEmpire" meine Webseiten und mein WebStart-Programm benutzen. Nun möchte ich genau das gleiche Verzeichnis einfach auf einen Webserver hochschieben und das dort dann genauso benutzen. Das geht aber nicht, weil ich im JNLP immer alle URLs absolut angeben muss. Alternativ kann ich eine "codebase" eintragen, dann muss die aber absolut sein. Ja - ich weiss, ich muss nur jeweils eine Zeile ändern. Trotzdem ärgert mich das.
Gibts da jemanden, der das Brett findet, das ich vor dem Kopf habe?!? -- ThomasBayen
--
Vor kurzem habe ich bemerkt, daß meine Applikation auf einem meiner Systeme (Debian Lenny) nicht läuft. Es kommt die Meldung "Fehler: JAR-Resourcen in JNLP-Datei sind nicht von demselben Zertifikat signiert". Ich habe alle Webstart-Caches gelöscht und herumprobiert und bin zu der Einsicht gekommen, daß es nur daran liegen kann, daß das Lenny-System ein Java 1.6.0_12 und mein Entwicklung-System ein Java 1.6.0_16 installiert hat. Genau so steht es auch auf http://forums.sun.com/thread.jspa?threadID=5401355. Das Problem tritt offensichtlich mit bestimmten Java-Versionen auf, wenn man Dateien signiert, die bereits signiert sind. Dort gibt es noch ein paar Tips, was man machen kann.
Autor: ThomasBayen