JHipster - проблема с Hibernate 2-й кеш / ehcache при попытке извлечь JHipster из проекта, сгенерированного JHipster - PullRequest
0 голосов
/ 18 января 2019

Я пытаюсь создать общий шаблон бэкэнда для весенней загрузки на основе сгенерированного JHipster (поскольку некоторые приложения не будут обслуживаться мной, а другим разработчикам Spring, возможно, придется адаптироваться к jhipster, чтобы внести изменения в jhipster путь). Тем не менее, процесс, которого я придерживался для достижения этой цели: создать два проекта jhipster со следующими настройками:

{
    "generator-jhipster": {
        "promptValues": {
            "packageName": "com.mypackage.springtemplate",
            "nativeLanguage": "en"
        },
        "jhipsterVersion": "5.7.2",
        "applicationType": "monolith",
        "baseName": "springtemplate",
        "packageName": "com.mypackage.springtemplate",
        "packageFolder": "com/mypackage/springtemplate",
        "serverPort": "8080",
        "authenticationType": "jwt",
        "cacheProvider": "ehcache",
        "enableHibernateCache": true,
        "websocket": "spring-websocket",
        "databaseType": "sql",
        "devDatabaseType": "mysql",
        "prodDatabaseType": "mysql",
        "searchEngine": false,
        "messageBroker": false,
        "serviceDiscoveryType": false,
        "buildTool": "maven",
        "enableSwaggerCodegen": false,
        "jwtSecretKey": "****",
        "clientFramework": "angularX",
        "useSass": true,
        "clientPackageManager": "npm",
        "testFrameworks": [],
        "jhiPrefix": "jhi",
        "otherModules": [],
        "enableTranslation": true,
        "nativeLanguage": "en",
        "languages": ["en", "es"]
    }
}

Один из них был для того, чтобы иметь это как ссылку. Вторым был проект, чтобы вынуть вещи Jhipster. Шаги, которые я выполнил, были:

  1. Удалена спецификация jhipster и включены отсутствующие зависимости.
  2. Локально скопировал используемые классы JHipster Framework (в основном для config и utils).
  3. Переименованный «JHipster» упоминает «Приложение».
  4. Изменено приложение - * .ml рамки ссылок на локальные.

Вот основные изменения структуры, которые произошли в проекте: Primary changes

Дело в том, что при попытке запустить проект я получаю следующую ошибку с Hibernate 2-го уровня cache / ehcache:

Caused by: java.lang.IllegalStateException: All Hibernate caches should be created upfront. Please update CacheConfiguration.java to add com.mypackage.springtemplate.domain.User
    at com.mypackage.springtemplate.config.cache.NoDefaultJCacheRegionFactory.createCache(NoDefaultJCacheRegionFactory.java:24)
    at org.hibernate.cache.jcache.JCacheRegionFactory.getOrCreateCache(JCacheRegionFactory.java:190)
    at org.hibernate.cache.jcache.JCacheRegionFactory.buildEntityRegion(JCacheRegionFactory.java:113)
    at org.hibernate.cache.spi.RegionFactory.buildEntityRegion(RegionFactory.java:132)

Конфигурация hibernate application-dev.yml указывает на новые локальные классы:

jpa:
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    database: MYSQL
    show-sql: true
    properties:
        hibernate.id.new_generator_mappings: true
        hibernate.connection.provider_disables_autocommit: true
        hibernate.cache.use_second_level_cache: true
        hibernate.cache.use_query_cache: false
        hibernate.generate_statistics: true
        hibernate.cache.region.factory_class: com.mypackage.springtemplate.config.cache.BeanClassLoaderAwareJCacheRegionFactory

Классы, связанные с кэшем, остаются прежними ...

BeanClassLoaderAwareJCacheRegionFactory.java

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Objects;
import java.util.Properties;

import javax.cache.CacheException;
import javax.cache.CacheManager;
import javax.cache.spi.CachingProvider;

/**
 * Fixes Spring classloader issues that were introduced in Spring Boot 2.0.3.
 *
 * This allows to use the same classloader for ehcache, both for the Spring Cache abstraction and for the Hibernate
 * 2nd level cache.
 *
 * See https://github.com/jhipster/generator-jhipster/issues/7783 for more information.
 */
public class BeanClassLoaderAwareJCacheRegionFactory extends NoDefaultJCacheRegionFactory {

    private static volatile ClassLoader classLoader;

    @Override
    protected CacheManager getCacheManager(Properties properties) {
        Objects.requireNonNull(classLoader, "Please set Spring's classloader in the setBeanClassLoader " +
            "method before using this class in Hibernate");
        CachingProvider cachingProvider = getCachingProvider( properties );
        String cacheManagerUri = getProp( properties, CONFIG_URI );

        URI uri = getUri(cachingProvider, cacheManagerUri);
        CacheManager cacheManager = cachingProvider.getCacheManager(uri, classLoader);

        // To prevent some class loader memory leak this might cause
        setBeanClassLoader(null);

        return cacheManager;
    }

    private URI getUri(CachingProvider cachingProvider, String cacheManagerUri) {
        URI uri;
        if (cacheManagerUri != null) {
            try {
                uri = new URI(cacheManagerUri);
            }
            catch (URISyntaxException e) {
                throw new CacheException("Couldn't create URI from " + cacheManagerUri, e);
            }
        }
        else {
            uri = cachingProvider.getDefaultURI();
        }
        return uri;
    }

    /**
     * This method must be called from a Spring Bean to get the classloader.
     * For example: BeanClassLoaderAwareJCacheRegionFactory.setBeanClassLoader(this.getClass().getClassLoader());
     *
     * @param classLoader The Spring classloader
     */
    public static void setBeanClassLoader(ClassLoader classLoader) {
        BeanClassLoaderAwareJCacheRegionFactory.classLoader = classLoader;
    }
} 

NoDefaultJCacheRegionFactory.java

import java.util.Properties;
import javax.cache.Cache;

import org.hibernate.cache.jcache.JCacheRegionFactory;
import org.hibernate.cache.spi.CacheDataDescription;

/**
 * Extends the default {@code JCacheRegionFactory} but makes sure all caches already exist to prevent
 * spontaneous creation of badly configured caches (e.g. {@code new MutableConfiguration()}.
 *
 * See http://www.ehcache.org/blog/2017/03/15/spontaneous-cache-creation.html for more information.
 */
@SuppressWarnings("serial")
public class NoDefaultJCacheRegionFactory extends JCacheRegionFactory {

    public static final String EXCEPTION_MESSAGE = "All Hibernate caches should be created upfront. " +
        "Please update CacheConfiguration.java to add";

    @Override
    protected Cache<Object, Object> createCache(String regionName, Properties properties, CacheDataDescription
        metadata) {
        throw new IllegalStateException(EXCEPTION_MESSAGE + " " + regionName);
    }
}

CacheConfiguration.java

import java.time.Duration;

import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.ExpiryPolicyBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.jsr107.Eh107Configuration;
import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.mypackage.springtemplate.config.properties.ApplicationProperties;

@Configuration
@EnableCaching
public class CacheConfiguration {

    private final javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration;

    public CacheConfiguration(ApplicationProperties applicationProperties) {
        BeanClassLoaderAwareJCacheRegionFactory.setBeanClassLoader(this.getClass().getClassLoader());
        ApplicationProperties.Cache.Ehcache ehcache =
            applicationProperties.getCache().getEhcache();

        jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(
            CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class,
                ResourcePoolsBuilder.heap(ehcache.getMaxEntries()))
                .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(ehcache.getTimeToLiveSeconds())))
                .build());
    }

    @Bean
    public JCacheManagerCustomizer cacheManagerCustomizer() {
        return cm -> {
            cm.createCache(com.mypackage.springtemplate.repository.UserRepository.USERS_BY_LOGIN_CACHE, jcacheConfiguration);
            cm.createCache(com.mypackage.springtemplate.repository.UserRepository.USERS_BY_EMAIL_CACHE, jcacheConfiguration);
            cm.createCache(com.mypackage.springtemplate.domain.User.class.getName(), jcacheConfiguration);
            cm.createCache(com.mypackage.springtemplate.domain.Authority.class.getName(), jcacheConfiguration);
            cm.createCache(com.mypackage.springtemplate.domain.User.class.getName() + ".authorities", jcacheConfiguration);
        };
    }
}

Уже проверено этот вопрос но цель Дейва отличается от моей. На самом деле я не делаю никаких изменений в сгенерированной реализации кэширования jhipster.

Есть что-то, что я пропускаю? Возможно, ликвидасы делают что-то, что я пропустил?

1 Ответ

0 голосов
/ 21 января 2019

Также возможно, что CacheConfiguration.cacheManagerCustomizer вообще не вызывается. Это будет означать, что вы нарушили конфигурацию кеша и, вероятно, не используете кеш или простой кеш, а не Ehcache. Пожалуйста, убедитесь, что javax.cache правильно указан в вашем классе.

Другая возможность заключается в том, что вы не используете один и тот же CacheManage для Hibernate и Spring. Пожалуйста, отладьте в EhcacheCachingProvider и убедитесь, что создан только один CacheManager. Если это не так, вам нужно посмотреть, что отличается. Обычно это загрузчик классов, но BeanClassLoaderAwareJCacheRegionFactory обычно должен предотвращать это.

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