Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would setting an attribute in the session from a Java servlet sometimes fail?

I'm working on a fairly simple web app using JSPs and a Java servlet, running on tomcat. I've been able to set attributes in the session from the servlet in order to pass information to the JSPs which then gets presented to the user. I've done this with several different objects of different classes and it worked fine. Suddenly though when I set a particular kind of object (containing configuration information), the attribute isn't showing up in the JSP at all. The other attributes that I set are still there, but the configuration object is totally missing. I printed off the list of attribute names and the name I was using isn't even there (though the other names for the other attributes I set are present).

What could cause this? There's nothing different or weird about my configuration class. I'd really appreciate any ideas on what sorts of things might cause this behavior. I've googled and searched and can't find anything.

ETA: If it matters the name of the attribute is "configuration". I couldn't find anything on that being a reserved word or anything... I set this attribute in the servlet in the same function as a few others such as "user". I then redirect to a JSP which attempts to get both user and configuration. So everything's going on at the same time. user is fine while configuration doesn't even appear in the list of attribute names.

ETA2: Here's the exception that keeps occurring in the logs:

java.lang.Exception
    at pms.SessionListener.printStackTrace(Unknown Source)
    at pms.SessionListener.attributeAdded(Unknown Source)
    at org.apache.catalina.session.StandardSession.setAttribute(StandardSession.java:1498)
    at org.apache.catalina.session.StandardSession.setAttribute(StandardSession.java:1390)
    at org.apache.catalina.session.StandardSessionFacade.setAttribute(StandardSessionFacade.java:154)
    at PMS.getTaskInfo(Unknown Source)
    at PMS.doGet(Unknown Source)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:108)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:558)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:379)
    at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:282)
    at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:357)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1687)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
like image 596
Maltiriel Avatar asked Mar 31 '11 20:03

Maltiriel


People also ask

What is session attribute in servlet?

The Servlet Sessions attribute group provides information about servlet sessions. A session is a series of requests to a servlet, originating from the same user at the same browser. Applications running in a Web container use Sessions to monitor the actions of individual users.

What are session attributes in Java?

A session attribute is a pre-defined variable that is persistent throughout the life of a Tealeaf session. Session attributes can be used to store various data that may be referenced by events at any point during the session.


2 Answers

As per the comments on the question:

The session is absolutely there, and I can retrieve other attributes that were set in the servlet at the same time from the session in the JSP. It's just this one particular attribute that won't show up. I found lots of stuff on the session not being there, but not why one attribute won't work when others do.

Then something has removed or nulled-out the attribute.

session.removeAttribute("name");

or

session.setAttribute("name", null);

or even in JSP

<c:set var="name" value="${null}" scope="session" />

Or it can be yourself who has set null instead of the fullworthy object.

To naildown the one and other better, I'd let the attribute implement HttpSessionBindingListener and dump the stack on valueUnbound().

public class Foo implements HttpSessionBindingListener {

    @Override 
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("Value bound"); // Logger?
    }

    @Override 
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.err.println("Value unbound"); // Logger?
        Thread.dumpStack();
    }

    // ...
}
like image 138
BalusC Avatar answered Sep 30 '22 21:09

BalusC


There are many possibilities on what could be going wrong.

  • There could be two different sessions.
  • There could be some code removing your configuration object from the session.
  • Others?

Here is a way you can test to see what exactly is going on.

There are two separate listener interfaces that you can implement to listen for specific session events: javax.servlet.http.HttpSessionListener and javax.servlet.http.HttpSessionAttributeListener

I would implement these two interfaces with a class that will log what is happening during each event and which session the event is coming from.

You should be able to easily add your listeners to your web.xml file so that they will actually be set as listeners on your sessions by tomcat.

EDIT

Here is a class you can place into your web.xml as a listener to your sessions. Both BalusC and myself have recommended that you try this approach to debug the issue. Please just humor us and let us know if you see anything interesting in the way your "configuration" attribute is being set?

import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class SessionListener implements HttpSessionListener, HttpSessionAttributeListener, HttpSessionBindingListener, HttpSessionActivationListener {

public void valueBound(HttpSessionBindingEvent event) {
    System.out.println("valueBound: " + event.getName() + " : " + event.getValue());
    System.out.println("  session: " + event.getSession().getId());
    this.printStackTrace();
}

public void valueUnbound(HttpSessionBindingEvent event) {
    System.out.println("valueUnbound: " + event.getName() + " : " + event.getValue());
    System.out.println("  session: " + event.getSession().getId());
    this.printStackTrace();
}

public void attributeAdded(HttpSessionBindingEvent event) {
    System.out.println("attributeAdded: " + event.getName() + " : " + event.getValue());
    System.out.println("  session: " + event.getSession().getId());
    this.printStackTrace();
}

public void attributeRemoved(HttpSessionBindingEvent event) {
    System.out.println("attributeRemoved: " + event.getName() + " : " + event.getValue());
    System.out.println("  session: " + event.getSession().getId());
    this.printStackTrace();
}

public void attributeReplaced(HttpSessionBindingEvent event) {
    System.out.println("attributeReplaced: " + event.getName() + " : " + event.getValue());
    System.out.println("  session: " + event.getSession().getId());
    this.printStackTrace();
}

public void sessionCreated(HttpSessionEvent event) {
    System.out.println("sessionCreated: " + event.getSession().getId());
    this.printStackTrace();
}

public void sessionDestroyed(HttpSessionEvent event) {
    System.out.println("sessionDestroyed: " + event.getSession().getId());
    this.printStackTrace();
}

public void sessionDidActivate(HttpSessionEvent event) {
    System.out.println("sessionDidActivate: " + event.getSession().getId());
    this.printStackTrace();
}

@Override
public void sessionWillPassivate(HttpSessionEvent event) {
    System.out.println("sessionWillPassivate: " + event.getSession().getId());
    this.printStackTrace();
}

private void printStackTrace() {
    try {
        if (true) {
            throw new Exception();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}

Please add the above class to your code then add the following to your web.xml file between your filter mappings and your servlet mappings:

<listener>
    <listener-class><your.package.name>SessionListener</listener-class>
</listener>
like image 43
hooknc Avatar answered Sep 30 '22 20:09

hooknc