Java:序列化外部(最终)字段

Dav*_*veB 0 java serialization jboss infinispan

我有一个类PasswordEncryptor,使用org.jasypt.util.password.StrongPasswordEncryptor它的领域之一,因为我试图使应用程序"集群化"的所有类都需要被序列化的会话复制,但每当PasswordEncryptor被访问我遇到以下异常:

Caused by: java.io.NotSerializableException: org.jasypt.util.password.StrongPasswordEncryptor
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:891)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1063)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1019)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:885)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1063)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1019)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:885)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:680)
    at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:62)
    at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:119)
    at org.jboss.as.clustering.SimpleMarshalledValue.getBytes(SimpleMarshalledValue.java:74)
    at org.jboss.as.clustering.SimpleMarshalledValue.writeObject(SimpleMarshalledValue.java:172)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_34]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.6.0_34]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.6.0_34]
    at java.lang.reflect.Method.invoke(Method.java:622) [rt.jar:1.6.0_34]
    at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:175)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1007)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:885)
    at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:62)
    at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:119)
    at org.infinispan.marshall.MarshallUtil.marshallMap(MarshallUtil.java:60)
    at org.infinispan.marshall.exts.MapExternalizer.writeObject(MapExternalizer.java:63)
    at org.infinispan.marshall.exts.MapExternalizer.writeObject(MapExternalizer.java:47)
    at org.infinispan.marshall.jboss.ExternalizerTable$ExternalizerAdapter.writeObject(ExternalizerTable.java:406)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:145)
    at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:62)
    at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:119)
    at org.infinispan.atomic.AtomicHashMap$Externalizer.writeObject(AtomicHashMap.java:229)
    at org.infinispan.atomic.AtomicHashMap$Externalizer.writeObject(AtomicHashMap.java:226)
    at org.infinispan.marshall.jboss.ExternalizerTable$ExternalizerAdapter.writeObject(ExternalizerTable.java:406)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:145)
    at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:62)
    at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:119)
    at org.infinispan.marshall.jboss.AbstractJBossMarshaller.objectToObjectStream(AbstractJBossMarshaller.java:86)
    at org.infinispan.marshall.VersionAwareMarshaller.objectToObjectStream(VersionAwareMarshaller.java:151)
    at org.infinispan.marshall.AbstractDelegatingMarshaller.objectToObjectStream(AbstractDelegatingMarshaller.java:44)
    at org.infinispan.marshall.MarshalledValue.serialize0(MarshalledValue.java:119)
    ... 117 more
Caused by: an exception which occurred:
    in field spe
    in field bean
    in object java.util.HashMap@b629b463
    in object org.jboss.as.clustering.SimpleMarshalledValue@b629b463
    in object org.infinispan.util.FastCopyHashMap@43ad73a2
    in object org.infinispan.atomic.AtomicHashMap@4fd181fe
    in object org.infinispan.marshall.MarshalledValue@4fd181fe
    in object org.infinispan.commands.write.PutKeyValueCommand@ce32d716
    in object org.infinispan.commands.tx.PrepareCommand@293098b
Run Code Online (Sandbox Code Playgroud)

我已经尝试将该字段标记transient如下:

import java.io.Serializable;

import org.jasypt.util.password.StrongPasswordEncryptor;

public class PasswordEncryptor implements Serializable {

    private static final long serialVersionUID = 1L;

    //Need to mark transient as its not serializable
    private transient StrongPasswordEncryptor spe = new StrongPasswordEncryptor();

    public String encrypt(String password){
        return spe.encryptPassword(password);
    }

    public boolean isPasswordCorrect(String enteredPassword, String passwordHash){
        return spe.checkPassword(enteredPassword, passwordHash);
    }

}
Run Code Online (Sandbox Code Playgroud)

我不能使用包装器来继承StrongPasswordEncryptor,因为它是最终的

还有其他方法吗?(最好不引入任何其他库)

Gal*_*eño 5

从Infinispan的角度来看,控制类序列化的最佳方法,特别是当类是最终的或者无法修改类时,最好的方法是为要序列化的类提供自己的Infinispan Externalizer.Infinispan的用户指南包含有关如何使用用户定义的外部化器插入Infinispan的完整章节,说明其优点,包括减少有效负载,更快的序列化以及无法修改序列化类时的问题.除了文档中的示例之外,Infinispan源代码(ASL2)包含大量的Externalizer示例,可以满足您的需求.

更具体地说,Externalizer为PasswordEncryptor不需要写任何东西writeObject,并在readObject它刚刚需要实例PasswordEncryptor.