$KK(scopes)
$R(Objective)
For the fundamental servlet attribute scopes (request, session, and context): write servlet code to
add, retrieve, and remove attributes; given a usage scenario, identify the proper scope for an attribute;
and identify multi-threading issues associated with each scope.
$R\
$KKK(Überblick)
Innerhalb von Web-Applikationen kommunizieren verschiedene Servlets miteinander. Sie
benötigen dazu einen gemeinsamen Bereich, mit dem sie Daten lesen bzw. austauschen
können. Die Servlet Spezifikation definiert dazu 3 verschiededen Scopes, die es erlauben
Attribute zu speichern und zu lesen.
Ihre Interfaces sind jeweils identisch, die Scopes unterscheiden sich lediglich in der
Lebensdauer.
$T(simple,cl,25.75)
request | Gültig für eine einzige Anfrage (i.a. an ein Servlet). Ein Servlet kann mittels
RequestDispatcher die Anfrage an mehreren anderen Servlets weiterleiten. Dann sind die
Attribute, die in dem request gespeichert werden, auch in diesen anderen Servlets sichtbar.
Wurde eine Anfrage abgearbeitet, so verliert man den Zugriff auf diese Attribute ||
session | Eine Session wird von einem einzigen Anwender in einem Browser angestossen,
und ist solange gültig bis sich der Anwender explizit abmeldet, oder der Servlet Container die
Session von sich aus beendet hat (z.B. falls lange keine Interaktion in dieser Session
gemacht wurde). I.a. geht eine Session von einem einzigen Browser aus, es sei denn der
Anwender öffnet aus diesem Browser aus einen 2. Fenster. (Wenn der Anwender dann noch Cookies
verbietet funktioniert das Session Management nicht mehr)||
context | Die Servlets einer Webapplikation teilen sich alle einen gemeinsamen
ServletContext. Alle Anfragen aller Anwender dieser Webapplikationen können auf die
Attribute des ServletContext zugreifen ||
$T\
$KKK(Das Interface)
Die folgende Tabelle zeigt, wie der Programmierer die verschiedenen Scopes erreicht.
$T(simple,cl,25.75)
request | Hier sind die Attribute an ein (Http)ServletRequest Instanz gebunden,
die in der doService() Methode eines HttpServlets als Parameter mitgegeben
wird ||
session | Von einer Instanz einer HttpServletRequest aus, bekommt man die aktuelle
HttpSession durch die Methode getSession() bzw. getSession(true) ||
context | Zu dem Context eines Servlets gelangt man vom HttpServlet aus, durch die
Methode getServletContext() ||
$T\
Das Interface um Attribute zu speichern, lesen und löschen sind für alle scopes identisch.
$S()
public interface ServletRequest (bzw. HttpSession oder ServletContext){
Object getAttribute(String name);
Enumeration getAttributeNames();
void setAttribute(String name, Object o);
void removeAttribute(String name);
}
$S\
Für die Attributnamen gibt es Konventionen:
* Attributnamen sollte man wie PackageNamen behandeln.Ein Attributname solle die Form haben
wie z.B.: meineFirma.meineWebApplikation.meinServlet.AttributName
* Es sollte nie derselbe Attributname in verschiedene Scopes sein. Ggf können einige
ServletContainer damit nicht umgehen.
$KKK(Überlegungungen zum Umgang mit Threads)
Ein WebServer wird i.a. paralell mit Anfragen bombadiert. Dabei kann es zu Problemen kommen,
wenn ein Thread ein Attribut ändert, das gerade ein anderer Thread in Bearbeitung hat.
* Bei Request Attribute ist man auf der sicheren Seite, da wenn 2 Anwender eine Anfrage
stellen, es verschiedene Instanzen dieses Servlets gebildet werden.
* Bei Session Attribute ist man leider nicht immer auf der sicheren Seite, da der Anwender
2 oder mehrere Fenster eines Browser geöffnet haben kann. Hier ist der Programmierer
dafür verantwortlich, dass ein Thread nur exclusiv Zugriff auf ein Attribut bzw Session hat.
$S()
HttpSession session = req.getSession();
synchronized(session){
session.removeAttribute(name);
}
$S\
Da ein Benutzer i.a. nicht hunderte von Browser geöffnet hat, ergibt sich dadurch aus Sicht
der Performance keinen Flaschenhals.
* Context Attribute sind von allen Threads sichtbar und veränderbar. Natürlich kann man
diese auch synchronisieren, allerdings kann man sich dadurch grosse Performance Probleme
einhandeln. Man sollte deshalb im ContextScope nur Attribute benutzen, die sich sehr selten ändern.
$KKK(Verhalten in einer verteilten Umgebung)
Bei grösseren Anwendungen sind die Servlets auf mehreren Rechnern verteilt. So kann z.B.
ein ServletContainer auf mehreren Maschinen mit verschiedenen Java Virtuellen Maschinen
(JVM) arbeiten. Dies hat folgende Vorteile
* Fail-over support - Fällt eine Maschine aus, so kann einfach die andere Maschine,
die Arbeit übernehmen.
* Load-balancing - ermöglicht eine weitgehend gleichmässige Auslastung der Server
Verteilte Anwendungen sind alles andere als trivial und wirken sich auf die Programmierung aus.
D.h. Eine Applikation entwickelt für eine Maschine mit einer JVM kann nicht ohne groesseren
Aufwand umkonfiguriert werden, so dass sie auf mehreren Maschinen läuft
* Wir können nicht annehmen, daß nur eine Instanz eines Servlets existiert, d.h. in einer
verteilten Umgebung ist es problematisch Informationen in statischen bzw. Instanzvariablen
zu speichern.
* Wir können nicht das lokale FileSystem benutzen.
* Verschiedene Maschinen haben verschiedene ServletContexte, d.h statt Attribute in einem
ServletContext zu speichern, sollte man diese lieber in eine Datenbank abspeichern.
Verhalten von Servlet Context
Für jede Webapplikation gibt es pro virtuelle Maschine genau einen ServletContext. In einer
verteilten Anwendung, gibt es aber i.a. mehrerer JVM und deshalb mehrere ServletContexte pro
Webapplikation.
* Die Attribute eines ServletContext sind für einen anderen ServletContext nicht sichtbar.
Es ist besser diese Attribute in einer Datenbank oder in einer Session zu speichern.
* Bei Änderungen in einem ServletContext können über Listener Objekte keine Methoden aus einem
anderen JVM ausgelöst werden.
* Servlet Context Initialisierungs Parameter sind in allen JVM's sichtbar, da diese im Deployment
Descriptor web.xml definiert worden sind
Verhalten von Http Session
Eine Session kann zu einem Zeitpunkt immer auf genau einer JVM laufen. Allerdings ist es
erlaubt eine Session von einer JVM zu einer anderen zu migrieren.
* Eine HttpSession kann nie gleichzeitig auf 2 verschiedenen JVM laufen.
* Ein HttpSessionEvent kann nicht zu anderen JVM weitergeleitet werden.
* Damit eines Session auf eine andere Maschinen migriert werden kann, müssen ihre Attribute
das Serializable Interface erfüllen. Ansonsten wird eine Illegal Argument Exception
ausgelöst.
* Wird eine Session migriert, werden alle Attribute die das HttpSessionActivationListener
Interface erfüllen benachrichtigt.