Registering Infinispan AdvancedExternalizers on JBoss7
canotech Aug 21, 2012 4:12 AMHi,
I have a bean which holds a reference to a JSF component (primefaces component to be exact). As per the spec, JSF components are not serializable. My web app runs in a JBoss cluster and the beans need to be distributed which means they need to be serializable. As a result, I therefore got this exception whenever I used the page whose backing bean is the one with the JSF component reference:
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
I checked the infinispan documentation and found that it is actually possible to handle finer-grained marshalling of components (including those which do not implement Serializable) by using AdvancedExternalizers.
So I wrote one for the non-Serializable jsf component as shown below:
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; } }
where FileUpload is the non-serializable jsf (primefaces) component.
For standalone infinispan, the Externalizer class can be registered with infinispan using xml configuration in the <global> element of the infinispan configuration as follows:
<infinispan> <global> <serialization> <advancedExternalizers> <advancedExternalizer externalizerClass="..."/> </advancedExternalizers> </serialization> </global> ... </infinispan>
The problem is that when infinispan is being used from within JBoss 7 container, then the configuration is different. The configuration is done in jboss7 standalone.xml (or any of the other config xml files ).
Unfortunately, in Jboss7, it is not possible to configure the <global> element. According to the jboss7 docs on infinispan configuration,
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.
This left me with the option of doing the registration by code. So I created an application-scoped seam component to do the registration there:
@Name("infinispanExternalizerRegistration") @Scope(ScopeType.APPLICATION) @Startup public class InfinispanAdvancedExternalizerRegistration { @Create public void init(){ GlobalConfigurationBuilder builder = new GlobalConfigurationBuilder(); builder.serialization().addAdvancedExternalizer(2345, new PhotoUploader.FileUploadExternalizer()); } }
However, I still get the NotSerializableExceptions described at the beginning of this question. Is this correct behavior? Or is my AdvancedExternalizer really not working due to some bad configuration? Thanks in advance for any help.
I am using Infinispan 5.1.5 Final, Seam 2.3.0 beta2 and JBoss AS 7.2.0 Alpha1