TagExtraInfo

Werbung
TagExtraInfo
•
Methode getVariableInfo(TagData)
–
•
•
Liefert Informationen über Skript−Variable an den JSP−
Compiler.
TagData−Parameter enthält die in der JSP−Seite
angegebenen Attribute des Tags.
–
<x:bar id="sample">
<p>Typ der Variablen:
<%= sample.getClass().getName() %>.</p>
</x:bar>
–
getAttributes(), getAttribute(), getId()
boolean isValid(TagData data)
–
Prüfung der Attribute zur Übersetzungszeit
Web−Anwendungen mit Java
501
Skript−Variablen: generierter Code
•
JSP−Compiler ruft getVariableInfo(TagData)
auf und generiert Deklaration und Initialisierung.
_jspx_th_bar_bar_0.doInitBody();
do {
java.security.Signature sample = null;
sample = (java.security.Signature)
pageContext.findAttribute("sample");
out.write("Bar");
} while (_jspx_th_bar_bar_0.doAfterBody() ==
BodyTag.EVAL_BODY_AGAIN);
Web−Anwendungen mit Java
502
Skriptvariable im TLD definieren
•
Statt über TagExtraInfo lassen sich
Skriptvariable statisch im TLD definieren.
•
Beispiel
<tag>
<name>foo</name>
<tag−class>de.rainer_klute.Foo</tag−class>
<variable>
<name−from−attribute>bar−id</name−from−attribute>
<variable−class>java.lang.String</variable−class>
<scope>NESTED</scope>
</variable>
<attribute>
<name>bar−id</name>
<required>true</required>
</attribute>
</tag>
Web−Anwendungen mit Java
503
URIs und TLDs
•
•
Zum Finden des TLD zwei Zuordnungen erforderlich
–
JSP−Seite: Präfix → URI
–
Deployment descriptor: URI → TLD
Implizite Zuordnung vermeidet zweiten Schritt
–
TLD spezifiziert »seinen« URI in einem Element <uri>.
–
JSP−Container untersucht alle TLDs und »weiß« danach,
welcher URI welchem TLD entspricht.
•
Explizite Zuordnungen haben Vorrang.
•
JSP−Container kann weitere implizite
Zuordnungen treffen.
•
Weitere Details siehe JSP−Spezifikation
Web−Anwendungen mit Java
504
Gut verpackt: Tag libs »aus der Dose«
•
Vorgefertigte Tag libs unmittelbar nutzen
–
•
•
Möglich durch implizite Zuordnungen
Gruppe zusammengehörender Aktionen in JAR−Datei
verpackt
–
TLDs in META−INF spezifizieren URI (<uri>−Element)
–
TLD besitzen Endung .tld, z.B. META−INF/foo.tld, META−
INF/bar.tld usw.
–
Spezifizierte Klassen werden im Classpath gesucht.
Bedienungsanleitung
–
JAR−Datei nach WEB−INF/lib der
Web−Anwendung kopieren (JAR−Datei gehört
dadurch zum Classpath)
Web−Anwendungen mit Java
505
Listener
•
Listener werden über Anwendungsereignisse
informiert.
•
Siehe Servlet−Kapitel
•
JSP erlaubt Angabe von Listener−Klassen im TLD
•
Vorteil: Eine einzige JAR−Datei bündelt
–
Listener
–
Tag handler
–
TLD
Web−Anwendungen mit Java
506
Validierung
•
Tag lib kann JSP−Seite validieren.
•
Im TLD Element <validator> angeben. Beispiel:
<validator>
<validator−class>
de.rainer_klute.plz.Validator
</validator−class>
<init−param>
<param−name>foo</param−name>
<param−value>bar</param−value>
</init−param>
</validator>
•
Validator−Klasse implementiert Interface
javax.servlet.jsp.tagext.TagLibraryValidator
Web−Anwendungen mit Java
507
TagLibraryValidator
•
•
void
setInitParameters(java.util.Map map)
–
Setzt die Init−Parameter
–
Aufruf durch JSP−Compiler
ValidationMessage[]
validate(String prefix, String uri,
PageData page)
–
Validiert eine JSP−Seite
–
Aufruf durch JSP−Compiler
–
Attribute von Aktionen lassen sich durch
TagExtraInfo.isValid() prüfen.
Web−Anwendungen mit Java
508
TagLibraryValidator
•
java.util.Map getInitParameters()
–
•
Liefert die Init−Parameter
void release()
–
Freigeben der Ressourcen der Validator−Klasse
–
Aufruf durch JSP−Compiler
Web−Anwendungen mit Java
509
PageData
•
JSP−Compiler übergibt PageData−Objekt an die
validate()−Methode.
•
PageData.getInputStream() liefert
InputStream.
•
InputStream enthält XML−Ansicht der JSP−Seite.
•
<%−Notation durch XML−Äquivalente ersetzt
•
Include−Direktiven aufgelöst → vollständige Seite
•
XML−Elemente möglicherweise mit jsp:id−Attributen
•
Für die Validierung ist ein XML−Parser hilfreich.
•
Ergebnis der Validierung: Array von
ValidationMessage−Objekten
Web−Anwendungen mit Java
510
ValidationMessage
•
Informiert über Fehler bei der Validierung
•
Validator erzeugt ValidationMessage
•
Konstruktor:
–
•
ValidationMessage(String id,
String message)
–
id: Wert von jsp:id, falls vorhanden
–
message: Text der Fehlermeldung
Methoden (vom JSP−Compiler aufgerufen)
–
String getId()
–
String getMessage()
Web−Anwendungen mit Java
511
TryCatchFinally
•
Hilfs−Interface für Tag handler, die z.B. Ressourcen
verwalten und nach Fehlern freigeben müssen
•
public class MyTagHandler
extends BodyTagSupport
implements TryCatchFinally
•
Methode doCatch(Throwable t)
–
•
Wird von JSP−Seite bei Fehler zwischen doStart()
und doEnd() aufgerufen.
Methode doFinally()
–
Wird von JSP−Seite immer nach doEnd()
aufgerufen.
Web−Anwendungen mit Java
512
Aufruf bei TryCatchFinally
h = ... // Tag handler
h.setPageContext(pc);
h.setParent(null);
h.setFoo("bar");
...
try
{
doStartTag();
...
doEndTag();
}
catch (Throwable t)
{
h.doCatch(t); // Exception bearbeiten
}
finally
{
h.doFinally(); // Immer ausführen
}
Web−Anwendungen mit Java
513
Noch einmal: Tag Library Descriptor
•
Aufbau etwas ausführlicher, siehe aber Details in
der JavaServer Pages 1.2 Specification
•
Wurzelelement: taglib
<?xml version="1.0" encoding="ISO−8859−1"?>
<!DOCTYPE taglib PUBLIC
"−//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web−jsptaglibrary_1_2.dtd">
<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">
...
</taglib>
•
DTD definiert das Inhaltsmodell von taglib:
DTD verstehen
•
<!ELEMENT taglib (tlib−version, jsp−
version, short−name, uri?, display−
name?, small−icon?, large−icon?,
description?, validator?, listener*,
tag+)>
•
<!ELEMENT (...)> definiert ein Element und legt
seinen Inhalt (Kind−Elemente) fest.
•
tlib−version, jsp−version: Definiert Reihenfolge
–
•
Hier: Genau ein tlib−version−Element gefolgt von
genau einem jsp−version−Element
uri?: ein optionales uri−Element (0 <= n <= 1)
Web−Anwendungen mit Java
515
DTD verstehen
•
listener*: optionale listener−Elemente (0 <= n)
•
tag+: Mindestens ein tag−Element (1 <= n)
•
foo | bar: Entweder ein foo−Element oder ein bar−
Element
•
(...): übliche Klammerregelung
Web−Anwendungen mit Java
516
TLD−Element »taglib«
•
tlib−version: Versionsnummer der Tag library
•
jsp−version: Versionsnummer der JSP−Spezifikation
•
short−name: Kurzname der Taglib, der z.B. als Präfix
genutzt werden kann
•
uri: eindeutiger URI der Taglib
•
display−name: »Lesbarer« Name der Taglib
Web−Anwendungen mit Java
517
TLD−Element »taglib«
•
small−icon: Name einer GIF− oder JPEG−Datei mit
16x16−Icon. Datei liegt relativ zum TLD und endet mit
.gif oder .jpg
•
large−icon: Name eines 32x32−Icons
•
description: Beschreibung der Taglib
•
validator: Validator−Spezifikation
•
listener: Listener−Spezifikation
•
tag: Spezifikation des/der Tags
Web−Anwendungen mit Java
518
TLD−Element »validator«
•
<!ELEMENT validator (validator−class,
init−param*, description?)>
•
Der Validator prüft die syntaktische Richtigkeit einer
JSP−Seite.
•
validator−class: Name der Validatorklasse
•
init−param: Initialisierungsparameter
•
description: Beschreibung
Web−Anwendungen mit Java
519
Element »init−param«
•
<!ELEMENT init−param (param−name,
param−value, description?)>
•
Spezifiziert ein Name−/Wert−Paar
•
param−name: Name des Parameters
•
param−value: Wert des Parameters
•
description: Beschreibung
Web−Anwendungen mit Java
520
TLD−Element »listener«
•
<!ELEMENT listener (listener−class)>
•
Wird bei Applikationsereignissen benachrichtigt
•
Details siehe Servlet−Kapitel und Servlet−Spezifikation
•
listener−class: Name der Listener−Klasse
Web−Anwendungen mit Java
521
TLD−Element »tag«
•
<!ELEMENT tag (name, tag−class, tei−
class?, body−content?, display−name?,
small−icon?, large−icon?, description?,
variable*, attribute*,example?)>
•
Spezifiziert ein Element (»Tag«) der Taglib
•
name: Name des Elements
•
tag−class: Tag−Klasse
•
tei−class: TagExtraInfo−Klasse
•
display−name: »Lesbarer« Name des Tags
•
description: Beschreibung des Tags
Web−Anwendungen mit Java
522
TLD−Element »tag«
•
small−icon: 16x16−Icon
•
large−icon: 32x32−Icon
•
body−content: Beschreibt den Body näher
–
JSP: Body enthält JSP−Elemente oder ist leer
(Voreinstellung).
–
tagdependent: Body enthält tag−spezifischen Inhalt,
z.B. SQL−Anweisungen oder ist leer.
–
empty: Body muß leer sein.
•
variable: Spezifikation einer Skriptvariablen
•
attribute: Spezifikation eines Attributs
•
example: Beispiel für die Verwendung des Tags
Web−Anwendungen mit Java
523
TLD−Element »variable«
•
<!ELEMENT variable ( (name−given | name−
from−attribute), variable−class?,
declare?, scope?, description?)>
•
Beschreibt eine Skriptvariable.
•
name−given: Name der Variablen
•
name−from−attribute: Name der Variablen ergibt sich
aus dem Namen dieses Attributs
•
variable−class: Klassenname der Variablen.
Voreinstellung: java.lang.String
•
declare: Gibt an, ob die Variable hier deklariert
wird. Voreinstellung: true
Web−Anwendungen mit Java
524
TLD−Element »variable«
•
•
scope: Geltungsbereich der Skriptvariable
–
NESTED: vom Start−Tag bis zum Ende−Tag
(Voreinstellung)
–
AT_BEGIN: vom Start−Tag bis zum Ende der Seite
–
AT_END: vom Start−Tag bis zum Ende der Seite
description: Beschreibung der Variablen
Web−Anwendungen mit Java
525
TLD−Element »attribute«
•
<!ELEMENT attribute (name, required?,
rtexprvalue?, type?, description?)>
•
Spezifiziert ein Attribut
•
name: Name des Attributs
•
required: Muß Attribut angegeben werden?
–
Werte: true | false | yes | no
(Voreinstellung: false)
Web−Anwendungen mit Java
526
TLD−Element »attribute«
•
rtexprvalue: Ausdrücke zur Laufzeit zulässig?
–
Werte: true | false | yes | no
(Voreinstellung: false)
•
type: Klasse des Attributs. Bei statischen Attributen
immer java.lang.String
•
description: Beschreibung der Variablen
Web−Anwendungen mit Java
527
Java 2 Enterprise Edition (J2EE)
Java 2
Enterprise Edition
(J2EE)
Web−Anwendungen mit Java
528
Zwei−Schichten−Architektur
•
Bisherige Anwendungen: Zwei−Schichten−Architektur
•
Anwendungslogik und Präsentation in derselben JVM
•
Skalierbarkeit schwierig
JSPs/Servlets + weitere Klassen
Datenbank
Web−Anwendungen mit Java
Anwendungslogik, Präsentation
Daten
529
Mehrschichten−Architektur
•
J2EE trennt Präsentation und Anwendungslogik.
•
Geschäftsobjekte als Enterprise Java Beans (EJBs)
•
EJBs laufen verteilt in EJB−Containern.
JSPs/Servlets + weitere Klassen
EJBs
Anwendungslogik
Datenbank
Web−Anwendungen mit Java
Präsentation
Daten
530
Architektur Web−Anwendung
HTTP/
SSL
Servlet / JSP
JDBC
Web−Container
Web−Browser
Web−Anwendungen mit Java
531
Servlet / JSP
Web−Anwendungen mit Java
Appl. Client
EJB
JDBC
HTTP/
SSL
Application
Client Container
Applet
EJB−Container
Web−Container
Applet−
Container
Architektur J2EE−Anwendung
532
J2EE−Standarddienste
•
In jedem J2EE−Container verfügbar
–
•
Application Server
Herstellerunabhängig
–
HTTP, HTTPS
–
–
Java Naming and Directory
Interface (JNDI)
JavaBeans Activation
Framework (JAF)
–
Java Message Service (JMS)
–
JDBC
–
–
Java Transaction API (JTA)
Java Authentication and
Authorization Service (JAAS)
–
RMI−IIOP
–
–
Java IDL
Java API for XML Parsing
(JAXP)
–
JavaMail
–
J2EE Connector
Architecture
Web−Anwendungen mit Java
533
Architektur J2EE−Anwendung (II)
Applet−Container
Web−Anwendungen mit Java
534
JAF
JDBC
Java
Mail
JAXP
JTA
JAAS
JMS
Connectors
JAF
JDBC
Java
Mail
JAXP
JTA
JAAS
EJB
JMS
Servlet / JSP
JDBC
Appl. Client
JAXP
EJB−Container
JAAS
Web−Container
JMS
Application Client
Container
Connectors
Applet
Serialisierung
Serialisierung
Web−Anwendungen mit Java
535
Serialisierung: Anforderungen
•
•
Persistente Objekte
–
Anwendung speichert Objekte permanent.
–
Späterer Lauf der Anwendung lädt gespeicherte Objekte.
Verteilte Objekte
–
Objekte von einer JVM zur anderen übertragen (→RMI)
•
Speichern / Übertragen aller Objekte, die vom
Ausgangsobjekt aus erreichbar sind
•
Erweiterbar
–
•
Künftige Versionen der Klasse unterstützen
Einfach
Web−Anwendungen mit Java
536
Serialisierung: Beispiel
•
Serialisierung: Objekt(e) speichern
•
Deserialisierung: Objekt(e) laden
•
Beispiel:
List list;
Set set;
/* List und Set mit Daten füllen */
FileOutputStream fos = new FileOutputStream("datei.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(list);
oos.writeObject(set);
oos.close();
FileInputStream fis = new FileInputStream("datei.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
list = (List) ois.readObject();
set = (Set) ois.readObject();
fis.close();
Web−Anwendungen mit Java
537
Serialisierung: Alternativen
•
Voreingestellte Serialisierung
–
(De−)Serialisieren aller Felder des Objekts
–
Ausnahmen: statische und transiente Felder
–
Klasse implementiert Interface Serializable.
–
•
Marker−Interface, keine Implementierung von Methoden nötig
Klassendefinierte Serialisierung
–
(De−)Serialisieren ausgewählter Felder
–
Felder müssen nicht denen der Klasse entsprechen.
–
–
Weiterentwicklung der Klasse
Klasse implementiert Serializable und
spezifiziert Felder.
Web−Anwendungen mit Java
538
Serialisierung: Alternativen
•
Externalisierung
–
Klasse nutzt die Serialisierungsmechanismen nicht.
–
Klasse ist selbst für korrektes Schreiben und Lesen der
externalisierten Daten verantwortlich.
–
Klasse implementiert Interface Externalizable.
–
–
public void writeExternal(ObjectOutput out)
throws IOException
public void readExternal(ObjectInput in) throws
IOException, ClassNotFoundException
Web−Anwendungen mit Java
539
Weiterentwicklung von Klassen
•
Neue Version einer Klasse ersetzt alte Version
–
Alte Klasse verwaltet einen DM−Betrag
–
Neue Klasse verwaltet Euro
–
Anforderung: automatische Umstellung
•
Deserialisierung eines alten Objekts mit
readObject() liefert InvalidClassException.
•
Jede Klasse enthält eine Seriennummer.
•
Neue Seriennummer bei signifikanten Änderungen
–
Neues oder gelöschtes Feld, neue oder gelöschte
Methode, geänderte Signatur einer Methode usw.
–
Nicht: Änderung im Methodenrumpf
Web−Anwendungen mit Java
540
Beispiel: Sum.java
package de.rainer_klute.serialization;
import java.io.*;
/**
* <p>Maintains a currency value (in DM).</p>
*/
public class Sum implements Serializable
{
private float sum;
public Sum()
{
sum = 0.0f;
}
Web−Anwendungen mit Java
541
Beispiel: Sum.java
float getSum()
{
return sum;
}
void add(float d)
{
sum += d;
}
}
Web−Anwendungen mit Java
542
Beispiel: Summing1.java
Sum sum;
final String FILENAME = "sum.ser";
if (new File(FILENAME).exists())
{
FileInputStream fis = new FileInputStream(FILENAME);
ObjectInputStream ois = new ObjectInputStream(fis);
sum = (Sum) ois.readObject();
fis.close();
}
else
sum = new Sum();
sum.add(Float.parseFloat(args[0]));
FileOutputStream fos = new FileOutputStream(FILENAME);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(sum);
oos.close();
System.out.println("Sum is now " + sum.getSum() +
" DM.");
Web−Anwendungen mit Java
543
Änderungsstrategie
•
Inkompatible Klassen kompatibel machen
•
Seriennummer der alten Klasse ermitteln
–
serialver de.rainer_klute.serialization.Sum
–
de.rainer_klute.serialization.Sum:
static final long
serialVersionUID = 3834243616784878964L;
•
Ausgabe des Kommandos serialver als Deklaration in
die neue Klasse übernehmen
•
Deserialisierung anpassen:
–
Alte Objekte erkennen
–
Alte Werte in neues Objekt einlesen
Web−Anwendungen mit Java
544
Beispiel: Sum.java (neue Version)
package de.rainer_klute.serialization;
import java.io.*;
/**
* <p>Maintains a currency value. An old version of this
* class could cope with DM only and kept it in a field
* named "sum". The new version supports Euro instead of
* DM. Conversion of old serialized objects happens
* automatically when the old object is deserialized.</p>
*/
public class Sum implements Serializable
{
static final long
serialVersionUID = 3834243616784878964L;
private float sumEuro;
Web−Anwendungen mit Java
545
Beispiel: Sum.java (neue Version)
public Sum()
{
sumEuro = 0.0F;
}
float getSum()
{
return sumEuro;
}
void add(float d)
{
sumEuro += d;
}
Web−Anwendungen mit Java
546
Beispiel: Sum.java (neue Version)
}
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException
{
ObjectInputStream.GetField gf = in.readFields();
ObjectStreamClass osc = gf.getObjectStreamClass();
ObjectStreamField field = osc.getField("sumEuro");
if (field != null)
{
System.out.println("New class version");
sumEuro = gf.get("sumEuro", 0f);
}
else
{
System.out.println("Old class version");
float f = gf.get("sum", 0f);
System.out.print(f + " DM ");
f = Math.round(f / 195.583f) / 100f;
System.out.println("converted to " + f + " EUR.");
sumEuro = f;
}
}
Web−Anwendungen mit Java
547
Alte und neue Klasse unterscheiden
•
Unterscheidungskriterium: Feldnamen oder
−typen in alter und neuer Klasse
–
•
Hier: feststellen, ob Feld "sum" oder "sumEuro" in
serialisiertem Objekt vorhanden
Besser: eigene Versionsnummer der Klasse in
Feldnamen kodieren
–
int classVersion_42;
–
Mit ObjectStreamClass−Methode
ObjectStreamField[] getFields() herausfinden,
welches Feld mit »classVersion_« beginnt
–
Rest des Feldnamens ist die Versionsnummer.
Web−Anwendungen mit Java
548
Remote Method Invocation (RMI)
Remote Method
Invocation (RMI)
Web−Anwendungen mit Java
549
Remote Method Invocation (RMI)
•
Zusammenarbeit zwischen verschiedenen JVM
•
Objekt in entfernter JVM (Remote−Objekt)
referenzieren
–
•
Methoden des entfernten Objekts aufrufen
Objekt von einer JVM zur anderen übertragen
–
Objekt muß serialisierbar sein.
Web−Anwendungen mit Java
550
Herunterladen