JSFコンポーネント(正確にはprimefacesコンポーネント)への参照を保持するBeanがあります。
仕様によると、JSF コンポーネントはシリアライズできません。私の Web アプリは JBoss クラスターで実行され、Bean を分散する必要があります。つまり、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 を実装していないものを含む) のより細かいマーシャリングを実際に処理できることがわかりました。
そのため、以下に示すように、シリアル化できない 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 構成を使用して、Externalizer クラスを infinispan に登録できます。
<infinispan>
<global>
<serialization>
<advancedExternalizers>
<advancedExternalizer externalizerClass="..."/>
</advancedExternalizers>
</serialization>
</global>
...
</infinispan>
問題は、JBoss 7 コンテナ内から infinispan が使用されている場合、設定が異なることです。設定は jboss7 standalone.xml (またはその他の設定 xml ファイル) で行われます。
残念ながら、Jboss7 では、要素を構成することはできません。infinispan 設定に関する jboss7 docs によると、
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.
これにより、コードで登録を行うオプションが残りました。そこで、そこで登録を行うアプリケーション スコープの seam コンポーネントを作成しました。
@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 が本当に機能していないのでしょうか? 助けてくれてありがとう。