Multitenancy and second level cache problems

Hi all,
I work on a project use spring boot 2.1, hibernate 5.3.14.Final.
I have a problem with the second level caching, i change the cache used from EHcache to infinispan for Multitenancy and distributed cache for invalidating entity.
My problem appeared when an second tenant use the application.
I start the server and i call a WS (Tenant1) to load from BDD some entity

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Entityimplements Serializable { … }

I see the first request and subselect request, at the second call of WS i don’t see any request, i modify an entity, the cache for this entity is invalidate, at the call, i see a request -> OK

After that when i use a WS to an other tenant, i see the request and result -> OK

and at this time the second cache level doesn’t seem works. On any tenant, if i load some entity, nothing is cached, every time the request is execute on BDD.

CacheFactoryConfiguration .java

@Component
public class CacheFactoryConfiguration extends InfinispanRegionFactory {

    private static final long serialVersionUID = 1L;

    private EmbeddedCacheManager cacheManager;

    public CacheFactoryConfiguration(EmbeddedCacheManager cacheManager) {
        super();
        this.cacheManager = cacheManager;
    }

    @Override
    protected EmbeddedCacheManager createCacheManager(Properties properties, ServiceRegistry serviceRegistry) {
        System.out.println("create cache manager");
        return cacheManager;
    }
}

CacheFactoryConfiguration .java

@Configuration
@EnableCaching
public class CacheConfiguration{

    private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);

    // Initialize the cache in a non Spring-managed bean
    private static EmbeddedCacheManager cacheManager;

    public static EmbeddedCacheManager getCacheManager() {
        System.out.println("getCacheManager");
        return cacheManager;
    }

    public static void setCacheManager(EmbeddedCacheManager cacheManager) {
        System.out.println("setCacheManager");
        CacheConfiguration.cacheManager = cacheManager;
    }

    @Bean
    public InfinispanGlobalConfigurer globalConfiguration(JHipsterProperties jHipsterProperties) {
        log.info("Defining Infinispan Global Configuration");
        return () -> GlobalConfigurationBuilder.defaultClusteredBuilder()
                .defaultCacheName("infinispan-test-cluster-cache").transport().defaultTransport()
                .addProperty("configurationFile", jHipsterProperties.getCache().getInfinispan().getConfigFile())
                .clusterName("infinispan-test-cluster").globalJmxStatistics()
                .enabled(jHipsterProperties.getCache().getInfinispan().isStatsEnabled()).allowDuplicateDomains(true)
                .build();
    }


    @Bean
    public InfinispanCacheConfigurer cacheConfigurer(JHipsterProperties jHipsterProperties) {
        log.info("Defining {} configuration", "app-data for local, replicated and distributed modes");
        JHipsterProperties.Cache.Infinispan cacheInfo = jHipsterProperties.getCache().getInfinispan();

        return manager -> {
            // initialize application cache
            manager.defineConfiguration("local-app-data",
                    new ConfigurationBuilder().clustering().cacheMode(CacheMode.LOCAL).jmxStatistics()
                            .enabled(cacheInfo.isStatsEnabled()).memory().evictionType(EvictionType.COUNT)
                            .size(cacheInfo.getLocal().getMaxEntries()).expiration()
                            .lifespan(cacheInfo.getLocal().getTimeToLiveSeconds(), TimeUnit.SECONDS).build());
            manager.defineConfiguration("dist-app-data",
                    new ConfigurationBuilder().clustering().cacheMode(CacheMode.DIST_SYNC).hash()
                            .numOwners(cacheInfo.getDistributed().getInstanceCount()).jmxStatistics()
                            .enabled(cacheInfo.isStatsEnabled()).memory().evictionType(EvictionType.COUNT)
                            .size(cacheInfo.getDistributed().getMaxEntries()).expiration()
                            .lifespan(cacheInfo.getDistributed().getTimeToLiveSeconds(), TimeUnit.SECONDS).build());
            manager.defineConfiguration("repl-app-data",
                    new ConfigurationBuilder().clustering().cacheMode(CacheMode.REPL_SYNC).jmxStatistics()
                            .enabled(cacheInfo.isStatsEnabled()).memory().evictionType(EvictionType.COUNT)
                            .size(cacheInfo.getReplicated().getMaxEntries()).expiration()
                            .lifespan(cacheInfo.getReplicated().getTimeToLiveSeconds(), TimeUnit.SECONDS).build());

            // initialize Hibernate L2 cache configuration templates
            manager.defineConfiguration("entity",
                    new ConfigurationBuilder().clustering().cacheMode(CacheMode.INVALIDATION_SYNC).jmxStatistics()
                            .enabled(cacheInfo.isStatsEnabled()).locking().concurrencyLevel(1000)
                            .lockAcquisitionTimeout(15000).template(true).build());
            manager.defineConfiguration("replicated-entity",
                    new ConfigurationBuilder().clustering().cacheMode(CacheMode.REPL_SYNC).jmxStatistics()
                            .enabled(cacheInfo.isStatsEnabled()).locking().concurrencyLevel(1000)
                            .lockAcquisitionTimeout(15000).template(true).build());
            manager.defineConfiguration("local-query",
                    new ConfigurationBuilder().clustering().cacheMode(CacheMode.LOCAL).jmxStatistics()
                            .enabled(cacheInfo.isStatsEnabled()).locking().concurrencyLevel(1000)
                            .lockAcquisitionTimeout(15000).template(true).build());
            manager.defineConfiguration("replicated-query",
                    new ConfigurationBuilder().clustering().cacheMode(CacheMode.REPL_ASYNC).jmxStatistics()
                            .enabled(cacheInfo.isStatsEnabled()).locking().concurrencyLevel(1000)
                            .lockAcquisitionTimeout(15000).template(true).build());
            manager.defineConfiguration("timestamps",
                    new ConfigurationBuilder().clustering().cacheMode(CacheMode.REPL_ASYNC).jmxStatistics()
                            .enabled(cacheInfo.isStatsEnabled()).locking().concurrencyLevel(1000)
                            .lockAcquisitionTimeout(15000).template(true).build());
            manager.defineConfiguration("pending-puts",
                    new ConfigurationBuilder().clustering().cacheMode(CacheMode.LOCAL).jmxStatistics()
                            .enabled(cacheInfo.isStatsEnabled()).simpleCache(true).transaction()
                            .transactionMode(TransactionMode.NON_TRANSACTIONAL).expiration().maxIdle(60000)
                            .template(true).build());

            Stream.of(com.mycompany.repository.campagne.CampagneRepository.CAMPAGNE_BY_DATE_CACHE)
                    .forEach(cacheName -> manager.defineConfiguration(cacheName,
                            new ConfigurationBuilder().clustering().cacheMode(CacheMode.INVALIDATION_SYNC)
                                    .jmxStatistics().enabled(cacheInfo.isStatsEnabled()).locking()
                                    .concurrencyLevel(1000).lockAcquisitionTimeout(15000).build()));

            setCacheManager(manager);
        };
    }

configuration.yml

spring:
    jpa:
        database-platform: io.github.jhipster.domain.util.FixedPostgreSQL95Dialect
        database: POSTGRESQL
        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.infinispan.statistics: true
            hibernate.cache.use_minimal_puts: true
            hibernate.cache.infinispan.entity.expiration.lifespan: 3600000
            hibernate.cache.infinispan.entity.memory.size: 1000
            hibernate.cache.infinispan.jgroups_cfg: default-configs/default-jgroups-tcp.xml

jhipster:
    cache:
        infinispan:
            config-file: default-configs/default-jgroups-tcp.xml
            statsEnabled: true

            local:
                time-to-live-seconds: 3600
                max-entries: 1000 

            distributed:
                time-to-live-seconds: 3600
                max-entries: 1000
                instance-count: 2
         
            replicated:
                time-to-live-seconds: 3600
                max-entries: 1000

Configuration of multitenancy for schema based

@Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
        Map<String, Object> hibernateProps = new LinkedHashMap<>();

        hibernateProps.putAll(hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(),
                new HibernateSettings()));
        hibernateProps.putAll(jpaProperties.getProperties());
        hibernateProps.put(AvailableSettings.CACHE_REGION_FACTORY, cacheFactoryConfiguration);
        hibernateProps.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
        hibernateProps.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider);
        hibernateProps.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolver);
        hibernateProps.put(Environment.DIALECT, jpaProperties.getDatabasePlatform());
        return builder.dataSource(dataSource).packages("com.mycompany.domain").properties(hibernateProps).jta(false)
                .build();
    }

Switching schema :

@Component
public class MultiTenantConnectionProviderImpl implements MultiTenantConnectionProvider {
    private static final long serialVersionUID = 6246085840652870138L;
    private static final Logger log = LoggerFactory.getLogger(MultiTenantConnectionProviderImpl.class);

    @Autowired
    private transient DataSource dataSource;

    @Override
    public Connection getAnyConnection() throws SQLException {
        return dataSource.getConnection();
    }

    @Override
    public void releaseAnyConnection(Connection connection) throws SQLException {
        connection.close();
    }

    @Override
    public Connection getConnection(String tenantIdentifier) throws SQLException {
        final Connection connection = getAnyConnection();
        try {
            connection.setSchema(tenantIdentifier);
        } catch (SQLException e) {
            log.warn("Use default schema, only in test mode");
        }
        return connection;
    }

    @Override
    public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
        try {
            connection.setSchema(RequestContextHolderUtils.getCurrentTenantIdentifier());
        } catch (SQLException e) {
            log.warn("Use default schema, only in test mode");
        }
        connection.close();
    }

    @SuppressWarnings("rawtypes")
    @Override
    public boolean isUnwrappableAs(Class unwrapType) {
        return false;
    }

    @Override
    public <T> T unwrap(Class<T> unwrapType) {
        return null;
    }

    @Override
    public boolean supportsAggressiveRelease() {
        return true;
    }
}

i read inside the documentation that the tenant is used to create key to store cache, i don’t see where is this problem, someone have an idea ? how can i see the current tenant of hibernate ?