4 Replies Latest reply on Dec 15, 2016 10:10 AM by a.niemeyer

    JpaStoreConfigurationBuilder and unpersisted data in LocalCache with embedded DBs like Derby or Hypersonic?

    a.niemeyer

      Hi,

       

      I tried hard to get a running configuration - and failed:

       

      For a local (database) caching in a staging service the entities should be written and persisted in sync into an embedded database permanently with less memory consumtion as possible.

      The issue is that no (entity) data is written into the database but data tables were created in-process.

       

      Setup: AppServer WildFly Full 9.0.1.Final with infinispan 7.2.3 with infinispan-cachestore-jpa-7.2.3.Final.jar release.

       

      The LocalCache itself is valid, I did some debugging and logging, entities are stored in the cache and could read out back from memory.

       

      The database and tables were managed by JTA and Hibernate, defined in a persistence.xml; the hibernate managed datasource is probably independent from the programmatically cache setup in the ServiceBean.

       

      I guess I did some misconfigurations and before I give it a new try with an updated Wildfly 10 release, I would like to know the reasons first.

       

      There are dozens of configuration options available and probably one would do the trick... or a wrong persistence configuration is in charge or misunderstandings....

       

      Thank you in advance for any pieces of help!

       

      Kind regards,

      Andreas

       

      The planned architecture is simple:

       

      1.) using a SingletonBean bean for providing the cache service

       

      @Startup
      @Singleton
      @LocalBean
      @TransactionManagement(TransactionManagementType.BEAN)

      public class LocalCacheService

       

           private Logger log = LoggerFactory.getLogger(LocalCacheService.class);

           private EmbeddedCacheManager cacheManager;

           private Cache<String, TestCacheEntityXY> jpaCache;

       

      @PostConstruct
      private void init() {

       

        GlobalConfiguration globalConfig = new GlobalConfigurationBuilder().globalJmxStatistics().allowDuplicateDomains(true).jmxDomain("domain").build();

          // playing around with different property values - nothing helped

        Configuration cacheConfig = new ConfigurationBuilder().persistence()

        .passivation(true)

        .addStore(JpaStoreConfigurationBuilder.class)

        .persistenceUnitName("TestCacheUnit")

        .entityClass(TestCacheEntityXY.class)

        .purgeOnStartup(false)

        .preload(true)

        .shared(true)
         .jmxStatistics()

        .enabled(false)

        .clustering()

        .cacheMode(CacheMode.LOCAL)

        .transaction()

        .transactionMode(TransactionMode.TRANSACTIONAL)

        .autoCommit(false)

        .transactionManagerLookup(new GenericTransactionManagerLookup())

        .build();

       

      // StoreConfiguration storeConfiguration = cacheConfig.persistence().stores().get(0);

       

        // JpaStoreConfiguration jpaCacheLoaderConfig = (JpaStoreConfiguration) storeConfiguration;

       

         cacheManager = new DefaultCacheManager(globalConfig);

         cacheManager.defineConfiguration("userCache", cacheConfig);

         cacheManager.start();

         jpaCache = cacheManager.getCache();

       

         log.info("start LocalCacheService bean with cache size: " + jpaCache.size());

         try {

              utx.begin();

         for (int i = 0; i < 10000; i++) {

              jpaCache.put(i + "", new TestCacheEntityXY(i + "", i + "@test.de"));

        }

         utx.commit();

        } catch (Exception e) {

              if (utx != null) {

              try {

                   utx.rollback();

             } catch (Exception e1) {

             }

             }

        }

       

         log.info(" LocalCacheService bean with cache size after inserts: " + jpaCache.size());

      }

      }

       

      @PreDestroy
      private void stop() {

         log.info("stop LocalCacheService bean with cache size: " + jpaCache.size());

         jpaCache.stop();

         cacheManager.stop();

       

      }

       

       

      2.) definition of persistence unit

       

      <persistence-unit name="TestCacheUnit" transaction-type="JTA">

       

         <provider>org.hibernate.ejb.HibernatePersistence</provider>

       

         <jta-data-source>java:jboss/datasources/Test-Cache</jta-data-source>

       

         <exclude-unlisted-classes>true</exclude-unlisted-classes>

       

         <class>de.xy.TestCacheEntityXY</class>

         <properties>

       

         <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyTenSevenDialect"/>

         <property name="hibernate.hbm2ddl.auto" value="update" />

         <property name="hibernate.format_sql" value="true"/>

         <property name="hibernate.show_sql" value="true"/>

       

         </properties>

      </persistence-unit>

       

      3.) separated datasource definition

       

      <datasources xmlns="http://www.jboss.org/ironjacamar/schema"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.jboss.org/ironjacamar/schema http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">

       

         <datasource jta="true" jndi-name="java:jboss/datasources/Test-Cache" pool-name="Test-CacheDSPool"  enabled="true"  use-ccm="true"  use-java-context="true">

              <connection-url>jdbc:derby:${jboss.server.data.dir}/derby/TestCache;create=true</connection-url>

              <driver>derby</driver>

              <security>

                   <user-name>sa</user-name>

                   <password>sa</password>

              </security>

       

         </datasource>

       

      </datasources>

       

      4.) standalone.xml driver configuration

       

      <drivers>

                 <driver name="derby" module="org.apache.derby">

                        <driver-class>org.apache.derby.jdbc.EmbeddedDriver</driver-class>

                 </driver>

      </drivers>

        • 1. Re: JpaStoreConfigurationBuilder and unpersisted data in LocalCache with embedded DBs like Derby or Hypersonic?
          a.niemeyer

          Hi,

           

          I did some changes:

           

          • upgraded to WildFly 10.1.2.Final containing by EAP 7.0.0 release
          • upgrades infinispan-cachestore-jpa-8.1.2.Final.jar and setup in `modules\system\layers\base\org\infinispan\cachestore\jpa\main'
            • make them accessable in jboss-deployment-structure.xml
              • <module name="org.infinispan.cachestore.jpa" export="true" />
          • My persistence.xml is designed to that example configurations:
          • Read the same cache as asigned in the definition and not the default cache as it is not the same cache as defined

                    cacheManager.defineConfiguration("jpaCache", cacheConfig);

                    jpaCache = cacheManager.getCache("jpaCache");  -> this call starts the cache initialisation and results in an error...

           

          During debugging I noticed the EntityManagerFactory in the org.infinispan.persistence.jpa.JPAStore.class is null and cannot be gathered and it results in an exception:

           

          Caused by: javax.ejb.EJBException: org.infinispan.commons.CacheException: Unable to invoke method public void org.infinispan.persistence.manager.PersistenceManagerImpl.start() on object of type PersistenceManagerImpl

           

          The reason seems the EntityManagerFactory could not determined:

           

             this.emfRegistry = (EntityManagerFactoryRegistry)ctx.getCache().getAdvancedCache().getComponentRegistry().getGlobalComponentRegistry().getComponent(EntityManagerFactoryRegistry.class);

           

          Thank you for help!

           

          Kind regards,

          Andreas

           

           

          1.) Part stack of exception:

           

          Caused by: org.infinispan.commons.CacheException: Unable to invoke method public void org.infinispan.persistence.manager.PersistenceManagerImpl.start() on object of type PersistenceManagerImpl

              at org.infinispan.commons.util.ReflectionUtil.invokeAccessibly(ReflectionUtil.java:172)

              at org.infinispan.factories.AbstractComponentRegistry$PrioritizedMethod.invoke(AbstractComponentRegistry.java:887)

              at org.infinispan.factories.AbstractComponentRegistry.invokeStartMethods(AbstractComponentRegistry.java:656)

              at org.infinispan.factories.AbstractComponentRegistry.internalStart(AbstractComponentRegistry.java:645)

              at org.infinispan.factories.AbstractComponentRegistry.start(AbstractComponentRegistry.java:548)

              at org.infinispan.factories.ComponentRegistry.start(ComponentRegistry.java:222)

              at org.infinispan.cache.impl.CacheImpl.start(CacheImpl.java:849)

              at org.infinispan.manager.DefaultCacheManager.wireAndStartCache(DefaultCacheManager.java:621)

              at org.infinispan.manager.DefaultCacheManager.createCache(DefaultCacheManager.java:572)

              at org.infinispan.manager.DefaultCacheManager.getCache(DefaultCacheManager.java:440)

              at org.infinispan.manager.DefaultCacheManager.getCache(DefaultCacheManager.java:426)

              at de.xxx.cache.LocalCacheService.init(LocalCacheService.java:198)

              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.jboss.as.ee.component.ManagedReferenceLifecycleMethodInterceptor.processInvocation(ManagedReferenceLifecycleMethodInterceptor.java:96)

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

              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:340)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

              ... 26 more

          Caused by: org.infinispan.commons.CacheException: Unable to start cache loaders

              at org.infinispan.persistence.manager.PersistenceManagerImpl.start(PersistenceManagerImpl.java:174)

              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.infinispan.commons.util.ReflectionUtil.invokeAccessibly(ReflectionUtil.java:168)

              ... 61 more

          Caused by: java.lang.NullPointerException

              at org.infinispan.persistence.jpa.JpaStore.start(JpaStore.java:80)

              at org.infinispan.persistence.manager.PersistenceManagerImpl.start(PersistenceManagerImpl.java:141)

              ... 66 more

           

          1.1) The method in JPAStore wherein the emfRegistry could not gathered:

           

          public void init(InitializationContext ctx) {

             this.configuration = (JpaStoreConfiguration)ctx.getConfiguration();

             this.emfRegistry = (EntityManagerFactoryRegistry)ctx.getCache().getAdvancedCache().getComponentRegistry().getGlobalComponentRegistry().getComponent(EntityManagerFactoryRegistry.class);

             this.marshallerEntryFactory = ctx.getMarshalledEntryFactory();

             this.marshaller = ctx.getMarshaller();

             this.timeService = ctx.getTimeService();

          }

           

           

          2.) The programmatically initialisation of the JPACacheStore in my singleton EJB I changed a bit

           

          Configuration cacheConfig = new ConfigurationBuilder().persistence()

            .passivation(false)

            .addStore(JpaStoreConfigurationBuilder.class)

            .persistenceUnitName("CacheJPA")

            .entityClass(EntityXX.class)

            .ignoreModifications(false)

            .purgeOnStartup(false)

            .preload(false)

            .shared(false)

            .async().enabled(false) //.flushLockTimeout(10, TimeUnit.SECONDS).threadPoolSize(1).ignoreModifications(false)
            //.eviction().type(EvictionType.COUNT).size(10L).strategy(EvictionStrategy.LRU)
             .jmxStatistics()

            .enabled(false)

            .clustering()

            .transaction()

            .transactionMode(TransactionMode.TRANSACTIONAL)

            .autoCommit(false)

            .transactionManagerLookup(new GenericTransactionManagerLookup())

            .build();

           

          GlobalConfiguration globalConfig = new GlobalConfigurationBuilder().globalJmxStatistics().allowDuplicateDomains(true).cacheManagerName("jpaCacheContainer").enabled(true).build();

          cacheManager = new DefaultCacheManager(globalConfig);

          cacheManager.defineConfiguration("jpaCache", cacheConfig);

          jpaCache = cacheManager.getCache("jpaCache");

           

          3.) persistence.xml

           

          <persistence-unit name="CacheJPA">

           

             <description>Cache Persistence Unit</description>

             <!--provider>org.hibernate.jpa.HibernatePersistenceProvider</provider-->

             <class>de.xx.cache.entity.EntityXX</class>

             <properties>

            

             <property name="hibernate.hbm2ddl.auto" value="create"/>

             <property name="hibernate.show_sql" value="true"/>

             <property name="hibernate.format_sql" value="true"/>

             <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyTenSevenDialect"/>

             <property name="hibernate.connection.url" value="jdbc:derby:${derby.system.home}ISP-CacheX;create=true"/>

             <property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.EmbeddedDriver"/>

             <property name="hibernate.connection.username" value="sa"/>

             <property name="hibernate.connection.password" value="sa"/>

             <property name="hibernate.jdbc.batch_size" value="20"/>

             <property name="hibernate.jdbc.fetch_size" value="20"/>

             <property name="hibernate.connection.autocommit" value="false"/>

            

             </properties>

           

          </persistence-unit>

           

           

          • 2. Re: JpaStoreConfigurationBuilder and unpersisted data in LocalCache with embedded DBs like Derby or Hypersonic?
            a.niemeyer

            Hi,

             

            after a deeper investigation I got all running.

             

            The trick was to add more and the correct dependencies in the module.xml of the infinispan cachestore jpa and other tiny settings / imports due classloader issues.

             

            The infinispan-cachestore-jpa needs to be included - and not only provided in the Maven POM if you want to use the the external infinispan configuration for the scheme files:

             

            jacheManager = new DefaultCacheManager("META-INF/XXX-Cache-infinispan.xml");

             

            Kind regards,

            Andreas

             

             

            1.) EAP-7\modules\system\layers\base\org\infinispan\cachestore\jpa\main\module.xml

             

            <?xml version="1.0" encoding="UTF-8"?>

             

            <module xmlns="urn:jboss:module:1.3" name="org.infinispan.cachestore.jpa">

                <properties>

                    <property name="jboss.api" value="private"/>

                </properties>

             

                <resources>

                    <resource-root path="infinispan-cachestore-jpa-8.1.2.Final.jar"/>

                </resources>

             

                <dependencies>

                    <module name="javax.api"/>

                    <module name="org.javassist"/>

                    <module name="javax.persistence.api"/>       

                    <module name="org.hibernate"/>

                    <module name="javax.transaction.api"/>

                    <module name="org.apache.commons.pool"/>

                    <module name="org.infinispan"/>

                    <module name="org.infinispan.commons"/>

                    <module name="org.jboss.logging"/>

                </dependencies>

            </module>

             

             

            2.) jboss-deployment-structure.xml

             

            <jboss-deployment-structure>

               <ear-subdeployments-isolated>false</ear-subdeployments-isolated>

               <deployment>

               <dependencies>

                     <module name="org.infinispan" export="true" />

                     <module name="org.infinispan.commons" export="true" />

                    <module name="org.infinispan.cachestore.jpa" export="true" />

               </dependencies>

               </deployment>

            </jboss-deployment-structure>

             

            3.) persistence.xml with unit

             

            <persistence-unit name="XXXCacheJPA">

             

               <class>org.infinispan.persistence.jpa.impl.MetadataEntity</class>

               <class>de.xxx.TestCacheEntityXY</class>

             

               <exclude-unlisted-classes>true</exclude-unlisted-classes>

             

               <properties>

               <property name="hibernate.hbm2ddl.auto" value="validate"/>

               <property name="hibernate.show_sql" value="true"/>

               <property name="hibernate.format_sql" value="true"/>

               <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyTenSevenDialect"/>

               <property name="hibernate.connection.url" value="jdbc:derby:${derby.system.home}ISP-Cache;create=false"/>

               <property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.EmbeddedDriver"/>

               <property name="hibernate.connection.username" value="sa"/>

               <property name="hibernate.connection.password" value="sa"/>

               <property name="hibernate.jdbc.batch_size" value="20"/>

               <property name="hibernate.jdbc.fetch_size" value="20"/>

               <property name="hibernate.connection.autocommit" value="false"/>

               <property name="hibernate.integration.envers.enabled" value="false"/>

               </properties>

            </persistence-unit>

             

            The {derby.system.home} is set as CLI -D argument: -Dderby.system.home:C\x\y\z\data\derby

             

            4.) Imports in EJB Projects

             

            <dependency>

               <groupId>org.infinispan</groupId>

               <artifactId>infinispan-core</artifactId>

               <version>${version.infinispan}</version>

               <scope>provided</scope>

            </dependency>

             

            <dependency>

               <groupId>org.infinispan</groupId>

               <artifactId>infinispan-cachestore-jpa</artifactId>

               <version>${version.infinispan}</version>

            </dependency>

             

            <dependency>

               <groupId>org.infinispan</groupId>

               <artifactId>infinispan-commons</artifactId>

               <version>${version.infinispan}</version>

               <scope>provided</scope>

            </dependency>

             

             

            • 3. Re: JpaStoreConfigurationBuilder and unpersisted data in LocalCache with embedded DBs like Derby or Hypersonic?
              sannegrinovero

              Hi Andreas,

              glad you got it working, but allow me an additional suggestion:

               

              The Infinispan libraries included within WildFly are not meant to be used "directly" by applications, these should be considered implementation detail of the application server's clustering and caching services.

               

              The Infinispan project also distributes a zip file with the full modules set, for people wishing to use Infinispan directly on WildFly: see the "WildFly/EAP modules" button on http://infinispan.org/download/

               

              There are several benefits to using the separate modules:

              • you can upgrade Infinispan without needing to change appserver version (or replace its used Infinispan version)
              • you get all other modules, like the JPA CacheStore, which are otherwise missing
              • you can even have multiple (different) Infinispan versions in the same appserver, to serve different apps
              • these modules are actually tested for scenarios like the one you had ;-)

               

              There's also one drawback: since it's a different Infinispan module, you can't configure caches by editing the appserver's configuration file: you'll have to start a new CacheManager (however I see you already do that).

              • 4. Re: JpaStoreConfigurationBuilder and unpersisted data in LocalCache with embedded DBs like Derby or Hypersonic?
                a.niemeyer

                Hi Sanne,

                 

                Thank you for that additional infos :-)

                 

                I will go with this dependeny:

                 

                <dependency>

                   <groupId>org.infinispan</groupId>

                   <artifactId>infinispan-embedded</artifactId>

                   <version>8.2.5.Final</version>

                </dependency>

                 

                The only required installation under `modules\system\layers\base' is the installation of the derby db since re-deployments keep a file lock if the driver is in the ear.

                 

                Following this article Installing Apache Derby to WildFly - Kohei Nozaki's blog  the derby setup looks like:

                 

                <?xml version="1.0" encoding="UTF-8"?>

                 

                <module xmlns="urn:jboss:module:1.3" name="org.apache.derby">

                 

                    <resources>

                        <resource-root path="derby.jar"/>

                        <resource-root path="derbytools.jar"/>

                        <resource-root path="derbynet.jar"/>

                    </resources>

                 

                    <dependencies>

                        <module name="javax.api"/>

                        <module name="javax.transaction.api"/>

                    </dependencies>

                </module>

                 

                 

                Great, I wish I had found the dependency before - on the other hand I learned a lot.

                 

                Next plan is using hibernate search or a similar module for indexing mails content of eml files in the cache store.

                Maybe you have a recommendation how to index everything in a lob excepting the base64 content?

                 

                Anyway - thank you!

                 

                Kind regards,

                Andreas