Entwicklungsumgebung

(Auszug aus "Java und XSLT" von Eric M. Burke)

Spezialisierte und leichtgewichtige Entwicklungswerkzeuge sind für Java-Entwickler sehr wichtig. Kommerzielle integrierte Entwicklungsumgebungen (IDEs) stellen nur einen kleinen Teil der in Java-Software-Projekten eingesetzten Werkzeuge. Diese umfassen Build-Werkzeuge wie Ant, Testwerkzeuge wie JUnit sowie verschiedene XML-Parser und XSLT-Prozessoren. Die folgende Abbildung illustriert einige der Werkzeuge einer typischen Java- und XSLT-Entwicklungsumgebung.

Gebräuchliche Java-, XML- und XSLT-Werkzeuge

Abbildung: Gebräuchliche Java-, XML- und XSLT-Werkzeuge

Es fällt auf, daß die Anzahl der eingesetzten Werkzeuge sehr groß ist. Die folgende Tabelle zeigt deren Einsatzfelder.

Tabelle: Übersicht über die Werkzeuge

Werkzeug Beschreibung
Java 2 SDK Java 2 Software Development Kit (JDK)
Apaches JMeter Werkzeug zum Test der Belastbarkeit, d.h. der Skalierbarkeit und Leistungsfähigkeit von Servlets und Websites
EJB-Container Enterprise JavaBeans Server, wie JBoss, Enhydra, WebLogic oder WebSphere
XML-Parser Xerces, Crimson oder ein anderer SAX- und/oder DOM-Parser
XSLT-Prozessor Xalan, SAXON oder jeder andere XSLT-Prozessor
Servlet-Container Apaches Tomcat oder ein anderer Servlet-Host; viele Anwendungsserver enthalten sowohl Servlet- als auch EJB-Container
JAXP Stellt eine gemeinsame API für XML-Parser und XSLT-Prozessoren zur Verfügung
Apaches Ant Java-Äquivalent zu make; Ant Build-Dateien ermöglichen konsistentes Kompilieren und Testen in einer Entwicklungsumgebung
IDE Eine integrierte Entwicklungsumgebung, z.B. Borlands JBuilder
JUnit Ein Open Source Test-Framework für Units

Einige Werkzeuge sind wesentlich hilfreicher, wenn sie im Kontext einer Entwicklungsumgebung eingesetzt werden. JUnit ist z.B. effektiver, wenn es in Kombination mit Ant eingesetzt wird, weil so sichergestellt wird, daß jeder Entwickler im Team mit identischen Einstellungen kompiliert und testet. Das bedeutet, daß die Tests eines Entwicklers bei jedem anderen identisch funktionieren. Ohne den Einsatz von Ant können erfolgreiche Tests eines Entwicklers bei anderen fehlschlagen, da diese eventuell mit anderen Versionen einiger Werkzeuge arbeiten.

CLASSPATH-Probleme

Der Übergang von XML-Parsern und XSLT-Prozessoren der ersten Generation war nicht gerade eine gute Erfahrung für Java-Entwickler. Die neueren APIs sind zwar sehr gut, es existieren aber in vielen Anwendungen und Verzeichnissen noch alte JAR-Dateien, die oftmals größere Schwierigkeiten bei Konfigurationen verursachen. Dieser Abschnitt behandelt die häufigsten Probleme und erläutert die Konfiguration verschiedener Werkzeuge.

JAR-Hölle?

Eine häufige Kritik an Windows-Systemen von Microsoft ist unter dem Namen »DLL-Hölle« bekannt. Sie bezieht sich auf die Probleme, die entstehen, wenn zwei Anwendungen verschiedene Versionen derselben DLL (Dynamic Link Library) benötigen. Die Installation einer neuen Anwendung kann eine ältere Version einer DLL überschreiben, von der aber andere Anwendungen abhängen, was zu fehlerhaftem Verhalten oder kompletten Systemabstürzen führen kann. (Auch bekannt unter dem Namen »blue screen of death«.)

Auch Java-Entwickler müssen sich jetzt häufiger mit inkompatiblen Versionen von JAR-Dateien herumärgern. JAXP 1.0 und JAXP 1.1 enthalten z.B. beide eine JAR-Datei namens jaxp.jar. Anwendungen, die Funktionalität von JAXP 1.1 benötigen, funktionieren nicht, wenn die Version 1.0 von jaxp.jar vor der neueren Version im CLASSPATH steht. Das kommt häufiger vor als man meint, weil viele kommerzielle und Open Source-Entwicklungswerkzeuge mit XML-Parsern und XSLT-Prozessoren ausgeliefert werden. Die zugehörigen Installationsroutinen dieser Werkzeuge können JAR-Dateien installieren, ohne den Nutzer zu informieren oder zu fragen.

Die einfachste Lösung ist es, die alten Versionen der JAR-Dateien zu finden und zu löschen. Das ist aber leichter gesagt als getan, da die Versionsnummer oft nicht Bestandteil des Dateinamens ist. Da viele Werkzeuge den CLASSPATH modifizieren oder ignorieren, wenn sie ausgeführt werden, reicht es oft nicht, die alten JAR-Dateien aus dem CLASSPATH zu löschen. Hilfestellungen zur Lösung dieser Probleme bei Ant, Tomcat und JBuilder folgen.

Einige JAR-Dateien schreiben mittlerweile Versionsinformationen in die Datei META-INF/MANIFEST.MF. Sie wird auch einfach Manifest genannt und kann mit der folgenden Anweisung aus einer JAR-Datei filename.jar extrahiert werden:

jar -xf filename.jar META-INF/MANIFEST.MF

Das extrahierte Manifest kann dann mit einem beliebigen Texteditor angezeigt werden. Das folgende Beispiel zeigt das Manifest der Version 1.0 von jaxp.jar:

Beispiel: Manifest der Version 1.0 von jaxp.jar

Manifest-Version: 1.0
Specification-Title: Java API for XML Parsing Interfaces
Specification-Vendor: Sun Microsystems
Created-By: 1.2.2 (Sun Microsystems Inc.)
Specification-Version: 1.0.0
Name: javax/xml/parsers
Package-Version: 1.0.0
Specification-Title: Java API for XML Parsing
Specification-Vendor: Sun Microsystems
Sealed: true
Specification-Version: 1.0.0
Package-Vendor: Sun Microsystems, Inc.
Package-Title: javax.xml.parsers

Dieses Manifest ermöglicht es, den Inhalt der JAR-Datei zu ermitteln. Obwohl die Produkte von Sun dieses Feature nutzen, ist das Manifest nur optional, und viele Produkte enthalten diese Informationen nicht.

Siegelverletzungen

Bei der gefürchteten »Siegelverletzung« handelt es sich um eine recht kryptische Ausnahme. Das folgende Beispiel zeigt einen Stack-Trace, der bei einer Siegelverletzung angezeigt wird.

Beispiel: Stack-Trace bei einer Siegelverletzung

Exception in thread "main" java.lang.SecurityException: sealing violation
at java.net.URLClassLoader.defineClass(URLClassLoader.java:234)
at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:297)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:286)
at java.lang.ClassLoader.loadClass(ClassLoader.java:253)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:313)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:120)
at javax.xml.transform.TransformerFactory.newInstance(TransformerFactory.java:117)
at Test.main(Test.java:17)

Da die Fehlermeldung nicht besonders informativ ist und der Stack-Trace hauptsächlich aus internen Java-Klassen besteht, ist die Ursache dieser Ausnahme schwer auszumachen. Laut Stack-Trace hat Zeile 17 von Test.java das Problem verursacht:

TransformerFactory transFact = TransformerFactory.newInstance( );

Diese Zeile ist aber absolut korrekt. Das eigentliche Problem ist wieder einmal der CLASSPATH. Die Beschreibung einer Siegelverletzung besagt, daß ein oder mehrere versiegelte JAR-Dateien in der falschen Reihenfolge im CLASSPATH aufgelistet werden.

Eine versiegelte JAR-Datei hat den Eintrag Sealed: true im Manifest, siehe das Beispiel Manifest der Version 1.0 von jaxp.jar. (Es ist auch möglich, einzelne Pakete einer JAR-Datei zu versiegeln. Weitere Informationen finden Sie in der Dokumentation der Java 2 Standard Edition.) Der Versiegelungsmechanismus für Pakete wurde mit der Java-Version 1.2 eingeführt, um die Konsistenz zwischen verschiedenen Versionen sicherzustellen. Wenn ein Paket versiegelt ist, müssen alle Klassen dieses Paketes aus derselben JAR-Datei geladen werden. Werden einige der Klassen aus einer JAR-Datei und andere aus einer anderen geladen, wird eine Ausnahme java.lang.SecurityException ausgelöst. Die folgenden Abbildung illustriert das Problem.

Siegelverletzung

Abbildung: Siegelverletzung

In diesem Diagramm wird parser.jar im CLASSPATH vor crimson.jar aufgeführt. Java-Anwendungen laden die JAR-Dateien in der Reihenfolge ihres Auftretens im CLASSPATH. Wurde die Klasse org.xml.sax.SAXException von der JVM geladen, müssen alle weiteren Klassen oder Interfaces des Pakets org.xml.sax ebenfalls aus dem versiegelten parser.jar geladen werden. Wenn die Anwendung dann eine Instanz von ContentHandler benötigt, versucht der Klassen-Loader diese Datei aus crimson.jar zu laden, was die SecurityException aus dem Beispiel Stack-Trace bei einer Siegelverletzung verursacht. Die Lösung dieses Problems besteht darin, parser.jar aus dem CLASSPATH zu entfernen, wodurch alle Klassen des Pakets org.xml.sax aus crimson.jar geladen werden.

Weitere Ausnahmen und Fehler

Weitere von JAXP definierte »Konfigurations«-Ausnahmen sind javax.xml.transform.TransformerConfigurationException und javax.xml.parsers.FactoryConfigurationError. Diese können auftreten, wenn eine ältere Version von jaxp.jar im CLASSPATH steht. Da in JAXP 1.0 weder SAX 2, DOM 2 noch XSLT-Transformationen bekannt waren, werden Anwendungen, die eines dieser Features verwenden wollen, eine dieser Ausnahmen erzeugen, wenn statt JAXP 1.1 noch JAXP 1.0 installiert ist.

Wie schon erwähnt, ist der Dateiname in beiden JAXP-Versionen jaxp.jar. Deshalb muß darauf geachtet werden, daß die neuere Version installiert ist. Da JAXP 1.1 abwärtskompatibel ist, kann die alte Version ersetzt werden, ohne Probleme bei bestehenden Anwendungen hervorzurufen.

Die am leichtesten zu behebende Ausnahme ist java.lang.ClassNotFoundException. Sie tritt auf, wenn JAXP 1.1 im CLASSPATH aufgeführt wird, aber kein XSLT-Prozessor oder XML-Parser. In diesem Fall müssen einfach ein JAXP-verträglicher Parser und XSLT-Prozessor zum CLASSPATH hinzugefügt werden.

Optionale Java-Pakete

Die Java-VM lädt Klassen nicht nur aufgrund der Umgebungsvariable CLASSPATH. Bevor dieser durchsucht wird, versucht die VM, Klassen aus einem Verzeichnis für optionale Pakete zu laden. Ein installiertes optionales Paket ist eine JAR-Datei, die sich im Verzeichnis lib/ext der Java 2 Runtime-Umgebung bzw. im Verzeichnis jre/lib/ext des Java 2 SDK befindet.

Wenn kein installiertes optionales Paket gefunden wurde, sucht die VM als nächstes nach ladbaren optionalen Paketen. Es handelt sich um JAR-Dateien, die im Manifest-Header einer anderen JAR-Datei explizit referenziert werden. Ein Manifest könnte z.B. die folgende Zeile enthalten:

Class-Path: jaxp.jar

In diesem Fall sucht die VM in demselben Verzeichnis, in dem die JAR-Datei mit dem Manifest-Eintrag stand, nach jaxp.jar.

Um sicherzustellen, daß die richtigen Versionen von XML-Parser, XSLT-Prozessor und JAXP installiert sind, können die benötigten JAR-Dateien ins Verzeichnis für optionale Pakete kopiert werden. Software-Entwickler sollten das Java 2 SDK installieren und die JAR-Dateien ins Verzeichnis JAVA_HOME/jre/lib/ext kopieren. Endnutzer, die die Java 2 Runtime-Umgebung und nicht das gesamte SDK nutzen, können die JAR-Dateien ins Verzeichnis lib/ext, wo auch die JRE installiert ist, kopieren.

Um ein optionales Paket zu deinstallieren, muß die JAR-Datei lediglich aus dem entsprechenden Verzeichnis gelöscht werden.

Integrierte Entwicklungsumgebungen für Java

Viele Entwickler verwenden Java-Entwicklungsumgebungen wie den JBuilder von Borland. Diese Werkzeuge können jedoch auch zu Problemen führen, da sie typischerweise eine Kopie des Java 2 SDK enthalten. Beim Kompilieren und Ausführen innerhalb der IDE benutzt die VM das Java-Verzeichnis der IDE anstelle eines Sun Java 2 SDK, das eventuell bereits auf dem System installiert ist. Die folgende Abbildung zeigt eine typische Verzeichnisstruktur, die dieses potentielle Problem verdeutlicht.

Typische Verzeichnisstruktur

Abbildung: Typische Verzeichnisstruktur

In diesem Beispiel ist der JBuilder korrekt mit JAXP 1.1, dem Crimson XML-Parser und der Xalan 2.0 JAR-Datei konfiguriert. Kompilieren, Ausführen und Debuggen funktionieren also innerhalb des JBuilder problemlos. Wird die Anwendung aber außerhalb des JBuilder ausgeführt, wird sie wahrscheinlich nicht funktionieren. Der Grund hierfür ist, daß im Java 2 SDK die JAXP 1.0 JAR-Datei und ein passender älterer XML-Parser installiert sind.

Werden die neuen JAR-Dateien von JAXP zum CLASSPATH hinzugefügt, führt dies wahrscheinlich zu einer Siegelverletzung, da die VM immer noch die Dateien aus dem Verzeichnis für optionale Pakete lädt, bevor der CLASSPATH durchsucht wird. Das Problem kann gelöst werden, indem die Dateien jaxp.jar und parser.jar durch die JAR-Dateien aus dem entsprechenden Verzeichnis von JBuilder ersetzt werden. Es ist auch möglich, die Umgebungsvariablen JAVA_HOME und PATH auf die Java-Installation des JBuilder zu setzen.

Ant

Es ist oft schwierig, die JAR-Dateien und den CLASSPATH auf dem Rechner eines Entwicklers richtig zu konfigurieren, ungleich schwerer ist es jedoch, die Konfiguration für ein ganzes Team von Entwicklern zu synchronisieren. Es ist äußerst wichtig, daß jedes Mitglied beim Testen und Integrieren seiner Code-Änderungen denselben Build-Prozeß verwendet. Apache stellt hierfür mit Ant ein hilfreiches Werkzeug zur Verfügung.

Unter Antdoc – Ein Dokumentations-Stylesheet für Ant wurde Apaches Ant bereits als ein Java-basiertes Build-Werkzeug und als eine exzellente Alternative zu make vorgestellt. (Diese Bemerkungen gelten für Ant 1.3. Neuere Versionen gehen eventuell anders mit JAR-Dateien um.) Ant bietet die folgenden Vorteile:

  • Seine XML-Build-Dateien sind einfacher zu erstellen als Makefiles.
  • Ant ist in Java geschrieben und damit portabel.
  • Builds sind extrem schnell, weil dieselbe Instanz der VM für die meisten Schritte im Build-Prozeß verwendet wird.

Ant kann unter Apache Ant heruntergeladen werden.

Die Installation von Ant

Um Ant zu installieren, muß nur die Binär-Distribution heruntergeladen und in einem beliebigen Verzeichnis entpackt werden. Die Umgebungsvariable ANT_HOME muß auf dieses Verzeichnis und JAVA_HOME auf das Installationsverzeichnis von Java verweisen. Zum Test geben Sie ant -version ein, was die folgende oder eine ähnliche Ausgabe erzeugt:

Ant version 1.3 compiled on March 2 2001

Da Ant in Java geschrieben ist, müssen Konflikte zwischen den JAR-Dateien von Ant und den JAR-Dateien im CLASSPATH vermieden werden. Das ist besonders dann wichtig, wenn Ant auch die XSLT-Transformation steuern soll, da Ant mit den JAR-Dateien von JAXP 1.0 ausgeliefert wird, die nicht mit den Implementierungen von JAXP 1.1 kompatibel sind.

Nachdem Ant installiert ist, können die Dateien ANT_HOME/lib/jaxp.jar und ANT_ HOME/lib/parser.jar erneuert werden. Alle JAR-Dateien, die im Verzeichnis ANT_ HOME/lib stehen, werden automatisch dem CLASSPATH von Ant hinzugefügt und sind für die verschiedenen Tasks im Build-Prozeß zugänglich. Indem die zu JAXP 1.1 kompatiblen JAR-Dateien ins Verzeichnis ANT_HOME/lib kopiert werden, können die meisten Probleme mit neuen Anwendungen, die DOM 2, SAX 2 oder die Unterstützung für XSLT-Transformationen benötigen, vermieden werden.

Eine typische Build-Datei für Ant

Der beste Weg, sich mit Ant vertraut zu machen, ist es herunterzuladen, den ersten Teil des Handbuchs zu lesen und dann verschiedene Build-Dateien zu studieren. Das folgende Beispiel zeigt eine solche Build-Datei, mit der ein Teil des Beispiel-Codes dieses Kapitels kompiliert und eine XSLT-Transformation durchgeführt werden kann.

Beispiel: build.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
 *******************************************************
 ** Beispiel einer Build-Datei für Ant.
 **
 ** Erwartet die folgende Verzeichnisstruktur:
 ** examples
 ** +-chapters
 ** | +-chap9
 ** | build.xml (diese Datei)
 ** | aidan.xml (Beispiel einer XML-Datei)
 ** | condensePerson.xslt (Beispiel einer XSLT-Datei)
 ** +-common
 ** | +-src
 ** | +-com/oreilly/javaxslt/swingtrans/...
 ** |
 ** +-build (wird von dieser Build-Datei erzeugt)
 **
 **************************************************** -->
<project name="chap9" default="help" basedir="../..">
    <!--
    *******************************************************
    ** Globale Eigenschaften.
    **************************************************** -->
    <property name="builddir" value="build"/>
    <path id="thirdparty.class.path">
        <pathelement path="lib/saxon_6.2.2.jar"/>
        <pathelement path="lib/jaxp_1.1.jar"/>
        <pathelement path="lib/servlet_2.3.jar"/>
        <pathelement path="lib/junit_3.5.jar"/>
        <pathelement path="lib/jdom_beta6.jar"/>
    </path>
    <!--
    *******************************************************
    ** Erzeuge die Verzeichnisstruktur für die Ausgabe.
    **************************************************** -->
    <target name="prepare">
        <mkdir dir="${builddir}"/>
    </target>
    <!--
    *******************************************************
    ** Zeige eine kurze Hilfemeldung. Es ist das Default-
    ** Ziel, das aufgerufen wird, wenn der Nutzer "ant" eingibt.
    **************************************************** -->
    <target name="help" description="Zeigt eine kurze Hilfemeldung">
         <echo message="Beispiel Build-Datei für Kapitel 9"/>
         <echo message="'ant -projecthelp' zeigt weitere Hilfe"/>
    </target>
    <!--
    ********************************************************
    ** Lösche das gesamte Build-Verzeichnis
    ***************************************************** -->
    <target name="clean"description="Lösche den gesamten kompilierten Code">
         <delete dir="${builddir}"/>
    </target>
    <!--
    ********************************************************
    ** Kompiliere das Paket com.oreilly.javaxslt.swingtrans
    ***************************************************** -->
    <target name="compile" depends="prepare" description="Kompiliere die Anwendung SwingTransformer">
         <javac srcdir="common/src" destdir="${builddir}" includes="com/oreilly/javaxslt/swingtrans/**">
              <classpath refid="thirdparty.class.path"/>
         </javac>
    </target>
    <!--
    ********************************************************
    ** Führe com.oreilly.javaxslt.swingtrans.SwingTransformer aus
    ***************************************************** -->
    <target name="run" depends="compile" description="Führe die Anwendung SwingTransformer aus">
         <java fork="yes" classname="com.oreilly.javaxslt.swingtrans.SwingTransformer">
            <classpath>
                 <pathelement path="${builddir}"/>
            </classpath>
            <classpath refid="thirdparty.class.path"/>
         </java>
    </target>
    <!--
    ********************************************************
    ** Führe eine XSLT-Transformation durch. Wenn die XML-Datei
    ** oder das XSLT-Stylesheet geändert wird, wird die
    ** Transformation erneut durchgeführt.
    **
    ** basedir - spezifiziert den Ort der XSLT-Datei
    ** destdir - dieses Attribut muß zwar angegeben werden, Ant 1.3
    ** ignoriert es aber. Die Konsolenausgabe suggeriert,
    ** daß das Verzeichnis destdir verwendet wird.
    ** Tatsächlich muß das Attribut "out" ebenfalls
    ** das Zielverzeichnis spezifizieren.
    ***************************************************** -->
    <target name="transform" description="Führe eine XSLT-Transformation durch">
        <style processor="trax" basedir="chapters/chap9" destdir="${builddir}" style="condensePerson.xslt" in="chapters/chap9/aidan.xml" out="${builddir}/aidan_condensed.xml">
            <!-- übergib einen Stylesheet-Parameter -->
            <param name="includeMiddle" expression="yes"/>
        </style>
    </target>
</project>

Alle Build-Dateien sind in XML geschrieben und haben das Wurzelelement <project>. Es spezifiziert das Default-Ziel und das Basisverzeichnis. Jedes Ziel wird durch ein Element <target> spezifiziert und kann von anderen Targets abhängen. Ein Target besteht aus Tasks, die jeweils für einzelne Arbeitsschritte verantwortlich sind.

Der CLASSPATH kann einmal definiert und von den verschiedenen Tasks in der gesamten Build-Datei verwendet werden. Das Element <path> ist im Beispiel build.xml hervorgehoben. Es enthält mehrere JAR-Dateien aus dem Verzeichnis lib. Zum Beispiel:

<pathelement path="lib/servlet_2.3.jar"/>

Hier werden zwei Punkte für die Definition einer konsistenten Entwicklungsumgebung deutlich gemacht. Erstens ist es eine gute Idee, JAR-Dateien so umzubenennen, daß sie Versionsnummern enthalten. Auf diese Weise werden Konflikte und unerwartete Fehler vermieden, die ihre Ursache in JAR-Dateien mit demselben Namen und unterschiedlichen Versionen haben. Der Nachteil dabei ist, daß die Build-Dateien manuell angepaßt werden müssen, wenn JAR-Dateien mit neuen Versionen installiert werden.

Zweitens verwendet diese spezielle Build-Datei ihren eigenen CLASSPATH, und nicht den des Entwicklers. Sich auf die Umgebungsvariable CLASSPATH zu verlassen, führt deshalb zu Problemen, weil jeder Entwickler im Team ganz unterschiedliche JAR-Dateien in seinem CLASSPATH definiert haben kann. Durch die Definition in der Build-Datei kompilieren und testen alle mit einer identischen Konfiguration.

Das folgende Target zeigt, wie die Anwendung kompiliert wird:

<target name="compile" depends="prepare" description="Kompiliere die Anwendung SwingTransformer">
    <javac srcdir="common/src" destdir="${builddir}" includes="com/oreilly/javaxslt/swingtrans/**">
        <classpath refid="thirdparty.class.path"/>
    </javac>
</target>

Um dieses Target auszuführen, geben Sie einfach ant compile an der Kommandozeile ein. Da dieses Target von prepare abhängt, wird das Verzeichnis build angelegt, bevor der Code kompiliert wird. Der Task <javac> kompiliert dabei nur die Quelldateien, die seit dem letzten Kompilieren geändert wurden, wodurch die Verwendung von Ant wesentlich schneller als das manuelle javac *.java ist.

Die Attribute srcdir und destdir liegen relativ zum basedir, das im Element <project> spezifiziert wurde. Ant verwendet normale Schrägstriche (/) zur Trennung der Pfadelemente, und diese relativen Pfade funktionieren unter Windows und Unix bzw. Linux. Das Attribut includes definiert einen Filter, der festlegt, welche Dateien zum Kompilieren herangezogen werden.

Das letzte Target dieser Build-Datei führt eine XSLT-Transformation durch. Dazu wird der Task <style> verwendet, der als nächstes beschrieben wird.

Transformationen mit dem Style-Task von Ant

Von besonderem Interesse für XSLT-Entwickler ist der <style>-Task von Ant. Es handelt sich um einen grundlegenden Task, der eine oder mehrere XSLT-Transformationen durchführt. Dazu müssen die JAXP JAR-Dateien von Ant wie beschrieben aktualisiert werden. Hier ist ein einfaches Beispiel:

<style basedir="." destdir="." style="sample.xslt" processor="trax" in="company.xml" out="report.txt"/>

Es wird im Basisverzeichnis des Projekts nach den XML- und XSLT-Dateien gesucht, und die Ausgaben der Transformation werden in die Datei report.txt geschrieben. Als Prozessor findet trax Verwendung, also JAXP 1.1. Ant verwendet den ersten JAXP-verträglichen Prozessor im CLASSPATH. Die folgende Tabelle zeigt die vollständige Liste der Attribute des <style>-Tasks.

Tabelle: Die Attribute des <style>-Tasks von Ant

Attribut Beschreibung erforderlich?
basedir Verzeichnis mit den XML-Dateien. ja
destdir Verzeichnis für das Ergebnis. ja
extension Default-Dateinamenerweiterung für das Ergebnis der Transformation(en). nein
style Dateiname des XSLT-Stylesheets. ja
processor Legt den zu benutzenden XSLT-Prozessor fest; gültige Werte sind »trax« für einen TrAX-verträglichen Prozessor, »xslp« für den XSL:P-Prozessor und »xalan« für Xalan in der Version 1.x; kann auch den Namen einer Klasse enthalten, die org.apache.tools.ant.taskdefs.XSLTLiaison implementiert; Defaultwert ist »trax«. nein
includes Durch Kommas getrennte Liste von einzubindenden Dateien. nein
includesfile Name einer Datei mit include-Mustern. nein
excludes Eine durch Kommas getrennte Liste von auszuschließenden Dateien. nein
excludesfile Name einer Datei mit exclude-Mustern. nein
defaultexcludes Gültige Werte sind »yes« oder »no«, Vorgabe ist »yes«. nein
in Einzelne XML-Eingabedatei. nein
out Name einer einzelnen Ausgabedatei. nein

Muster-Attribute wie includes und excludes funktionieren wie alle anderen Muster in Ant. Mit ihrer Hilfe kann der Task herausfinden, welche Dateien transformiert werden. Werden diese Attribute nicht angegeben, werden alle Dateien im Basisverzeichnis transformiert. Ein ganzes Verzeichnis mit XML-Dateien wird wie folgt transformiert:

<style basedir="xmlfiles" includes="*.xml" destdir="build/doc" style="report.xslt" extension="html"/>

Wie im Beispiel build.xml gezeigt wurde, können Parameter mit verschachtelten <param>-Elementen übergeben werden. Dieses Element benötigt die Attribute name und expression:

<style basedir="xmlfiles" includes="*.xml" destdir="build/doc" style="report.xslt" extension="html">
   <param name="reportType" expression="'detailed'"/>
</style>

Tomcat

Bei Tomcat von Apache handelt es sich um einen Servlet- und JSP-Container, der schon des öfteren in diesem Buch erwähnt wurde. Tomcat ist einfach zu installieren und zu konfigurieren:

  • Laden Sie das neueste Release von Tomcat für Ihr Betriebssystem herunter.
  • Entpacken Sie die Distribution in ein Verzeichnis.
  • Setzen Sie die Umgebungsvariable TOMCAT_HOME auf dieses Verzeichnis.
  • Setzen Sie die Umgebungsvariable JAVA_HOME auf das Verzeichnis Ihrer Java-Distribution.

Da Webanwendungen Konfigurationsinformationen aus ihrem XML-Anwendungsdeskriptor (web.xml) lesen, sind alle aktuellen Versionen von Tomcat mit einem XML-Parser ausgestattet.

Die Konfiguration von Tomcat 3.2.x

Tomcat 3.2.x beinhaltet verschiedene JAR-Dateien im Verzeichnis $TOMCAT_ HOME/lib, unter anderem jaxp.jar und parser.jar mit Unterstützung für die Version 1.0 von JAXP und den XML-Parsern SAX 1.0 und DOM 1.0. Jede JAR-Datei, die zum Verzeichnis lib hinzugefügt wird, ist für alle Webanwendungen verfügbar. Tomcat verwendet ein einfaches Skript, um *.jar im Verzeichnis lib zu finden und zu seinem CLASSPATH hinzuzufügen. Die Reihenfolge hängt davon ab, wie das Betriebssystem die Dateien auflistet, also typischerweise alphabetisch. Der komplette CLASSPATH von Tomcat 3.2.x beinhaltet die folgenden Einträge:

  • $TOMCAT_HOME/classes
  • $TOMCAT_HOME/lib/*.jar
  • Jeden existierenden CLASSPATH
  • $JAVA_HOME/jre/lib/tools.jar

Obwohl das Verzeichnis lib eine einfache Möglichkeit bietet, Hilfsklassen zu installieren, auf die alle Webanwendungen zugreifen können, entstehen Konflikte, wenn einzelne Anwendungen unterschiedliche Versionen von SAX, DOM oder JAXP benötigen. Wenn Tomcat eine alte Version eines Tools vor der neuen findet, treten in der Regel Ausnahmen auf. Es kommt z.B. zu einer Siegelverletzung, wenn im CLASSPATH eine neue Version von crimson.jar und eine alte von parser.jar vorhanden sind.

Tomcat 3.2.x kann folgendermaßen für eine XML-Unterstützung konfiguriert werden:

  • Löschen Sie jaxp.jar und parser.jar aus dem Verzeichnis $TOMCAT_HOME/lib.
  • Kopieren Sie die folgenden Dateien aus der Distribution von JAXP 1.1 in das Verzeichnis $TOMCAT_HOME/lib: jaxp.jar, crimson.jar und xalan.jar.

Natürlich unterstützt JAXP 1.1 neben Crimson und Xalan auch andere Werkzeuge. Wenn Sie es vorziehen, ersetzen Sie crimson.jar und xalan.jar mit anderen zu JAXP 1.1 kompatiblen Produkten.

Die Konfiguration von Tomcat 4.0.x

Die Konfiguration von Tomcat 4.0 ist in zwei Punkten gegenüber Tomcat 3.2.x verbessert worden. Erstens wird der CLASSPATH des Nutzers nicht mehr an den CLASSPATH von Tomcat angehängt. Dadurch werden Situationen vermieden, in denen der Code bei einem Entwickler funktioniert, der eine benötigte Datei in seinem CLASSPATH stehen hat, bei geringfügig anderen Einstellungen eines anderen Entwicklers aber nicht.

Zweitens sind die JAXP JAR-Dateien von Tomcat 4.0 nicht mehr für Webanwendungen sichtbar. Deshalb müssen die entsprechenden JAR-Dateien installiert werden, wenn XML-Unterstützung benötigt wird. Durch dieses neue Modell werden unerwartete Konflikte mit XML-Bibliotheken vermieden, die intern von Tomcat verwendet werden. Wenn Sie also die XML-Unterstützung nicht installieren, liefert Tomcat den Fehler java.lang.NoClassDefFoundError.

Um die XML-Unterstützung für Tomcat 4.0 zu installieren, müssen nur die benötigten JAR-Dateien ins Verzeichnis $TOMCAT_HOME/lib kopiert werden. Diese sind dann für alle Webanwendungen verfügbar. Auf der anderen Seite können die JAR-Dateien auch in das Verzeichnis WEB-INF/lib der einzelnen Webanwendungen installiert werden. Mit diesem Ansatz kann jede Anwendung eine andere Version der einzelnen Pakete verwenden, ohne daß es zu Konflikten kommen kann.

   

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema Java & XSLT bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © 2002 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "Java und XSLT" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O’Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de