Section 4: Session Management


 

4.1 Write servlet code to store objects into a session object and retrieve objects from a session object.

** Quizás este objetivo debería ser estudiado cronologicamente después del objetivo 4.2, es decir después de saber como obtener una sesión desde un servlet.

Una vez obtenida la sesión, podemos asociar objetos a ella de la misma manera que asociabamos objetos a los otros scopes, es decir utilizando el método setAttribute().

 void setAttribute(java.lang.String name, java.lang.Object value)
          Binds an object to this session, using the name specified.

Para obtener los atributos, utilizamos las funciones getAttribute(String) y getAttributeNames() que retorna una enumeration.

java.lang.Object getAttribute(java.lang.String name)
          Returns the object bound with the specified name in this session, or null if no object is bound under the name.

** Recordá que este método retorn un object, por lo que debes castearlo al objeto que necesitas!

java.util.Enumeration getAttributeNames()
          Returns an Enumeration of String objects containing the names of all the objects bound to this session.

Para borrar un atributo de la sesión utilizamos el método removeAttribute().

4.2 Given a scenario describe the APIs used to access the session object, explain when the session object was created, and describe the mechanisms used to destroy the session object, and when it was destroyed.

HTTP es un protocolo stateless, es decir que no mantiene ningun estado de los diferentes requerimientos que hace un cliente. Muchas veces sin embargo, surge el requerimiento de guardar cierta información a través de un un conjunto de requerimientos. Para lidiar con esto, la especificación de servlets provee las sesiones, a través del objeto HttpSession (Notar que las sesiones tienen que ver con HTTP, por lo que no existe un objeto Session).
Para mantener una sesión, debemos hacer 2 llamadas a getHttpSession. La primera será hecha en el servlet desde donde se desea mantener la sesión (osea en el punto que se desea 'crear' la sesión). Para ello, se hace la siguiente llamada:

HttpSession session = request.getSession();

Este método creará una sesion en estado 'new'. En el próximo requerimiento desde el mismo browser o desde un browser abierto desde el browser original (y que probablemente sea a otro servlet), la llamada a este método retornará el mismo objeto sesión.

El método getSession esta sobrecargado

getSession()
getSession(boolean session)

En la segunda versión, el parámetro identifica si se quiere crear o no una nueva sesión (osea que si el parametro es false, la sesión no se creará).

Sesiones Distribuidas

Cual es el efecto de una aplicación distribuida sobre las sesiones? Las sesiones deberían estar replicadas en las 2 instancias. Osea que si una de las aplicaciones falla, el failover server debería tener toda la información de las sesiones replicadas. Esto agrega la necesidad que los atributos de las sesiones sean serializables.

Cuando muere una sesión

Podes matarla utilizando el método invalidate() exprofeso o se puede acabar el tiempo disponible para la sesión. El tiempo que se le da a la sesión puede venir de 3 lugares:
1. Los web containers asignan un valor por default.
2. Se asigna un valor de el deployment descriptor (en minutos):
    <web-app>
      <session-config>
        <session-timeout>30</session-timeout>
      </session-config>
    </web-app>

3. Utilizando el método setMaxInterval(int segundos) de HttpSession. En este caso, el parametro va en segundos (para confundir un poco más)

** Un valor negativo en 2) o 3) determina que la sesión no vence nunca.
** Un valor de 0 en 2) determina que la sesión no vence nunca, pero en el método directamente la mata.

4.3 Using session listeners, write code to respond to an event when an object is added to a session, and write code to respond to an event when a session object migrates from one VM to another.

Las sesiones tienen 2 listeners que siguen el mismo pattern que para los scopes de request y context:

HttpSessionListener - sin embargo, el primero de los métodos no sigue el pattern para el nombre

- sessionCreated(HttpSessionEvent) - Este método se llama justo después de crear una sesión.

- sessionDestroyed(HttpSessionEvent) - Este método es llamado cuando se llama a HttpSession.invalidate(), pero antes que la sesión sea invalidada.

** Si el web container decide dealocar la aplicación, entonces estos listeners serán invocados antes que los listeners de aplicación.

HttpSessionAttributeListener

- Esta interface tiene los 3 métodos de los otros scopes, pero el evento que recibe es HttpSessionBindingEvent, que es un evento que sigue el patrón de HttpSessionBindingListener, que es otro listener que existe solamente en este scope.

Además de estos 2 listeners, el scope de sesión tiene 2 listeners más, que se diferencian de los anteriores porque no tienen que ser declarados en el deployment descriptor.

HttpSessionBindingListener -  Los objetos que implementan esta interface serán llamados por el web container cuando sean ligados o desligados de una sesión. Los métodos que tiene son los siguientes:

- valueBound(HttpSessionBindingEvent) - es llamado ANTES de asociar este valor a un atributo en una sesión.

- valueUnbound(HttpSessionBindingEvent) - es llamado DESPUES de remover el atributo de la sesion.

** Si también tengo asociado un HttpSessionAttributeListener, se llama primero a valueBound()

HttpSessionActivationListener - Esta interface sirve para objetos que serán asociados a sesiones distribuidas. Los métodos que tiene serán llamados antes de migrar a otra JVM y cuando son recuperados.

- sessionWillPassivate(HttpSessionEvent) - Este método es llamado justo antes de serializarse, para ser transportado a otra JVM

- sessionDidActivate(HttpSessionEvent) - Este método es llamado en la otra JVM justo después de la deserialización.

4.4 Given a scenario, describe which session management mechanism the Web container could employ, how cookies might be used to manage sessions, how URL rewriting might be used to manage sessions, and write servlet code to perform URL rewriting.

Los 2 métodos más comunes para mantener las sesiones son

1. A través de Cookies

2. A través de URL rewriting

Utilizar cookies es el método más usado, cuando el browser las acepta. El web container envia una cookie, con nombre JSESSIONID y un string que representa la sesión. En los subsecuentes requerimientos del cliente, esta cookie será enviado y permitira que del lado del servidor se identifique a esta conversación con la sesión.

A través de URL rewriting es más complicado para el programador, ya que todos los links deberán incluir un 'parametro' en la URL de la siguiente manera:

http://www.myserver.com/catalog/index.html;jsessionid=1234

Afortunadamente existen métodos que facilitan nuestra tarea:

HttpServletResponse.encodeURL(): Este método recibe una URL y devuelva la misma URL, pero con el parametro de sesión incluido. Este método no agrega el parametro de sesión si se estan utilizando cookies, por lo que sería buena práctica de programación incluir todos los links de esta manera.

HttpServletResponse.encodeRedirectURL(): Este método es usado en sendRedirect().