Usando Java Session en aplicaciones web

Uno de los conceptos que más problemas produce cuando comenzamos a trabajar con aplicaciones web en Java es el concepto de java session (HttpSession) que sirve para almacenar información entre diferentes peticiones HTTP  ya que este protocolo es stateless (sin estado). Así pues en muchas ocasiones nos encontraremos con el problema de compartir estado (datos usuario) entre un conjunto amplio de páginas de nuestra Aplicación.

datosusuario

Java Session

Para solventar este problema en la plataforma Java EE se usa de forma muy habitual la clase HttpSession que tiene una estructura de HashMap (Dicccionario) y  permite almacenar cualquier tipo de objeto en ella de tal forma que pueda ser compartido por las diferentes páginas que como usuarios utilizamos.

hashmap

Funcionamiento

El funcionamiento del sistema de sessiones es relativamente sencillo. Cada vez que un usuario crea una session accediendo a una página (que la genere) se crea un objeto a nivel de Servidor con un HashMap vacío que nos permite almacenar la información que necesitamos relativa a este usuario. Realizado este primer paso se envía al navegador del usuario una Cookie que sirve para identificarle y asociarle el HashMap que se acaba de construir para que pueda almacenar información en él. Este HashMap puede ser accedido desde cualquier otra página permitiéndonos compartir información.

creacionSession

Usuarios y Sessiones

El concepto de Session es individual de cada usuario que se conecta a nuestra aplicación y la información no es compartida entre ellos. Así pues cada usuario dispondrá de su propio HashMap en donde almacenar la información que resulte útil entre páginas.

 

sessionesusuarios

Un ejemplo sencillo

Vamos a ver un ejemplo utilizando dos Servlets básicos en el cual un servlet almacena datos en la sessión (concretamente un objeto producto) y otro servlet lee los datos de la session y los muestra por pantalla.


package com.arquitecturajava;

public class Producto {

private int id;
private String concepto;
private double importe;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getConcepto() {
return concepto;
}
public void setConcepto(String concepto) {
this.concepto = concepto;
}
public double getImporte() {
return importe;
}
public void setImporte(double importe) {
this.importe = importe;
}
public Producto(int id, String concepto, double importe) {
super();
this.id = id;
this.concepto = concepto;
this.importe = importe;
}
public Producto() {
super();
}

}


package com.arquitecturajava;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet("/CrearSession")
public class CrearSession extends HttpServlet {
private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

HttpSession misession= request.getSession(true);
Producto miproducto= new Producto(1,"telefono",300);
misession.setAttribute("producto",miproducto);
PrintWriter pw= response.getWriter();
pw.println("<html><body>Producto en session</body></html>");
pw.close();

}
}


package com.arquitecturajava;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet("/VerSession")
public class VerSession extends HttpServlet {
private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession misession= (HttpSession) request.getSession();

Producto miproducto= (Producto) misession.getAttribute("producto");

PrintWriter pw= response.getWriter();
pw.println("<html><body>"+ miproducto.getId()+ "," +miproducto.getConcepto()+","+ miproducto.getImporte());
pw.close();
}
}

En este caso el primer Servlet (CreaSession) se encarga de crear la session y almacenar un producto en ella. Mientras el segundo Servlet se encargará de acceder a los datos y mostrarlos por pantalla.
creaVee

 

Una vez  invocado el Servlet que crea la session invocamos a VerSession y nos mostrará por pantalla los datos que se han introducido.

datosSession

 

Hemos compartido información perteneciente al mismo usuario entre dos Servlets. Recordemos que no se debe abusar del almacenamiento de objetos en Session ya que al ser por cada usuario si tenemos muchos usuarios concurrentes estaremos obligando al servidor a utilizar mucha memoria para almacenarlos.

Otros artículos relacionados : ServletContext, Java Filter , ServletContextListener

It's only fair to share...Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn

About Cecilio Álvarez Caules

Cecilio Álvarez Caules Sun Certified Enterprise Architech (J2EE/JEE).

50 Responses to Usando Java Session en aplicaciones web

  1. Alfonso 27 Julio, 2017 at 3:42 #

    Buenas tardes Cecilio:

    Me podría orientar sobre como mantener sesiónes activas tal y como se hacen con un explorador web y un servidor apache, pero yo lo quiero hacer desde una aplicación de escritorio java swing a un servidor apache. Desde su experiencia, necesito me facilite alguna clase que pueda utilizar o una libreria para mantener la sesión activa durante un cierto tiempo o mientras este abierta la aplicación de escritorio. De antemano muchas gracias

    • Cecilio Álvarez Caules 27 Julio, 2017 at 6:21 #

      Esto normalmente se aborda con Statefull Session Beans , Se necesita un servidor full stack como JBoss , WebLogic , WebSphere para llevarlo a cabo.

  2. D0101D 22 Julio, 2017 at 4:41 #

    hola me puedesayudar

    • Cecilio Álvarez Caules 22 Julio, 2017 at 7:53 #

      cual es la pregunta? 🙂

  3. Alberto 18 Julio, 2017 at 18:18 #

    Hola Que tal? Disculpa yo tengo que hacer algo semejante y la aplicación web esta realizada con spring y jsf, me podrias orientar como hacerlo?

    • Cecilio Álvarez Caules 18 Julio, 2017 at 21:47 #

      Bajate mi libro del blog y te ayudará viene como hacerlo paso a paso 🙂

    • nando 18 Agosto, 2017 at 8:16 #

      amigo jsf ya paso a la historia te sugiero que utilices sprint con Mybatis

      • Cecilio Álvarez Caules 18 Agosto, 2017 at 15:19 #

        Cuando una tecnología es un standard , sigue teniendo su hueco, primefaces es un ejemplo 😉

  4. Madrid 12 Julio, 2017 at 23:37 #

    He visto un montón de preguntas en varios foros sobre un caso que ocurre diariamente en programación J2EE y nadie responde creo que aquí en este mundo todos nos copiamos de todos y nadie experimente por si mismo y lo que nadie inventa nadie lo sabe….

    Mi pregunta es muy sencilla…
    Haces login en una JSP, se hace el submit hacia un sevlelt ,
    este servlet crea una session … HttpSession sesion = request.getSession();
    el sevlet hace un response.sendRedirect(“loginExito.jsp”)

    antes del response he creado un…. sesion.setAttribute(“usuario”, usu);

    una vez que estoy en loginExito.jsp…pinto…. hola usu “ESTAS VALIDADO”
    bien… hasta aqui todo bien

    en la JSP login Exito.jsp tengo un botón , hago clic que hace un submit de un formulario dirigido a un servlet llamado popup el target del formulario es blank (ventana)
    bien en esta ventana no recupero …. sesion.getAttribute(“usuario”);
    Porque?……
    Porque en las popup no se recuperan las variables de sesión….?
    Nadie responde , nadie pone un ejemplo válida (que venga de un servlet) y se carga en un popup…
    Gracias.

    • Cecilio Álvarez Caules 13 Julio, 2017 at 16:51 #

      Pues no he tenido tiempo de probarlo , pero parece que puede ser algún tema muy particular de como el navegador abre una nueva pestaña. Has probado a utilizar url rewriting y adjuntar a la pestaña que se abre el jsessionid?

  5. Max Jara 27 Junio, 2017 at 18:41 #

    Buenos días estimado Cecilio tengo una duda… con respecto al 2do servlet tienes la línea: HttpSession misession= (HttpSession) request.getSession(); para llamar a la sesión presente… pero si esta no existe… prácticamente se crearía una nueva sesión verdad…

    Entonces el hecho de usar apps web en línea no se trata netamente de trabajar con una única sesión para todo el trayecto del aplicativo??? de esta manera… dicha línea no sería: HttpSession misession= (HttpSession) request.getSession(false); cosa que si por algún motivo… me distraigo y pasan los 30min reglamentarios de sesión cuando regrese esto me daría error haciendo que no se vea dicha sesión???

    Tengo eso duda… por favor ruego me ayude

    • Cecilio Álvarez Caules 27 Junio, 2017 at 22:03 #

      Si , eso esta claro , si ya no tienes sessión tienes que hacer algo para solventarlo. una opción es esta filtro invalidar session . Eres tu el que me ha preguntado por twitter verdad? 🙂

  6. carlos 2 Junio, 2017 at 21:32 #

    Hola,muy buena la explicación. Ahora bien, es necesario trabajar con sesiones en una aplicacón web? o se puede obviar?. Tengo una aplicación que tendrían que acceder alrededor de 13 personas para ingresar, modificar o eliminar datos a una base de datos mysql y lo estoy haciendo con jsp, servlet y accesos a bbdd. Muchas gracias

    • Cecilio Álvarez Caules 2 Junio, 2017 at 22:33 #

      Sino necesitas que entre diversas vistas se comparta estado , entonces no las necesitas

  7. Ervin Rivas 6 Abril, 2017 at 19:17 #

    En este momento estoy teniendo un Problema en el cual usuario con sesiones unicas al loguearse son redirigidos hacia sesiones que no son las suyas, el servidor de aplicaciones es GlassFish y el desarrollo esta en JSF, podrian indiacrme que pasos seguir para solucionar este inconveniente…

    Gracias.

    • Cecilio Álvarez Caules 6 Abril, 2017 at 21:02 #

      Pues eso suena bastante raro , da la sensación de que alguien no ha implementado bien las sessiones y el estado a nivel de programacion ,crea un objeto en session sencillo en una página y compruebalo

  8. Alberto 4 Enero, 2017 at 16:44 #

    Hola Cecilio

    Me gustaria saber como se manejar el paso de sesión entre aplicaciones web, para que una aplicacion A con usuario autenticado pueda invocar un servlet en la aplicacion B en la cual no tiene una sesion.

  9. Pedro 4 Enero, 2017 at 12:37 #

    Buenas y feliz año.

    Trabajo en el mundo del testing y no son pocas las veces que me he encontrado problemas de desbordamiento de la memoria Java a causa del uso indiscriminado de la sesión de usuario (en pruebas de carga), por lo que +1 a no abusar del almacenamiento en sesión.

    Mi comentario va más relacionado con la monitorización de recursos. ¿Conoces alguna herramienta que calcule el tamaño de la sesión de usuario?. Suelo utilizar JavaMelody para estos casos, pero por si conocieras otra.

    Gracias, saludos.

    • Cecilio Álvarez Caules 4 Enero, 2017 at 13:52 #

      Pues no conozco , no estoy tan metido en el mundo de las pruebas de carga 🙂 , pero muchas gracias por el aporte de Java Melody lo echaré un veo. Feliz Año 😉

  10. Misael 16 Diciembre, 2016 at 18:46 #

    Hola y gracias por el ejemplo. He utilizado picket link para manejar los inicios de sesión, ¿consideras este framework robusto?, ¿cual es tu opinión al respecto de esta librería ?.

    Saludos

    • Cecilio Álvarez Caules 17 Diciembre, 2016 at 7:42 #

      No la conozco 🙂 , pero la voy a echar un veo gracias por el aporte 😉

    • Cecilio Álvarez Caules 17 Diciembre, 2016 at 7:43 #

      Veo que esta creada por redhat … seguro que es una buena opcion 🙂

  11. Lucas 16 Diciembre, 2016 at 14:35 #

    Hola amigo, en base a este ejemplo, yo necesito manejar simplemente una variable. La cosa es asi, tengo un jsp que envía los datos al servlet y este se encarga de realizar el Insert, a su ves este servlet debe redirigir a otra pagina(estadisticas.jsp) y mostrar un mensaje de exito(que los datos se cargaron correctamente) y si la carga no se realizo correctamente debe mandar a otra pagina(index.jsp) y mostrar también un mensaje.
    Mi idea era manejar una variable session(que seria un booleano) en el servlet y dependiedo si cargaron bien los datos se ponga en true y sino que se ponga en false, entonces en cada pagina (estadisticas.jsp e index.jsp) tomaria esa variable y según su valor mandaría el mensaje correspondiente, este mensaje lo podria tratar con JavaScript.

    Muchas gracias, soy nuevo en esto y no he encontrado la forma de resolverlo

    • Cecilio Álvarez Caules 17 Diciembre, 2016 at 7:54 #

      Podrías hacerlo con sessiones pero no es obligatorio que ya se lo podrías pasar a los despachadores vía setAttribute en la request. Las sessiones se usan más cuando muchas páginas comparten la información

  12. gerardo 29 Octubre, 2016 at 1:48 #

    Buena tarde tengo una duda que me recomiendas utilizar para una aplicación desarrollada con java ee que utiliza cliente/servidor, en el servidor cree un webservice pero no tengo bien claro si usar Stateless o Stateful, el cliente estará en swing.

    • Cecilio Álvarez Caules 2 Noviembre, 2016 at 9:00 #

      Los webservices normalmente no almacenan estado y son stateless

  13. Ray 6 Octubre, 2016 at 16:31 #

    Cecilio, gracias por tus aportes, aunque con una duda respecto a los ejemplos que expones con la constante:

    private static final long serialVersionUID = 1L;

    Me he percatado que asignas el mismo serialVersionUID para estas clases, tanto para esta entrada en tu blog como en otros ejemplos de otras entradas (soy fiel seguidor). Me da la impresión que al tratarse de un UID tendría que ser univoco, y del no ser así, ¿que sentido tiene informar un mismo valor por defecto?

    Y nuevamente gracias por tu dedicación.

    • Cecilio Álvarez Caules 21 Octubre, 2016 at 16:00 #

      Mientras todas tengan el mismo número no genera problema , este campo se usa cuando hablamos de programación distribuida y una clase está ubicada en dos máquinas diferentes

  14. Daniel Ramirez 17 Septiembre, 2016 at 19:19 #

    Cecilio, aprovechando tu disposición, como haces para modificar el tiempo por defecto de las sesiones del web.xml, si al momento de crear un servlet prefieres trabajar con anotaciones.?
    gracias

    • Cecilio Álvarez Caules 18 Septiembre, 2016 at 10:34 #

      el web.xml sigue siendo necesario para algunas tareas , el tiempo de timeout se configura en él 🙂

  15. Ulises 9 Junio, 2016 at 19:40 #

    Que tal muchas gracias por compartir tu conocimiento.
    Yo tengo una aplicacion web y las sesiones entre usuarios no se mezclan, pero cuando un usuario edita un registro, y luego abre otra pestaña y edita otro registro este ultimo sobre escribe el primer registro, este ejemplo cubre este escenaro?

    • Cecilio Álvarez Caules 9 Junio, 2016 at 20:25 #

      Es normal las dos pestañas comparten la misma sessión

  16. Raquel 19 Mayo, 2016 at 20:52 #

    Hola Cecilio,
    Ante todo, gracias por compartir.

    ¿Desde tu conocimiento, consideras el servidor OC4J como de Producción?. En este servidor se me ha dado el caso de mezcla de sesiones entre usuarios. La particularidad es que la aplicación en sí esta integrada por varios módulos web (.war), y es desde cualquiera de estos módulos que se puede hacer el login (momento de creación de la sesión)…
    ¿Puede ser esta la causa? Me refiero a que quizás cada módulo web controla la unicidad en los identificadores de sesión, ¿pero casualmente un identificador de sesión podría verse repetido en otro módulo?.

    El foro ya lleva tiempo abierto; pero por si lo lees muchas gracias de antemano,

    • Cecilio Álvarez Caules 20 Mayo, 2016 at 6:51 #

      En principio no debiera dar problemas ya que todos los servidores pasan un proceso de certificacion, pero oC4j ya es bastante antiguo.

  17. VictorC 3 Abril, 2015 at 4:56 #

    Estoy haciendo una pagina web donde ocupo iniciar session, en index tengo el formulario para el login, en otro jsp tengo la pagina que seria mostrado despues de pasar por login, pero si ingreso la url directa de dicha pagina sin pasar por login, puedo ingresar, como se puede controlar esto??

  18. Nelson 21 Noviembre, 2014 at 23:17 #

    “…este protocolo es stateless (sin estado).” Precisamente lo del estado no lo he entendido muy bien. Qué implica tener o no tener estado?

    • Cecilio Álvarez Caules 23 Noviembre, 2014 at 16:43 #

      El estado implica que una variable mantiene su valor entre varias páginas .Estos datos se almacenan en session normalmente.

      • nelson 24 Noviembre, 2014 at 6:00 #

        Entonces los managedBeans son EJB @Statefull? (por ejemplo)

        • Cecilio Álvarez Caules 24 Noviembre, 2014 at 7:36 #

          No pero si tienen scope de sesión mantienen estado

  19. Edwin Ilovares 28 Octubre, 2014 at 18:01 #

    Cecilio gracias por compartir.

    Con respeto a la Session yo tengo una mala experiencia, tengo una sistema que sirve para los usuarios vean sus estados de cuenta bancarias. Y una vez me paso que se “mezclaron las sessiones” y un usuario pudo ver las cuentas del otro. Me causo muchos problemas como haz de imaginar.
    Es algo no encontré explicación, tanto que leí en algun foto de Glassfish, que era un issue que tenia el mismo GF.
    Esto me hizo meter un control extra para validar la Session y cuando pasará eso de nuevo detectarlo y sacar al usuario para vuelva hacer LogIn.

    Al día de hoy aun no se porque razón se da, lo llamo “El caso Maalouf”.

    • Cecilio Álvarez Caules 29 Octubre, 2014 at 18:07 #

      GlassFish siempre ha sido un servidor para probar las especificaciones no tanto un servidor puro de producción tipo Tomcat/WebLogic/JBoss/Websphere 🙁 . Probablemente ese era tu mayor problema

    • Rafael Contreras 30 Diciembre, 2015 at 14:49 #

      Hola, yo tuve un problema similar pero en php cree un sistema de login sencillo para hacer una encuesta, basicamente un formulario con algunas preguntas… Cuando ingresaban más de 15 usuarios las sesiones se cruzaban y aparecían datos de otro usuario, nunca supe porque, no hay info al respecto, ahora voy a hacer la misma app usando JEE y me dices que tiene el mismo problema me preocupa, si tienes más info al respecto me podrías ayudar, te dejo mi correo zirtrex@live.com

      • Cecilio Álvarez Caules 31 Diciembre, 2015 at 13:24 #

        No debieras tener ningún problema con las sessiones ya que asignan una cookie al navegador que te identifica de forma única

  20. Juan 15 Octubre, 2014 at 17:23 #

    Grandisimo ejemplo! Gracias por compartir…

    Pero a raiz de el comentario de arriba y como tu tambien dices, si no se puede abusar del uso de la sesión, ¿que alternativas tenemos? ¿Como podemos hacer esto de otra manera?

    gracias! un saludo

    • Cecilio Álvarez Caules 16 Octubre, 2014 at 7:53 #

      Cada framework web tiene las suyas. Por ejemplo JSF tiene pageFlows y conversaciones y Spring MVC webflows

  21. Carles 15 Octubre, 2014 at 15:13 #

    ¡Buen ejemplo! Aunque es una práctica peligrosa, lástima que pocos cumplan esto: “no se debe abusar del almacenamiento de objetos en Session”.

    • Cecilio Álvarez Caules 16 Octubre, 2014 at 7:52 #

      gracias 🙂

Trackbacks/Pingbacks

  1. Java HttpSession Timeout - Arquitectura Java - 2 Diciembre, 2014

    […] artículos relacionados : El concepto de HttpSession , Manejando […]

Deja un comentario