Не удалось запустить Wildfly при активном кеше запросов Hibernate - PullRequest
1 голос
/ 04 июля 2019

Мы переносим наше приложение с JBoss EAP 6.4 на WildFly 14. У нас возникают проблемы с Hibernate и Infinispan.

Приложение настроено на использование кэша второго уровня Hibernate (также называемого 2LC) с Infinispan от Wildfly.

Если включен кэш 2LC, но кэш запросов отключен, приложение запускается и работает нормально.

Но когда мы пытаемся снова включить кэш запросов (свойство hibernate.cache.use_query_cache , установленное на true ), он падает во время инициализации, давая объединенную трассировку стека.

java.lang.ClassCastException: org.infinispan.hibernate.cache.v53.impl.DomainDataRegionImpl cannot be cast to org.hibernate.cache.spi.QueryResultsRegion

Во время отладки я не могу понять, почему внутренний код Hibernate, который управляет кэшем второго уровня, пытается преобразовать область кэша сущностей в область кэша результатов запроса.

Я пытался использовать отдельные кэши для каждого, определяя свойство hibernate.cache.infinispan.query.cfg с кешем local-query , определенным в конфигурации Infinispan , но, похоже, Hibernate не принимает это во внимание.

Я довольно новичок в кеше, должен признаться, что не до конца понимаю, что делаю, даже после прочтения большого количества документации.

Версии:

  • Hibernate 5.3.6. Финал
  • Infinispan 9.3.1. Финал
  • WildFly 14.0.1. Финал
  • OpenJDK 1.8

Вот декларация зависимостей Maven в нашем заинтересованном pom.xml (приложение разделено на несколько проектов Maven)

  • org.infinispan: infinispan-spring4-внедрен (по умолчанию / компилировать)
  • org.infinispan: core-span-core (предоставляется)
  • org.infinispan: infinispan-commons (предоставляется)
  • org.infinispan: infinispan-hibernate-cache-v53 (предоставляется)
  • org.infinispan: infinispan-hibernate-cache-spi (предоставляется)
  • org.infinispan: infinispan-hibernate-cache-commons (предоставляется)

Все это в версии 9.3.1. Финал

Это конфигурация контейнеров кэша, хранящаяся в standalone.xml :

        <subsystem xmlns="urn:jboss:domain:infinispan:7.0">
            ...
            <cache-container name="hibernate" module="org.infinispan.hibernate-cache">
                <local-cache name="entity">
                    <transaction mode="NON_XA"/>
                    <object-memory size="10000"/>
                    <expiration max-idle="100000"/>
                </local-cache>
                <local-cache name="local-query">
                    <object-memory size="10000"/>
                    <expiration max-idle="100000"/>
                </local-cache>
                <local-cache name="timestamps"/>
            </cache-container>
        </subsystem>

Раздел зависимостей нашего jboss-deploy-structure.xml .

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
    <deployment>
        ...
        <dependencies>
            <!-- Infinispan -->
            <module name="org.infinispan" /> 
            <module name="org.infinispan.commons" />
            <module name="org.infinispan.hibernate-cache"/>

        </dependencies>
    </deployment>
</jboss-deployment-structure>

Наш конфигурационный файл Infinispan:

<infinispan
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:infinispan:config:7.0 http://www.infinispan.org/schemas/infinispan-config-7.0.xsd"
    xmlns="urn:infinispan:config:7.0">
    <threads />

    <cache-container name="DefaultCacheManager"
        statistics="true">
        <transport />
        <jmx duplicate-domains="true" />

        <local-cache name="___defaultcache">
            <transaction mode="NONE" />
        </local-cache>

        <local-cache name="defaultCache">
            <transaction mode="NONE" />
            <expiration lifespan="1000" max-idle="1000" interval="500" />
            <memory>
                <object size="1000" />
            </memory>
            <persistence passivation="false">
                <file-store purge="false" read-only="false"
                    path="${jboss.server.temp.dir}/cacheservice" />
            </persistence>
        </local-cache>

        <local-cache name="local-query">
            <locking isolation="READ_COMMITTED" concurrency-level="1000"
                acquire-timeout="15000" striping="false" />
            <eviction max-entries="140000" strategy="LRU" />
            <expiration max-idle="1200000" />
            <transaction mode="NONE" auto-commit="false" />
        </local-cache>

        <!-- Other application caches ... -->

    </cache-container>
</infinispan>

Вместо правильного запуска автономный экземпляр WildFly аварийно завершает свою работу во время инициализации при попытке подключить кэш 2LC и выдает следующую трассировку стека.

Установка hibernate.cache.use_query_cache в false решает проблему, но нам нужен кеш запросов.

Caused by: java.lang.ClassCastException: org.infinispan.hibernate.cache.v53.impl.DomainDataRegionImpl cannot be cast to org.hibernate.cache.spi.QueryResultsRegion
    at org.hibernate.cache.internal.EnabledCaching.makeQueryResultsRegionAccess(EnabledCaching.java:491)
    at org.hibernate.cache.internal.EnabledCaching.getQueryResultsCache(EnabledCaching.java:478)
    at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2515)
    at org.hibernate.loader.Loader.list(Loader.java:2498)
    at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:109)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1959)
    at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:370)
    at fr.bdf.interop.middle.dao.hibernate.HibernateGenericDao.find(HibernateGenericDao.java:110)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy204.find(Unknown Source)
    ...

Спасибо

1 Ответ

0 голосов
/ 12 июля 2019

Наконец-то я нашел, как это исправить.Как сказал Радим Ванса, проблема возникла из-за конфликта между областью кэша сущностей / коллекции и областью кэша запросов.

В документации Hibernate относительно кэширования я обнаружил, что для определения имени области кэша для запроса или критериев,setCacheRegion(String) метод должен быть использован.

Просматривая все вызовы этих методов в нашем коде, я наконец понял, что в нашем абстрактном универсальном классе DAO мы определяем имя области запроса следующим образом:

public HibernateGenericDao(Class<E> type) {
    ...
    this.cacheRegion = type.getCanonicalName();
}

Здесь используется поле cacheRegion:

criteria.setCacheRegion(getCacheRegion());

Учитывая, что имя области кэша сущностей / коллекций также определяется полным именем класса сущностей (мы не знаем, как), добавление суффикса к имени области кэша запросов разрешит конфликт и заставит приложение запускаться правильно.

this.cacheRegion = type.getCanonicalName().concat(QUERY_CACHE_REGION_PREFIX);

Спасибо,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...