Anwendung des Stylesheet-Cache

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

Wir haben jetzt zwei Möglichkeiten kennengelernt, mit denen man das feste Einprogrammieren des absoluten Pfades von XSLT-Stylesheets im Servlet vermeiden kann. Im ersten Ansatz wurde ServletContext verwendet, um Ressourcen aus einer Webanwendung mittels relativer Pfadnamen zu laden. Im zweiten Ansatz wurde die Position als Context-Initialisierungsparameter festgelegt.

Dies betraf Änderungen zur Übersetzungszeit, doch jetzt wollen wir uns dem dynamischen Laden zuwenden. In der Klasse PersonalDataServlet werden die beiden XSLT-Stylesheets lokalisiert und in Instanzen des Interface javax.xml.transform.Templates »kompiliert«. Dadurch wird zwar eine hohe Leistungsfähigkeit der Transformationen erreicht, die Stylesheets werden aber nie aus dem Speicher entfernt. Wenn die XSLT-Stylesheets geändert werden, muß das Servlet gestoppt und neu gestartet werden.

Integration des Stylesheet-Cache

Unter XSLT-Verarbeitung mit Java wurde ein Stylesheet-Cache implementiert. Im nächsten Beispiel wird unser PersonalDataServlet so modifiziert, daß es mit diesem Cache und nicht direkt mit den Templates arbeitet. Das ermöglicht nahezu dieselbe Laufzeit-Performance. Trotzdem können Sie das Stylesheet modifizieren und die Änderungen sofort im Browser sehen. Jedesmal wenn ein Stylesheet angefordert wird, überprüft der Cache seinen Zeitstempel im Dateisystem. Wurde die Datei geändert, wird eine neue Instanz von Templates erzeugt, ohne den Server zu beenden und neu zu starten.

Glücklicherweise wird durch die Integration des Cache die Implementierung des Servlets PersonalDataServlet einfacher. Das folgende Beispiel zeigt den geänderten Programmcode.

Beispiel: Geändertes PersonalDataServlet.java mit dem Stylesheet-Cache

package chap6;

import com.oreilly.javaxslt.util.StylesheetCache;
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

/**
 * Eine Modifikation des PersonalDataServlets, das die
 * Klasse com.oreilly.javaxslt.util.StylesheetCache verwendet.
 */
public class PersonalDataServlet extends HttpServlet {
  private PersonalDataXML personalDataXML = new PersonalDataXML( );
  private String editXSLTFileName;
  private String thanksXSLTFileName;
  
  /**
   * Einmalige Initialisierung des Servlets.
   */
  public void init( ) throws UnavailableException {
    this.editXSLTFileName = getServletContext( ).getRealPath(
      "/WEB-INF/xslt/editPersonalData.xslt");
    this.thanksXSLTFileName = getServletContext( ).getRealPath(
      "/WEB-INF/xslt/confirmPersonalData.xslt");
  }
  
  /**
   * Bearbeitet HTTP GET-Anfragen, z.B. wenn der Nutzer eine
   * URL eingibt oder einen Link betätigt.
   */
  protected void doGet(HttpServletRequest request,
      HttpServletResponse response) throws IOException,
      ServletException {
    PersonalData personalData = getPersonalData(request);
    // Der dritte Parameter 'false' bewirkt, daß beim Anzeigen
    // der Seite keine Fehlermeldungen ausgegeben werden.
    showPage(response, personalData, false, this.editXSLTFileName);
  }
  
  /**
   * Bearbeitet HTTP POST-Anfragen, z.B. wenn der Nutzer den
   * Senden-Button betätigt, um seine Informationen abzuschicken.
   */
  protected void doPost(HttpServletRequest request,
      HttpServletResponse response) throws IOException,
      ServletException {
    // Hole das Objekt personalData und beschreibe es mit den Informationen,
    // die der Nutzer übermittelt hat.
    PersonalData pd = getPersonalData(request);
    pd.setFirstName(request.getParameter("firstName"));
    pd.setLastName(request.getParameter("lastName"));
    pd.setDaytimePhone(request.getParameter("daytimePhone"));
    pd.setEveningPhone(request.getParameter("eveningPhone"));
    pd.setEmail(request.getParameter("email"));
        
    if (!pd.isValid( )) {
      // Zeige die Seite 'Ändern' mit einer Fehlermeldung
      showPage(response, pd, true, this.editXSLTFileName);
    } else {
      // zeige die Seite 'Bestätigung'
      showPage(response, pd, false, this.thanksXSLTFileName);
    }
  }
  
  /**
   * Eine Hilfsmethode, die die persönlichen Daten als HTML an den
   * Browser des Client schickt. Dabei wird ein XSLT-Stylesheet auf den
   * DOM-Baum angewendet.
   */
  private void showPage(HttpServletResponse response,
      PersonalData personalData, boolean includeErrors,
      String xsltFileName) throws IOException, ServletException {
    try {
      org.w3c.dom.Document domDoc =
        this.personalDataXML.produceDOMDocument(
        personalData, includeErrors);
      
      Transformer trans =
        StylesheetCache.newTransformer(xsltFileName);
      
      response.setContentType("text/html");
      PrintWriter writer = response.getWriter( );
      
      trans.transform(new DOMSource(domDoc), new StreamResult(writer));
    } catch (Exception ex) {
      showErrorPage(response, ex);
    }
  }
  
  /**
   * Falls ein Fehler auftritt, kann diese Methode den
   * Stack-Trace im Browser darstellen.
   */
  private void showErrorPage(HttpServletResponse response,
      Throwable throwable) throws IOException {
    PrintWriter pw = response.getWriter( );
    pw.println("<html><body><h1>Ein Fehler ist aufgetreten</h1><pre>");
    throwable.printStackTrace(pw);
    pw.println("</pre></body></html>");
  }
  
  /**
   * Eine Hilfsmethode, die das Objekt PersonalData aus der HttpSession ermittelt.
   */
  private PersonalData getPersonalData(HttpServletRequest request) {
    HttpSession session = request.getSession(true);
    PersonalData pd = (PersonalData) session.getAttribute(
          "chap6.PersonalData");
    if (pd == null) {
        pd = new PersonalData( );
        session.setAttribute("chap6.PersonalData", pd);
    }
    return pd;
  }
}

Der Hauptunterschied zur ersten Implementierung ist die Abhängigkeit von der Klasse com.oreilly.javaxslt.util.StylesheetCache. Das erfordert natürlich, daß StylesheetCache.class im entsprechenden Verzeichnis zur WAR-Datei hinzugefügt wird. Eine andere Möglichkeit ist es, den Stylesheet-Cache in eine JAR-Datei zu packen und diese in das Verzeichnis TOMCAT_HOME/lib zu kopieren. Dieser Ansatz wird im Beispielcode zu diesem Buch verfolgt.

Die größten Einsparungen im Code finden sich in der Methode init( ), denn hier werden nur die Namen der Stylesheet-Dateien gespeichert, anstelle der Instanzen von Templates. Das ist so, weil der Stylesheet-Cache Dateinamen als Input verlangt und seine eigenen Instanzen von Templates erzeugt. Dasselbe gilt für die meisten Änderungen am Servlet.

Wenn Sie es geschafft haben, das Beispiel zum Laufen zu bekommen, ist es ein leichtes, die Fähigkeiten des dynamischen Ladens zu testen. Wie vorher wird chap6.war ins Verzeichnis TOMCAT_HOME/webapps kopiert. Wenn Sie das Servlet das erste Mal aufrufen, wird die WAR-Datei ins Verzeichnis TOMCAT_HOME/webapps/chap6 entpackt. Wechseln Sie einfach ins Verzeichnis TOMCAT_HOME/webapps/chap6/WEB-INF/xslt, und verändern Sie eines der Stylesheets. Wenn Sie nun den Aktualisieren-Button in Ihrem Browser betätigen, sollten Sie das Resultat Ihrer Änderungen sehen.

Wenn sich Ihre Änderungen nicht auswirken, existieren wahrscheinlich einige ältere Dateien aus früheren Beispielen dieses Kapitels. Beenden Sie Tomcat, und löschen Sie sowohl chap6.war als auch das Verzeichnis chap6 aus dem Verzeichnis webapps von Tomcat. Installieren Sie es neu, und versuchen Sie es noch einmal.

   

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