我有一个 bean,它包含对 JSF 组件(确切地说是primefaces 组件)的引用。
根据规范,JSF 组件不可序列化。我的 Web 应用程序在 JBoss 集群中运行,并且需要分发 bean,这意味着它们需要可序列化。因此,
因此,每当我使用其支持 bean 是具有 JSF 组件引用的页面时,我都会遇到此异常:
Caused by: java.lang.RuntimeException: Failure to marshal argument(s)
at org.infinispan.remoting.transport.jgroups.CommandAwareRpcDispatcher.marshallCall(CommandAwareRpcDispatcher.java:257)
at org.infinispan.remoting.transport.jgroups.CommandAwareRpcDispatcher.processSingleCall(CommandAwareRpcDispatcher.java:274)
at org.infinispan.remoting.transport.jgroups.CommandAwareRpcDispatcher.invokeRemoteCommand(CommandAwareRpcDispatcher.java:165)
... 74 more
Caused by: org.infinispan.marshall.NotSerializableException: org.primefaces.component.fileupload.FileUpload
Caused by: an exception which occurred:
in field uploadComponent
in field bean
in object java.util.HashMap@0
in object org.jboss.as.clustering.SimpleMarshalledValue@0
in object org.infinispan.atomic.PutOperation@1fe7028
in object java.util.LinkedList@90f00d5b
in object org.infinispan.atomic.AtomicHashMapDelta@46933
in object org.infinispan.commands.write.PutKeyValueCommand@515ccf63
in object org.infinispan.commands.tx.PrepareCommand@1aaebdcd
我检查了 infinispan 文档,发现实际上可以使用 AdvancedExternalizers 处理更细粒度的组件编组(包括那些不实现 Serializable 的组件)。
所以我为non-Serializable jsf组件写了一个,如下图:
public static class FileUploadExternalizer implements AdvancedExternalizer<FileUpload> {
private static final long serialVersionUID = 1L;
@Override
public void writeObject(ObjectOutput output, FileUpload fileUpload)
throws IOException {
}
@Override
public FileUpload readObject(ObjectInput input)
throws IOException, ClassNotFoundException {
return new FileUpload();
}
@SuppressWarnings("unchecked")
@Override
public Set<Class<? extends FileUpload>> getTypeClasses() {
return Util.<Class<? extends FileUpload>>asSet(FileUpload.class);
}
@Override
public Integer getId() {
return null;
}
}
其中 FileUpload 是不可序列化的 jsf(primefaces)组件。
对于独立的 infinispan,可以使用 infinispan 配置元素中的 xml 配置向 infinispan 注册 Externalizer 类,如下所示:
<infinispan>
<global>
<serialization>
<advancedExternalizers>
<advancedExternalizer externalizerClass="..."/>
</advancedExternalizers>
</serialization>
</global>
...
</infinispan>
问题是当从 JBoss 7 容器中使用 infinispan 时,配置是不同的。配置在 jboss7 Standalone.xml(或任何其他配置 xml 文件)中完成。
不幸的是,在 Jboss7 中,无法配置元素。根据关于 infinispan 配置的 jboss7 文档,
Where is <global/>?
Much of the global configuration contains references to other JBoss AS services. In JBoss AS 7, these services are auto-injected behind the scenes. This includes things like thread pools (described below), the JGroups transport (also described below), and the mbean server.
这让我可以选择通过代码进行注册。所以我创建了一个应用程序范围的接缝组件来在那里进行注册:
@Name("infinispanExternalizerRegistration")
@Scope(ScopeType.APPLICATION)
@Startup
public class InfinispanAdvancedExternalizerRegistration {
@Create
public void init(){
GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder();
builder.serialization().addAdvancedExternalizer(2345, new PhotoUploader.FileUploadExternalizer());
}
}
但是,我仍然得到这个问题开头描述的 NotSerializableExceptions。这是正确的行为吗?还是我的 AdvancedExternalizer 真的因为一些错误的配置而无法工作?提前感谢您的帮助。