-
-
Save magro/6370466 to your computer and use it in GitHub Desktop.
package de.javakaffee.web.msm.serializer.kryo; | |
import java.nio.ByteBuffer; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.List; | |
import org.springframework.security.core.GrantedAuthority; | |
import org.springframework.security.core.userdetails.User; | |
import com.esotericsoftware.kryo.Kryo; | |
import com.esotericsoftware.kryo.serialize.IntSerializer; | |
import com.esotericsoftware.kryo.serialize.SimpleSerializer; | |
import com.esotericsoftware.kryo.serialize.StringSerializer; | |
/** | |
* Provides a custom kryo serializer for the Spring Security User class. | |
* <p> | |
* This is needed because the User class internally contains a collection | |
* of {@link GrantedAuthority}, which is actually a TreeSet with a | |
* Comparator. During deserialization kryo creates a TreeSet *without* | |
* any comparator and therefore expects that the contained items are | |
* Comparable, which is not the case for SimpleGrantedAuthority - ClassCastException. | |
* </p> | |
* <p> | |
* Motivated by <a href="http://code.google.com/p/memcached-session-manager/issues/detail?id=145"> | |
* issue #145: Deserialization fails on ConcurrentHashMap in Spring User object | |
* </a>. | |
* </p> | |
* @author Martin Grotzke | |
*/ | |
public class SpringSecurityUserRegistration implements KryoCustomization { | |
@Override | |
public void customize(final Kryo kryo) { | |
kryo.register( User.class, new SpringSecurityUserSerializer( kryo ) ); | |
} | |
static class SpringSecurityUserSerializer extends SimpleSerializer<User> { | |
private final Kryo _kryo; | |
public SpringSecurityUserSerializer(final Kryo kryo) { | |
_kryo = kryo; | |
} | |
@Override | |
public User read(final ByteBuffer buffer) { | |
final String password = StringSerializer.get(buffer); | |
final String username = StringSerializer.get(buffer); | |
final int size = IntSerializer.get(buffer, true); | |
final List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(size); | |
for (int i = 0; i < size; i++) { | |
authorities.add((GrantedAuthority)_kryo.readClassAndObject(buffer)); | |
} | |
final boolean accountNonExpired = buffer.get() == 1; | |
final boolean accountNonLocked = buffer.get() == 1; | |
final boolean credentialsNonExpired = buffer.get() == 1; | |
final boolean enabled = buffer.get() == 1; | |
return new User(username, password, enabled, accountNonExpired, credentialsNonExpired, | |
accountNonLocked, authorities); | |
} | |
@Override | |
public void write(final ByteBuffer buffer, final User user) { | |
StringSerializer.put(buffer, user.getPassword()); | |
StringSerializer.put(buffer, user.getUsername()); | |
final Collection<GrantedAuthority> authorities = user.getAuthorities(); | |
IntSerializer.put(buffer, authorities.size(), true); | |
for (final GrantedAuthority item : authorities) { | |
_kryo.writeClassAndObject(buffer, item); | |
} | |
put(buffer, user.isAccountNonExpired()); | |
put(buffer, user.isAccountNonLocked()); | |
put(buffer, user.isCredentialsNonExpired()); | |
put(buffer, user.isEnabled()); | |
} | |
private void put(final ByteBuffer buffer, final boolean value) { | |
buffer.put(value ? (byte)1 : (byte)0); | |
} | |
} | |
} |
it seems the serializer is never used.
Hi, Martin, i add config transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
customConverter="de.javakaffee.web.msm.serializer.kryo.SpringSecurityUserRegistration"
in tomcat config,and i get this error.
INFO: Could not store session 5E8DA4A26B75BE055E19E55CF6DC64E7-n1 in memcached.
java.util.concurrent.ExecutionException: com.esotericsoftware.kryo.SerializationException: Unable to serialize object of type: java.util.concurrent.ConcurrentHashMap
at de.javakaffee.web.msm.BackupSessionService$SynchronousExecutorService.submit(BackupSessionService.java:348)
at de.javakaffee.web.msm.BackupSessionService.backupSession(BackupSessionService.java:205)
at de.javakaffee.web.msm.MemcachedSessionService.backupSession(MemcachedSessionService.java:1040)
at de.javakaffee.web.msm.RequestTrackingHostValve.backupSession(RequestTrackingHostValve.java:230)
at de.javakaffee.web.msm.RequestTrackingHostValve.invoke(RequestTrackingHostValve.java:159)
at de.javakaffee.web.msm.RequestTrackingHostValve.invoke(RequestTrackingHostValve.java:124)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2442)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2431)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
Caused by: com.esotericsoftware.kryo.SerializationException: Unable to serialize object of type: java.util.concurrent.ConcurrentHashMap
at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:524)
at com.esotericsoftware.kryo.ObjectBuffer.writeObject(ObjectBuffer.java:251)
at de.javakaffee.web.msm.serializer.kryo.KryoTranscoder.serializeAttributes(KryoTranscoder.java:303)
at de.javakaffee.web.msm.TranscoderService.serializeAttributes(TranscoderService.java:155)
at de.javakaffee.web.msm.BackupSessionTask.serializeAttributes(BackupSessionTask.java:176)
at de.javakaffee.web.msm.BackupSessionTask.call(BackupSessionTask.java:110)
at de.javakaffee.web.msm.BackupSessionTask.call(BackupSessionTask.java:51)
at de.javakaffee.web.msm.BackupSessionService$SynchronousExecutorService.submit(BackupSessionService.java:346)
... 17 more
Caused by: com.esotericsoftware.kryo.SerializationException: Unable to serialize object of type: org.springframework.security.core.context.SecurityContextImpl
at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:493)
at com.esotericsoftware.kryo.serialize.MapSerializer.writeObjectData(MapSerializer.java:104)
at de.javakaffee.kryoserializers.CopyForIterateMapSerializer.writeObjectData(CopyForIterateMapSerializer.java:56)
at com.esotericsoftware.kryo.Serializer.writeObject(Serializer.java:43)
at com.esotericsoftware.kryo.Kryo.writeObject(Kryo.java:520)
... 24 more
Caused by: com.esotericsoftware.kryo.SerializationException: Serialization trace:
principal (org.springframework.security.authentication.UsernamePasswordAuthenticationToken)
authentication (org.springframework.security.core.context.SecurityContextImpl)
at com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSerializer.java:191)
at com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(ReferenceFieldSerializer.java:52)
at com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSerializer.java:175)
at com.esotericsoftware.kryo.serialize.ReferenceFieldSerializer.writeObjectData(ReferenceFieldSerializer.java:52)
at com.esotericsoftware.kryo.Kryo.writeClassAndObject(Kryo.java:489)
... 28 more
Caused by: java.lang.NullPointerException
at com.esotericsoftware.kryo.serialize.StringSerializer.put(StringSerializer.java:29)
at de.javakaffee.web.msm.serializer.kryo.SpringSecurityUserRegistration$SpringSecurityUserSerializer.write(SpringSecurityUserRegistration.java:68)
at de.javakaffee.web.msm.serializer.kryo.SpringSecurityUserRegistration$SpringSecurityUserSerializer.write(SpringSecurityUserRegistration.java:39)
at com.esotericsoftware.kryo.serialize.SimpleSerializer.writeObjectData(SimpleSerializer.java:17)
at com.esotericsoftware.kryo.serialize.FieldSerializer.writeObjectData(FieldSerializer.java:175)
... 32 more
Could you help me ? thx.
Hey Martin, I test the serializer and it does not work for me. I config customConverter="de.javakaffee.web.msm.serializer.kryo.SpringSecurityUserRegistration" but it seems the serializer is never used.