Search code examples
hibernateinfinispanwildfly-10second-level-cache

Hibernate Infinispan 2LC : query cache and entity cache in same cache region


Using JBoss Cache, it was possible to store the entity cache and query cache in the same cache region without any issue. But once migrated to wildfly 10 (with infinispan as 2LC) , there seems to be problem.

I have provided the cache region for entity as below.

@Entity     
@Cacheable  
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY, 
     region="regionA")
public class EntityXYZ{

And query cache as

 entManager.createQuery(
        "....")
    .setHint("org.hibernate.cacheable", true)
    .setHint("org.hibernate.cacheRegion", "regionA").getResultList();

It is important to note that the above query also contains the entities that are themselves declared as cacheable and has same cache region as regionA.

Now on execution, there is this error. I suspect that it is due to conflict as they are stored in same region and it tries to fetch object id that returns another object. But can someone throw light. Is this really the case ? and explain more about the error ?

But the same works in JBoss cache in JBoss 5. Does infinispan handles differently ? Or is this Hibernate issue ?

ERROR [org.jboss.as.ejb3.invocation] (default task-8) WFLYEJB0034: EJB Invocation failed on component... javax.ejb.EJBTransactionRolledbackException: Object [id=4] was not of the specified subclass [ com.abc.xyz] : loaded object was of wrong class class  com.abc.yyy
                at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleInCallerTx(CMTTxInterceptor.java:159)
                at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:256)

     [org.hibernate.event.internal.DefaultLoadEventListener] (default task-8) HHH000327: Error performing load command : org.hibernate.WrongClassException: Object [id=4] was not of the specified subclass [com.abc.xyz] : loaded object was of wrong class class com.abc.yyy

UPDATE:

The entitymanager tries to load in different calls of 2 such classes (in same shared cache 2LC region) that has @id as int. As Flavius pointed out, the id=4 seems to be common between 2 classes.

On adding below config to persistence.xml , there is a startup error.

persistence.xml

<property name="hibernate.cache.keys_factory" value="default" />

error

 javax.persistence.PersistenceException: [PersistenceUnit: app-entity] Unable to build Hibernate SessionFactory
            at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:179)
            at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:121)
            at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:667)
            at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:193)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
            at java.lang.Thread.run(Thread.java:745)
            at org.jboss.threads.JBossThread.run(JBossThread.java:320)
    Caused by: javax.persistence.PersistenceException: [PersistenceUnit: app-entity] Unable to build Hibernate SessionFactory
            at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:954)
            at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:882)
            at org.jboss.as.jpa.hibernate5.TwoPhaseBootstrapImpl.build(TwoPhaseBootstrapImpl.java:44)
            at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:161)
            ... 7 more
    Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.spi.CacheImplementor]
            at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264)
            at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228)
            at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207)
            at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:242)
            at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444)
            at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879)
            ... 9 more
    Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [default] as strategy [org.hibernate.cache.spi.CacheKeysFactory]
            at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor(StrategySelectorImpl.java:113)
            at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveDefaultableStrategy(StrategySelectorImpl.java:162)
            at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveDefaultableStrategy(StrategySelectorImpl.java:126)

UPDATE 2

I have changed to provide the default to exact FQN, however it does not work. The error is not correct as the class is implementation of the specified class.

<property name="hibernate.cache.keys_factory" value="org.hibernate.cache.internal.DefaultCacheKeysFactory" />

error:

Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.spi.CacheImplementor]
        at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264)
        at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228)
        at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207)
        at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:242)
        at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444)
        at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879)
        ... 9 more
Caused by: java.lang.ClassCastException: org.hibernate.cache.internal.DefaultCacheKeysFactory cannot be cast to org.hibernate.cache.spi.CacheKeysFactory
        at org.hibernate.cache.infinispan.InfinispanRegionFactory.determineCacheKeysFactory(InfinispanRegionFactory.java:427)
        at org.hibernate.cache.infinispan.InfinispanRegionFactory.start(InfinispanRegionFactory.java:378)
        at org.hibernate.internal.CacheImpl.<init>(CacheImpl.java:49)
        at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:28)
        at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:20)
        at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.initiateService(SessionFactoryServiceRegistryImpl.java:46)
        at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254)

Solution

  • Query cache is string-indexed, and the entity cache is indexed either using raw ids (the same object as the field/method marked with @Id in EntityXYZ) so I wonder how the conflict could happen on id=4.

    Anyway, it's not a good idea to use the same region (cache) for entities and queries - entities sometimes need more complex handling to achieve DB-style isolation. Such combination may not be possible at all with Hibernate 6. You may not hit the issues until you run stress tests in many threads, sequential invocation usually works ok.

    If you insist on storing them into the same cache, you could try setting hibernate.cache.keys_factory=default (I hope your WF version already contains this setting, newer versions should have it already as default).

    See https://hibernate.atlassian.net/browse/HHH-11083 and https://hibernate.atlassian.net/browse/HHH-10287 for details.