How do I figure out what object my session is trying to serialize?
Asked Answered
H

3

5

I recently upgraded to Spring Security 4.2.3.RELEASE. I'm also using spymemcached v 2.8.4. I'm running into this situation where for some reason Spring is trying to serialize service implementation classes. I can't figure out where this is coming from. The line of my code that the exception refers to is

Set<Session> userSessions = (Set<Session>) memcachedClient.get(userId);
...
memcachedClient.set(userId, sessionTimeoutInSeconds.intValue(), userSessions); // dies here

with the mysterious error (the "java.io.NotSerializableException: org.mainco.subco.ecom.service.ContractServiceImpl" is buried within) ...

09:06:47,771 ERROR [io.undertow.request] (default task-58) UT005023: Exception handling request to /myproject/registration/save: java.lang.IllegalArgumentException: Non-serializable object
    at net.spy.memcached.transcoders.BaseSerializingTranscoder.serialize(BaseSerializingTranscoder.java:110)
    at net.spy.memcached.transcoders.SerializingTranscoder.encode(SerializingTranscoder.java:162)
    at net.spy.memcached.MemcachedClient.asyncStore(MemcachedClient.java:282)
    at net.spy.memcached.MemcachedClient.set(MemcachedClient.java:733)
    at net.spy.memcached.MemcachedClient.set(MemcachedClient.java:126)
    at org.mainco.subco.session.service.MemcachedSessionService.associateUser(MemcachedSessionService.java:365)
    at org.mainco.subco.session.service.MemcachedSessionService.setSessionSecurityContext(MemcachedSessionService.java:288)
    at org.mainco.subco.core.security.SubcoSecurityContextRepository.saveContext(subcoSecurityContextRepository.java:116)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:114)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132)
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85)
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:72)
    at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:174)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:198)
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:784)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.io.NotSerializableException: org.mainco.subco.ecom.service.ContractServiceImpl
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)

How do I figure out the object memcache is trying to serialize and thus figure out how it is referencing a service class to serialize?

The point of this question is not how do I make my service class serializable but why is my session trying to serialize it in the first place.

Hogue answered 17/6, 2017 at 14:9 Comment(0)
T
3

I'm running into this situation where for some reason Spring is trying to serialize service implementation classes.

spring don't try to serialize implementation .

looks lite when you do

memcachedClient.set(userId, sessionTimeoutInSeconds.intValue(), userSessions);

it's expect for Serializable object ,but userSessions is not.

Set is not serializable , and type that you get

(Set) memcachedClient.get(userId);

is not serialized to. check if you can cast memcachedClient.get(userId) to something that is Serializable like HashSets or TreeSet ....

the worst it's you can try BUT you might get CastException

memcachedClient.set(userId, sessionTimeoutInSeconds.intValue(), (Serializable)userSessions);


you can iterate set and do simple check :

int count=0;
for(Session session: userSessions ){
    log....
    boolean isSerializable = checkIfSerializable(session);
    count=isSerializable ? count+1 : count;
    log 
}

private static boolean checkIfSerializable(Object value) throws IllegalAccessException {
    try {
        ByteArrayOutputStream bf = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bf);
        oos.writeObject(value);
        oos.close();
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bf.toByteArray()));
        Object o = ois.readObject();
        return true;

    } catch (Exception e) {
        System.out.println("----->>>> Not exactly Serializable : " + value);
    }
        return false;
}
Troglodyte answered 17/6, 2017 at 16:22 Comment(12)
When the Set is created, it is created using "userSessions = new HashSet<Session>();" so I'm already doing what you are suggesting and yet the error remains.Hogue
from your source Set<Session> userSessions = (Set<Session>) memcachedClient.get(userId); check in debug for userSessions type of SetTroglodyte
I have verified it is of type java.util.HashSet.Hogue
what about Session ? is it Serializable ? something in userSessions is not Serializable , if set is , then session is'tTroglodyte
My question is how do I figure that out. There is probably something in session that's not, but what's the easiest way to know?Hogue
Chech that all in session is serialable. You can check all objects manually or in debug mode. Also you can get object session and do cast to serializable inteface . Did you try to cast?Troglodyte
It's hard to say what is exactly wrong without debug or vision about types of object in sessionTroglodyte
By checking stuff manually, I assume you mean looking through my code. I already did taht before posting the question and I'm stuck so hopefully this bounty will bring out some programmatic ways that I ahven't throught of.Hogue
Programatticaly- try wiith reflectionTroglodyte
private static void checkIfSerializable(Object value) throws IllegalAccessException { try { ByteArrayOutputStream bf = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bf); oos.writeObject(value); oos.close(); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bf.toByteArray())); Object o = ois.readObject(); System.out.println(o.toString()); } catch (Exception e) { System.out.println("Not exactly Serializable"); } }Troglodyte
try this test for userSessions . add method and call before memcachedClient.set checkIfSerializable(userSessions);Troglodyte
and show out put for this : Class<?>[] inClasses = userSessions .getClass().getInterfaces(); for(Class c : inClasses){ System.out.println(c); }Troglodyte
C
4

Why don't you try to enumerate the sessions and the attributes and java-serialize them to a dummy output stream until one fails ? when it fails you print attribute name and value class.

I suppose session is org.apache.catalina.Session. In your code add:

for(Session x : userSessions) checkSerializable(x.getSession());

with checkSerializable:

 private static void checkSerializable(HttpSession s) {
        Enumeration e = s.getAttributeNames();
        while (e.hasMoreElements()) {
            String name = (String) e.nextElement();
            Object value = s.getAttribute(name);
            try
            {
                ObjectOutputStream out=new ObjectOutputStream(new ByteArrayOutputStream());
                out.writeObject(value);
            }
            catch(NotSerializableException ex)
            {
                ex.printStackTrace();
                System.out.println(name + " is not serializable, class is: " + value.getClass().getName());
            }
            catch(IOException e2)
            {
                throw new RuntimeException("Unexpected", e2);
            }

        }

    }
Collodion answered 26/6, 2017 at 10:9 Comment(2)
The Session object I reference isn't actually an HttpSession objecct, but rather one I create . As such I don't have a "getAttributeNames" method per se. Is there any way at run-time to print out the object tree of my session, its fields, and then their fields, and so on?Hogue
You could try some dump utility #302036 if that can enumerate values I would also try to serialize themCollodion
T
3

I'm running into this situation where for some reason Spring is trying to serialize service implementation classes.

spring don't try to serialize implementation .

looks lite when you do

memcachedClient.set(userId, sessionTimeoutInSeconds.intValue(), userSessions);

it's expect for Serializable object ,but userSessions is not.

Set is not serializable , and type that you get

(Set) memcachedClient.get(userId);

is not serialized to. check if you can cast memcachedClient.get(userId) to something that is Serializable like HashSets or TreeSet ....

the worst it's you can try BUT you might get CastException

memcachedClient.set(userId, sessionTimeoutInSeconds.intValue(), (Serializable)userSessions);


you can iterate set and do simple check :

int count=0;
for(Session session: userSessions ){
    log....
    boolean isSerializable = checkIfSerializable(session);
    count=isSerializable ? count+1 : count;
    log 
}

private static boolean checkIfSerializable(Object value) throws IllegalAccessException {
    try {
        ByteArrayOutputStream bf = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bf);
        oos.writeObject(value);
        oos.close();
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bf.toByteArray()));
        Object o = ois.readObject();
        return true;

    } catch (Exception e) {
        System.out.println("----->>>> Not exactly Serializable : " + value);
    }
        return false;
}
Troglodyte answered 17/6, 2017 at 16:22 Comment(12)
When the Set is created, it is created using "userSessions = new HashSet<Session>();" so I'm already doing what you are suggesting and yet the error remains.Hogue
from your source Set<Session> userSessions = (Set<Session>) memcachedClient.get(userId); check in debug for userSessions type of SetTroglodyte
I have verified it is of type java.util.HashSet.Hogue
what about Session ? is it Serializable ? something in userSessions is not Serializable , if set is , then session is'tTroglodyte
My question is how do I figure that out. There is probably something in session that's not, but what's the easiest way to know?Hogue
Chech that all in session is serialable. You can check all objects manually or in debug mode. Also you can get object session and do cast to serializable inteface . Did you try to cast?Troglodyte
It's hard to say what is exactly wrong without debug or vision about types of object in sessionTroglodyte
By checking stuff manually, I assume you mean looking through my code. I already did taht before posting the question and I'm stuck so hopefully this bounty will bring out some programmatic ways that I ahven't throught of.Hogue
Programatticaly- try wiith reflectionTroglodyte
private static void checkIfSerializable(Object value) throws IllegalAccessException { try { ByteArrayOutputStream bf = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bf); oos.writeObject(value); oos.close(); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bf.toByteArray())); Object o = ois.readObject(); System.out.println(o.toString()); } catch (Exception e) { System.out.println("Not exactly Serializable"); } }Troglodyte
try this test for userSessions . add method and call before memcachedClient.set checkIfSerializable(userSessions);Troglodyte
and show out put for this : Class<?>[] inClasses = userSessions .getClass().getInterfaces(); for(Class c : inClasses){ System.out.println(c); }Troglodyte
B
3

So what about org.mainco.subco.ecom.service.ContractServiceImpl? Is this a spring bean?

I guess it has scope="session" and so it's bound to your session as one of it's attributes. And if you want to serialize your session - all of it's attributes has to be serializable.

Brave answered 21/6, 2017 at 6:53 Comment(3)
I'm not understanding how this answer helps me figure out why is my session trying to serialize it in the first place.Hogue
When your session is being serialized, obviously all of it's attributes has to be serialized too. Apparently your service is one of the session attributesBrave
I don't wnat it to be. How do I programmatically view the contents of hte session?Hogue

© 2022 - 2024 — McMap. All rights reserved.