Bug 19701 - array of custom class cannot be serialized in session persistance
Summary: array of custom class cannot be serialized in session persistance
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 4
Classification: Unclassified
Component: Catalina (show other bugs)
Version: 4.1.24
Hardware: PC Solaris
: P3 major with 2 votes (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-05-06 16:40 UTC by Chris Cheshire
Modified: 2004-11-16 19:05 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Cheshire 2003-05-06 16:40:59 UTC
OS : Sun Solaris 2.8 (Intel)
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)
Tomcat 4.1.24 w/ Apache 2.0.45

When reloading a context with the manager app, serializing the session fails if
there is an array of a class I have created in the session object. Serialization
of a single instance of the class succeeds. There is one instance where the
serialization of the array succeeds, and that is if the class is in a package
that is read from $TOMCAT_BASE/common/lib.

This is not an ongoing option for me due to file system privileges. If I place
the package in either WEB-INF/lib (as a jar) or expanded into WEB-INF/classes I
get the exception listed below. 

Another observation, a String[] can be serialized successfully.

There is no problem with the class being found for compiling a jsp or servlet,
it is only the classloader used for session persistence that has a problem.

The exception produced (twice) is :

2003-05-05 10:48:12 StandardManager[] ClassNotFoundException while loading
persisted sessions: java.lang.ClassNotFoundExcept
ion: [Lextras.SearchResult;
java.lang.ClassNotFoundException: [Lextras.SearchResult;
        at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1443)
        at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1289)
        at
org.apache.catalina.util.CustomObjectInputStream.resolveClass(CustomObjectInputStream.java:119)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1513)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1435)
        at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1560)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1271)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
        at
org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1369)
        at
org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:864)
        at
org.apache.catalina.session.StandardManager.load(StandardManager.java:440)
        at
org.apache.catalina.session.StandardManager.start(StandardManager.java:655)
        at
org.apache.catalina.core.StandardContext.reload(StandardContext.java:2572)
        at
org.apache.catalina.servlets.ManagerServlet.reload(ManagerServlet.java:802)
        at
org.apache.catalina.servlets.HTMLManagerServlet.reload(HTMLManagerServlet.java:501)
        at
org.apache.catalina.servlets.HTMLManagerServlet.doGet(HTMLManagerServlet.java:151)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:740)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
        at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)
        at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)
        at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
        at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
        at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
        at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
        at
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:551)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
        at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
        at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
        at
org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2415)
        at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
        at
org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
        at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
        at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
        at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
        at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)
        at
org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
        at
org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
        at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
        at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:223)
        at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:261)
        at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:360)
        at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:604)
        at
org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:562)
        at org.apache.jk.common.SocketConnection.runIt(ChannelSocket.java:679)
        at
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:619)


The class that produced this error is shown below. Any of my classes fail to be
serialized when in arrays, but succeed when serialized as single objects.

SearchResult.java
******************
package extras;

import java.io.Serializable;
import com.bigredwire.util.Utility;

public class SearchResult implements Serializable, Cloneable {
    
    private String memberId;
    
    private String firstName;
    
    private String lastName;
    
    private String emailAddress;
    
    /** 
     * Creates a new instance of SearchResult 
     */
    public SearchResult() {
        memberId = "";
        firstName = "";
        lastName = "";
        emailAddress = "";
    }

    public String getMemberId() {
        return memberId;
    }
    
    public String getEmailAddress() {
        return emailAddress;
    }
    
    public String getFirstName() {
        return firstName;
    }
    
    public String getLastName() {
        return lastName;
    }
    
    public void setMemberId(String memberId) {
        this.memberId = Utility.ensureLength(memberId, 20, false);
    }
    
    public void setEmailAddress(String emailAddress) {
        this.emailAddress = Utility.ensureLength(emailAddress, 60, false);
    }
    
    public void setFirstName(String firstName) {
        this.firstName = Utility.ensureLength(firstName, 50, false);
    }
    
    public void setLastName(String lastName) {
        this.lastName = Utility.ensureLength(lastName, 50, false);
    }
    
    public Object clone() {
        try {
            return super.clone();
        }
        catch (CloneNotSupportedException ex) {
            throw new InternalError(ex.getMessage());
        }
    }
    
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("member id = " + memberId);
        sb.append(Utility.EOL);
        sb.append("first name = " + firstName);
        sb.append(Utility.EOL);
        sb.append("last name = " + lastName);
        sb.append(Utility.EOL);
        sb.append("email address = " + emailAddress);
        sb.append(Utility.EOL);
        return sb.toString();
    }
}
Comment 1 Remy Maucherat 2003-05-06 16:59:35 UTC
Well, [Lextras.SearchResult; is not the proper classname. Where is it specified
that CL must parse it because apparently one JDK component can submit garbage
instead of the proper classname ? I haven't seen that parsing code in the JDK
classloading code, but maybe I didn't look hard enough.
Comment 2 Chris Cheshire 2003-05-14 00:17:29 UTC
remy, were those comments directed to me, or the tomcat developers? i can't
actually answer them as i am just a user, and have no knowledge about the
internals of tomcat (my project schedule doesn't lend support to me
investigating either).

should i be waiting for this to get looked at, or just rewrite everything
affected to use vectors instead of arrays?
Comment 3 Chris Cheshire 2003-06-18 18:22:05 UTC
Hey guys, is this being looked into at all? Is more info needed? Or am I doing
something wrong and this really isn't a bug at all - in which case can someone
point me in the right direction please?

Thanks

Chris
Comment 4 Mark Thomas 2004-04-28 22:57:02 UTC
To clarify Remy's comment he believes that this is a JDK issue where 
java.io.ObjectInputStream passes an invalid classname to Tomcat. Hence this is 
not a tomcat bug.

Given that String[] works it is likely that there is something in your class - 
through no fault of yours - that is hitting some form of JDK bug.

Have you tried searching the sun JDK bug list? How about trying a later 
version of the JDK?
Comment 5 Jason Brittain 2004-06-04 21:21:26 UTC
This is actually a duplicate of bug 22146 that affects Tomcat 4.1.x.
It was fixed in Tomcat 5, but Remy couldn't reproduce it in 4.1 so
he didn't apply the same fix for 4.1.  I'm seeing this bug in 4.1.27,
and it looks like it should still affect the latest 4.1.

Can you apply this patch to 4.1?

http://cvs.apache.org/viewcvs.cgi/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/util/CustomObjectInputStream.java?r1=1.1&r2=1.2

I have verified in my working copy that it does fix the problem for
Tomcat 4.1.27.

Thanks.
Comment 6 Mark Thomas 2004-09-02 18:47:59 UTC
OK. I have ported the patch and it will be included in the upcoming 4.1.31 
release.