4 Replies Latest reply on Jan 19, 2016 10:39 AM by Paul Ferraro

    Registering Infinispan AdvancedExternalizers on JBoss7

    Charles Akalugwu Newbie

      Hi,

       

       

      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