# ServletContextListener: getAttribute und setAttribute



## wolfgke (14. Sep 2008)

Hallo,
ich habe einen ServletContextListener erstellt. Code-Auszug:

```
public class ThinxelsOnFlowListener implements ServletContextListener,
        HttpSessionListener, HttpSessionAttributeListener {

    @Override
    public void contextInitialized(ServletContextEvent e) {
        Logger.getLogger(ThinxelsOnFlowListener.class.getName()).log(Level.INFO, 
                "Initialized "+e.getServletContext().toString());
        
        e.getServletContext().setAttribute(ContextAttributes.SESSION_LIST,
                new HashMap<String, HttpSession>());
        try {
            Logger.getLogger(ThinxelsOnFlowListener.class.getName()).log(Level.INFO, 
                    "Starting OTP node");
            
            OtpNode node = new OtpNode(
                    e.getServletContext().getInitParameter(ContextInitParameters.OTP_SELF_NODE), 
                    e.getServletContext().getInitParameter(ContextInitParameters.OTP_COOKIE)
                    );
            
             Logger.getLogger(ThinxelsOnFlowListener.class.getName()).log(Level.INFO, 
                    "Node="+node);
            
            e.getServletContext().setAttribute(ContextAttributes.OTP_NODE, node);
            
        } catch (IOException ex) {
            Logger.getLogger(ThinxelsOnFlowListener.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent e) {
        Logger.getLogger(ThinxelsOnFlowListener.class.getName()).log(Level.INFO, 
                "Destroyed "+e.getServletContext().toString());
        
        OtpNode node = (OtpNode) e.getServletContext().getAttribute(ContextAttributes.OTP_NODE);
        if (node != null) {
            Logger.getLogger(ThinxelsOnFlowListener.class.getName()).log(Level.INFO, 
                    "Closing OTP node");
            node.close();
        }
        else {
            Logger.getLogger(ThinxelsOnFlowListener.class.getName()).log(Level.WARNING, 
                    "No OTP node exists to close");
        }
    }

// ... Implementation der anderen Interfaces
}
```

Theoretisch sollte beim Hoch- und anschließendem Runterfahren des Servers folgendes Verhalten zu beobachten sein:

Hochfahren:
Ausgabe "Initialized "+irgendetwas
Ausgabe "Starting OTP node"
Ausgabe "Node="+irgendetwas

Herunterfahren:
Ausgabe "Destroyed "+irgendetwas
Ausgabe "Closing OTP node"

Dies ist jedoch die Ausgabe, welche tatsächlich kommt:

Hochfahren (abgesehen, dass anscheinend 2 Servlet-Kontexte initialisiert werden - Ursache unbekannt, tritt vor allem das Problem auf, dass er anscheinend beim kurzzeitig darauffolgenden Herunterfahren von org.apache.catalina.core.ApplicationContextFacade@f7ce53 nichts mehr vom Context-Attribute ContextAttributes.OTP_NODE etwas weiß...)


> [...]
> WEB0712: Sun-Java-System/Application-Server HTTP/1.1 wird gestartet auf 8080
> WEB0712: Sun-Java-System/Application-Server HTTP/1.1 wird gestartet auf 8181
> WEB0712: Sun-Java-System/Application-Server HTTP/1.1 wird gestartet auf 4848
> ...



Herunterfahren:


> WEB0303: Sun-Java-System/Application-Server wird gestoppt.
> WEB0713: Sun-Java-System/Application-Server HTTP/1.1 wird gestoppt auf 8080
> WEB0713: Sun-Java-System/Application-Server HTTP/1.1 wird gestoppt auf 8181
> WEB0713: Sun-Java-System/Application-Server HTTP/1.1 wird gestoppt auf 4848
> ...



Auch hier weiß er beim Herunterfahren von org.apache.catalina.core.ApplicationContextFacade@c235e1 offensichtlich nichts von dem aktuellen Wert dieses Context-Attributs.

Ich habe hier echt schon alles, was mir einfällt probiert, aber ich kann nicht herausfinden, wie ich mein Programm dazu bringen kann, dass er, wenn contextDestroyed() vom Servlet-Container von Glassfish aufgerufen wird, diesen Attributwert noch "weiß".

Ich starte das ganze mit Netbeans+Glassfish über den "Ausführen"-Button.

Bonusfrage: warum werden 2 Kontexte erzeugt und der eine sofort wieder zerstört?


----------



## wolfgke (15. Sep 2008)

Nur damit mir niemand vorwirft, ich könnte nicht googlen:

ich habe einen weiteren Thread in einem ganz anderen Forum gefunden, wo ein ähnliches Problem (mit Tomcat statt Glassfish) geschildert wird:

http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=56&t=003337

Nur: die .war-Datei, die hier zum Testen angeboten wird gibt es nicht mehr.


----------



## wolfgke (15. Sep 2008)

Durch zusätzliches Implementieren des Interface ServletContextAttributeListener fand ich heraus, dass anscheinend zuerst alle Context-Attribute gelöscht werden, bevor contextDestroyed aufgerufen wird. Welchen Sinn hat dieses Verhalten? Und vor allem: man findet viel Quellcode im Netz, wo in contextDestroyed noch allerhand z. B. Datenbank-Verbindungen, die als Context-Attribute gespeichert werden, geschlossen werden (x-beliebiges Beispiel: http://www.onjava.com/onjava/2003/01/08/examples/ContextListener.html ).

Habe ich irgendetwas falsch gemacht oder warum ist die Reihenfolge des Aufrufs exakt umgekehrt bei mir?

Das einzige, was ich beim Glassfish-Server geändert habe, ist Comet aktiviert zu haben, da ich es in Zukunft brauchen werde.


----------

