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