11 Replies Latest reply on Apr 27, 2015 3:20 PM by jvskriubakken

    ClassCastException on object of same class when retrieving object from a Infinispan cache

    jvskriubakken

      Hello!

      I'm struggling with a ClassCastException on object of same class when retrieving object from a Infinispan cache which was populated by another module.

       

      I'm using Wildfly 8.2.0.Final.

       

      I've setup an Infinispan invalidation cache:

      <cache-container name="my-caches" module="org.wildfly.clustering.ejb.infinispan">

        <transport lock-timeout="60000"/>

        <invalidation-cache name="my-objects" start="EAGER" mode="SYNC">

        <transaction mode="NON_XA"/>

        </invalidation-cache>

      </cache-container>

       

      In the shared service layer code the cache is accessed through a producer like this:

      class MyObjectCacheProducer {

        @Resource(lookup = "java:jboss/infinispan/cache/my-caches/my-objects")

        @Produces
        @MyObjectCacheQualifier
        Map<String, MyObject> cache;
      }

       

      The cache is then used by both an ear and a war deployed on the same Wildfly server using a standalone-ha configuration. This is our typical development scenario - where we wish to deploy every part of the application in one local Wildfly server.


      Depending on which module (war or ear) that populates the cache first, the second one accessing it will always get a:
      java.lang.ClassCastException: com.acme.domain.MyObject cannot be cast to com.acme.domain.MyObject

      As I understand it, this happens because the java.lang.Class.equals fails when objects retrieved from the cache was created in another module (which uses another ClassLoader).

       

      I thought the purpose of an Infinispan invalidation-cache was not to reuse data but to only send invalidations (Infinispan User Guide). But maybe that only applies if the cache is remote? Which is not the case in my development scenario where both war and ear are deployed on the same "Wildfly standalone-ha" server?

       

      How can I solve this problem in a way that it both works in a development scenario (where all modules are deployed) and in a production scenario where typically the war and ear runs on different servers.

       

      Please, do not hesitate to ask if you need any more information to answer more accurately.

       

      Help is most appriciated!

       

      Thanks!

       

      Jørund Vier Skriubakken

      System Developer @ logiq.no

        • 1. Re: ClassCastException on object of same class when retrieving object from a Infinispan cache
          frenky1983

          In my opinion you have a conflict between dependency, may be you have two different version in your app and in wildfly.

          If you hadadded the artifact in wildfly you might defined in scope provided in your app (if you use maven).

          i had the same error with dom4j and adding this

           

          <dependency>

             <groupId>dom4j</groupId>

             <artifactId>dom4j</artifactId>

             <version>1.1</version>

             <scope>provided</scope>

          </dependency>


          i solved, because that artifact is yet in wildfly

          i hope this is helpful

          • 2. Re: ClassCastException on object of same class when retrieving object from a Infinispan cache
            jvskriubakken

            Hi and thanks for your opinion! I'm not sure if I understand your explanation. Mayed I should try explain how my application is organized.

             

            myapp-part1.ear

            myapp-part2.ear

            myapp-admin.war

             

            In a production sceniaro the ears and war can be deployed on differnet servers or together. In a development scenario they are typically all deployed together.

             

            Both parts (ear) and the admin (war) uses/depends on two shared jars (myapp-domain.jar, myapp-services.jar) which contains the shared domain and service classes. MyObject is packaged in the myapp-domain.jar and the Infinispan cache is accessed by a service in myapp-services.jar.

             

            The exception occurs when one of the ears or war retrieves a MyObject which have been populated in the cache by one of the other ears or war.

             

            Since the deployments cannot be depenent on each other I cannot set myapp-domain.jar or myapp-service.jar as provided.

             

            Does this make my problem clearer?

             

            Thanks!

            Jørund

            • 3. Re: ClassCastException on object of same class when retrieving object from a Infinispan cache
              wdfink

              The cache is shared, all object in the cache are the seen by-reference for both applications.

              Now if one app put something into the cache the other app need to be able to solve the class.

               

              Now if you have MyObject.class in both applications packed these classes are identified by class and classloader, if you have the class packed in both ear files this will end in a ClassCast. You need to add the class to a module or store it as binary (there is a binary cache) but in this case each access to the cache need to use marshalling which might have performance issues.

              1 of 1 people found this helpful
              • 4. Re: ClassCastException on object of same class when retrieving object from a Infinispan cache
                leo.chen

                Hi Wolf-Dieter,

                 

                Can you please spare some time to take a look a problem I am meeting with here:

                EAP 6.4.0.GA start error: java.lang.ClassNotFoundException from Service Module Loader

                 

                It is really blocking my progress on my work of upgrding JBoss. It is much appreciated if you can give me some advise on how to fix this problem.

                • 5. Re: ClassCastException on object of same class when retrieving object from a Infinispan cache
                  jvskriubakken

                  Thanks for the answer Wolf-Dieter!

                   

                  Yes, my cached domain objects are immutables so I'm trying my best to avoid marshalling/unmarshalling. But is it common to "deploy" your applicaiton's domain classes as a static module in this case? Is that wise?

                  • 6. Re: ClassCastException on object of same class when retrieving object from a Infinispan cache
                    wdfink

                    It depends

                     

                    If you try to use the cache and the classes inside "as reference" it might be faster and not burden the GC.

                    But you need to have the correct classloading with a module.

                     

                    If you need to be independent from classes (i.e. to be able to use different versions of it with rolling updates of the application) you can pack the class into the application, but in this case you need to use marshalling to access the cache.

                    But if so I would consider a remote cache and access via HotRod, this will keep the cache complete independent from the application

                    • 7. Re: ClassCastException on object of same class when retrieving object from a Infinispan cache
                      jvskriubakken

                      Hi!

                       

                      Thanks again Wolf-Dieter for the follow up.

                       

                      I'm hoping to avoid marshalling to access the cache.

                      I'm hoping that both apps can load my domain object using the same class loader, but I'm unsure of the consequences of deploying new updates where domain classes have changes. As I understand I then have to undeploy all my dependent apps before updating the static modules with my domain classes.

                       

                      How about having different versions of the the same library in the static modules.. like serveral versions on Guava, is that possible?

                      Do you know any indepth resource explaining usage of static modules for you're own classes?

                      • 8. Re: ClassCastException on object of same class when retrieving object from a Infinispan cache
                        pferraro

                        For starters, do not use start="EAGER".  This can cause Infinispan to attempt to unmarshal objects from your cache before your deployment module is available.  This has caused so many issues for people that I plan to drop it altogether.

                        Also, you don't need to define a module for your cache-container unless you have custom externalizers that you wish to auto-register.

                        That said, an invalidation cache should never have to serialize your cache values, since invalidation events should only require marshalling of the key.

                        • 9. Re: ClassCastException on object of same class when retrieving object from a Infinispan cache
                          jvskriubakken

                          Hi and thanks for your reply Paul!

                           

                          If I do not set start="EAGER" on the cache, then deployment fails with the following exception:

                           

                          Caused by: java.lang.IllegalArgumentException: JBAS016081: Error injecting resource into CDI managed bean. Can't find a resource named java:jboss/infinispan/cache/babel-config-caches/detection-steps defined on java.util.Map no.logiq.babel.service.document.format.DetectionStepCacheProducer.cache

                            at org.jboss.as.weld.services.bootstrap.WeldResourceInjectionServices.resolveResource(WeldResourceInjectionServices.java:188)

                            at org.jboss.as.weld.services.bootstrap.WeldResourceInjectionServices$1.createResource(WeldResourceInjectionServices.java:139)

                            at org.jboss.weld.injection.AbstractResourceInjection.getResourceReference(AbstractResourceInjection.java:44)

                            at org.jboss.weld.injection.AbstractResourceInjection.injectResourceReference(AbstractResourceInjection.java:53)

                            at org.jboss.weld.util.Beans.injectEEFields(Beans.java:343)

                            at org.jboss.weld.injection.producer.ResourceInjector$1.proceed(ResourceInjector.java:69)

                            at org.jboss.weld.injection.InjectionContextImpl.run(InjectionContextImpl.java:48)

                            at org.jboss.weld.injection.producer.ResourceInjector.inject(ResourceInjector.java:72)

                            at org.jboss.weld.injection.producer.BasicInjectionTarget.inject(BasicInjectionTarget.java:121)

                            at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:150)

                            at org.jboss.weld.context.unbound.DependentContextImpl.get(DependentContextImpl.java:69)

                            at org.jboss.weld.manager.BeanManagerImpl.getReference(BeanManagerImpl.java:742)

                            at org.jboss.weld.injection.producer.AbstractMemberProducer.getReceiver(AbstractMemberProducer.java:128)

                            at org.jboss.weld.injection.producer.AbstractMemberProducer.produce(AbstractMemberProducer.java:148)

                            at org.jboss.weld.bean.AbstractProducerBean.create(AbstractProducerBean.java:183)

                            at org.jboss.weld.bean.builtin.ee.EEResourceProducerField.createUnderlying(EEResourceProducerField.java:144)

                            at org.jboss.weld.bean.builtin.ee.EEResourceProducerField.access$000(EEResourceProducerField.java:48)

                            at org.jboss.weld.bean.builtin.ee.EEResourceProducerField$EEResourceCallable.call(EEResourceProducerField.java:68)

                            at org.jboss.weld.bean.builtin.CallableMethodHandler.invoke(CallableMethodHandler.java:38)

                            at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56)

                            at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:100)

                            at org.jboss.weld.util.Map$500775993$Proxy$_$$_Weld$Proxy$.get(Unknown Source)

                            at no.logiq.babel.service.document.format.DetectionStepCacheImpl.get(DetectionStepCacheImpl.java:32)

                            at no.logiq.babel.service.document.format.DetectionStepServiceImpl.getAll(DetectionStepServiceImpl.java:26)

                            at no.logiq.babel.processor.boot.BootServiceBean.checkDetectionSteps(BootServiceBean.java:78)

                          at no.logiq.babel.processor.boot.BootServiceBean.initialize(BootServiceBean.java:59)

                            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.8.0_31]

                            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) [rt.jar:1.8.0_31]

                            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.8.0_31]

                            at java.lang.reflect.Method.invoke(Method.java:483) [rt.jar:1.8.0_31]

                            at org.jboss.as.ee.component.ManagedReferenceLifecycleMethodInterceptor.processInvocation(ManagedReferenceLifecycleMethodInterceptor.java:96)

                            at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)

                            at org.jboss.invocation.WeavedInterceptor.processInvocation(WeavedInterceptor.java:53)

                            at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)

                            at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.doLifecycleInterception(Jsr299BindingsInterceptor.java:114)

                            at org.jboss.as.weld.ejb.Jsr299BindingsInterceptor.processInvocation(Jsr299BindingsInterceptor.java:103)

                            at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)

                            at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:407)

                            at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:55)

                            at org.jboss.as.weld.ejb.EjbRequestScopeActivationInterceptor.processInvocation(EjbRequestScopeActivationInterceptor.java:83)

                            at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)

                            at org.jboss.as.weld.injection.WeldInjectionInterceptor.processInvocation(WeldInjectionInterceptor.java:53)

                            at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)

                            at org.jboss.as.ee.component.AroundConstructInterceptorFactory$1.processInvocation(AroundConstructInterceptorFactory.java:28)

                            at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)

                            at org.jboss.as.weld.injection.WeldInterceptorInjectionInterceptor.processInvocation(WeldInterceptorInjectionInterceptor.java:56)

                            at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)

                            at org.jboss.as.weld.ejb.Jsr299BindingsCreateInterceptor.processInvocation(Jsr299BindingsCreateInterceptor.java:94)

                            at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)

                            at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50)

                            at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309)

                            at org.jboss.as.ejb3.tx.EjbBMTInterceptor.handleInvocation(EjbBMTInterceptor.java:104)

                            ... 26 more

                          Caused by: javax.naming.NameNotFoundException: infinispan/cache/babel-config-caches/detection-steps [Root exception is java.lang.IllegalStateException]

                            at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:140) [wildfly-naming-8.2.0.Final.jar:8.2.0.Final]

                            at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:81) [wildfly-naming-8.2.0.Final.jar:8.2.0.Final]

                            at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:202) [wildfly-naming-8.2.0.Final.jar:8.2.0.Final]

                           

                          ... because we have a "BootServiceBean" with a @PostConstruct method that triggers code that tries to access (populate) the Infinispan cache:

                          @Startup
                          @javax.ejb.Singleton
                          @TransactionManagement(TransactionManagementType.BEAN)

                          public class BootServiceBean {

                          ....

                            @PostConstruct
                            public void initialize() {

                             ....

                            }
                          }

                          • 10. Re: ClassCastException on object of same class when retrieving object from a Infinispan cache
                            pferraro

                            Rather than accessing the "java:jboss" namespace directly, try using a resource-ref to map the jndi resource to a standard jndi namespace.

                            See: JNDI Reference - WildFly 8 - Project Documentation Editor

                            e.g.

                            In your deployment descriptor:

                            <resource-ref>
                              <res-ref-name>caches/mycache</res-ref-name>
                              <lookup-name>java:jboss/infinispan/babel-config-caches/detection-steps</lookup-name>
                            </resource-ref>
                            

                             

                            In your producer:

                            @Resource(name="caches/mycache")
                            @Produces
                            @MyObjectCacheQualifier
                            Map<String, MyObject> cache;
                            
                            • 11. Re: ClassCastException on object of same class when retrieving object from a Infinispan cache
                              jvskriubakken

                              You write "Also, you don't need to define a module for your cache-container unless you have custom externalizers that you wish to auto-register." I'm not sure if I follow you here.

                              The idea was to create a static module for our domain classes so that two deployed modules could access the same Infinispan invalidation-cache without any marshalling/unmarshalling.