You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Felipe Jaekel <fk...@gmail.com> on 2015/10/08 23:29:13 UTC

HttpSessionListener.sessionDestroyed() sometimes not called?

Hi,

I have a customer support chat webapp where when the attendant session
expires, I need to end all his active conversations and change his status
to offline, so I implemented a HttpSessionListener.

Since some attendants log in the system multiple times, they where being
disconnect incorrectly if the second session ended before the first...

To solve this, I started to track the sessions. First I though about
something application scoped, but as I'm using parallel deployment, I
needed something that would be common to all the versions of the webapp, so
I chose the database(MySQL 5.6). I have a table with the following columns:
recordId, userId, sessionId, appVersion, sessionStart and sessionEnd.

When the attendant log in, a new record is created, leaving sessionEnd with
null. On HttpSessionListener.sessionDestroyed(), I set sessionEnd with the
current timestamp, then I query the database to see if there are additional
sessions active for him. If not, I end all his active conversations and
change his status to offline.

Now the problem is the opposite, some attendants are not disconnected
automatically. Looking at the session tracking table, I see some records
with sessionEnd == null, but the sessionId of the record is not listed on
the server's current active session list of any version of the webapp.

The first thing I do on my sessionDestroyed() method is to log the
sessionId that is destroyed. So in case my business logic failed, at least
this line I should see on the log before any possible exceptions. But there
is nothing there, what makes me think that the method was not called at all.

This webapp uses Apache Shiro 1.2.3. Server is restarted daily at dawn to
reset PermGen...

I thought it could be related to this issue(56657
<https://bz.apache.org/bugzilla/show_bug.cgi?id=56657>), since I was using
version 7.0.47. But I upgraded to 7.0.62 and it didn't solved, so I tried
to disable session persistence. Still no luck.


Any ideas?

Thanks in advance


*Session listener code:*

@WebListener
public class SessionListener implements HttpSessionListener
{
@PersistenceUnit(unitName = MySqlListener.PERSISTENCE_UNIT)
private EntityManagerFactory emf;

@Override
public void sessionCreated(final HttpSessionEvent sessionEvent)
{
Logger.getLogger(getClass().getName()).info("create " +
sessionEvent.getSession().getId());
}

@Override
public void sessionDestroyed(final HttpSessionEvent sessionEvent)
{
EntityManager em = null;
try
{
Logger.getLogger(getClass().getName()).info("destroy " +
sessionEvent.getSession().getId());

final HttpSession session = sessionEvent.getSession();

/**
* Nesse caso não há requisição nem FacesContext, portanto o EntityManager
será passado
* por referência para que a mesma instância seja usada em todas as operações
*/
em = emf.createEntityManager();

TbTecnicoService.destroySession(session.getId(), em);

final TBTecnico tecnico = (TBTecnico)
session.getAttribute(TbTecnicoService.TECNICO_LOGADO);

if(tecnico != null)
{
final Long totalSessoesAtivas = new
SessaoColaboradorService(em).countSessoesAtivasByColaborador(tecnico.getId());
if(totalSessoesAtivas < 1)
{
try
{
final Atendente atendente = new AtendenteService(em).findByTecnico(tecnico);

final AtendenteDisponivel atendenteDisponivel = new
AtendenteDisponivelService(em).findAtendenteOnline(atendente);

// Caso o atendente tenha clicado em "Sair" no portal considera como logout
manual
final boolean manualLogout =
Converter.toBoolean(session.getAttribute(Constants.MANUAL_LOGOUT));

new AtendimentoService(em).desconectarAtendente(atendente, manualLogout,
atendenteDisponivel.isPush());
}
catch(final NoResultException ex)
{
// Técnico não é um atendente ou o atendente não estava online
}

if(tecnico.getSetor().getId() == TbSetor.DESENVOLVIMENTO)
{
final ChamadoService chamadoService = new ChamadoService(em);
chamadoService.pause(tecnico);
}
}
}
}
catch(final Exception e)
{
GestaoErroClient.persist(IdAplicacao.COLABORADOR, JsfUtil.getVersion(),
getClass().getName(), e);
}
finally
{
EntityManagerHandler.close(em);
}
}
}