views:

903

answers:

4

We just switched to Glassfish V2. We are now getting errors when setting a session attribute.

Error is:

java.lang.IllegalArgumentException: PWC2788: setAttribute: Non-serializable attribute

Code is:

getRequest().getSession().setAttribute("questionsForUser", getQuestions());

getQuestions() is just a simple getter which is inside an abstract class named 'Parent Action'....so to make getQuestions() a serialized object does my class need to implement serializable?:

public List getQuestions() {
    return questions;
}
  • How can we make this object serializable?
  • is it a good practice to only put serialized object in the session (as Glassfish appears to be requiring)?
  • Are there risks of sessions being swapped between users with serialized objects?

Edit: I am using ORM (iBatis)

More Information about "Questions"

setter:

public void setQuestions(List questions) {
    this.questions = questions;
}

setter is called inside this method. this method calls the iBatis mappings.

public void prepareQuestions()
{        
setExamIfaceDAO((SecurityExamIfaceDAO)ApplicationInitializer.getApplicationContext().getBean("securityExamIfaceDAO"));
    String userRole = questionsBasedOnUserRole();
    int questionsToBeShown = 0;
    if (userRole.equalsIgnoreCase("C"))
        questionsToBeShown = 15;
    else if (userRole.equalsIgnoreCase("U"))
        questionsToBeShown = 10;
    List local_questions = getExamIfaceDAO().getSecurityQuestions(userRole);
    Collections.shuffle(local_questions);
    if (local_questions.size()>=questionsToBeShown)
        setQuestions(local_questions.subList(0, questionsToBeShown));
    getRequest().getSession().setAttribute("questionsForUser", getQuestions());
}
A: 

It is requiring them to be serializable because the servlet spec says that they have to be if the "distributable" tag is in web.xml. The spec assumes servlet engines will replicate sessions across services using serialization.

The only way to make it be serializable is to... use an implementation of List that is serializable! You must have written your own custom List class, since all the implementations in the JDK are serializable that I know of. Either that or the objects in the list are not serializable.

Or you could just remove the "distributable" if you don't care if your sessions get replicated across multiple servers or not.

Licky Lindsay
lol...def did not write my own custom List class...
Omnipresent
Maybe the objects in your list are not serializable then..
Licky Lindsay
Where does "questions" come from? Are you using an ORM? Many ORMs (like Hibernate) introduce their own Collection implementations. You probably need to unwrap your questions and wrap them into a normal ArrayList. Please also post the class definition of the Question class.
mhaller
@mhaller yes, I am using iBatim ORM. Please see my edit
Omnipresent
+2  A: 

You can make the object serializable by using a serializable List implementation and making sure that the objects in the list are also serializable.

Yes -- it is good practice to only put serializable objects in the session since this will allow your application to be run on a server with multiple nodes. Even if you don't care about this at the moment it might be useful in future.

The servlet container should ensure that sessions are not swapped between users. Making objects stored in the session serializable allows the container to 'distribute' the session state across multiple nodes in a cluster, allowing the user who owns the session to have requests serviced by any node.

Andy
A: 

What type of objects does the List contain? I.e. what's the generic type of the List? Is it List<String> or List<Question> wherein Question is a homegrown javabean class? If the latter is the case, you need to let it implement java.io.Serializable. That's basically all. You're also required by the javabean specification to do so.

BalusC
A: 

All the JDK collections are serializable if their elements are serializable. My guess is its the List elements that are not serializable, not the List object itself. To (over-)simplify, for an object to be serializable it must:

  • Implement Serializable
  • Only have non-static non-transient fields that are also serializable
Ramon