2 Replies Latest reply on Jan 9, 2013 5:39 PM by Tomáš Klouček

    Problems with creating own JDBCStore (java.lang.IllegalArgumentException: Cannot load null class!)

    Tomáš Klouček Newbie

      Hi guys,

       

      I'm trying to create own JDBCStore with JBoss Infinispan, version 5.1.7.Final. But everytime when I try to get the instance

      of the cache with the attached Store, via EmbddedCacheManager:

       

      (cache is added programatically, adding it within the XML configuration file ends with the same result....)

       

       

      Configuration loc = new ConfigurationBuilder()
              .clustering().cacheMode(CacheMode.LOCAL)
              .transaction().transactionMode(TransactionMode.TRANSACTIONAL)
              .autoCommit(false)
              .transactionManagerLookup(new GenericTransactionManagerLookup())
              .loaders().passivation(false).preload(false).shared(false)
              .addCacheLoader().cacheLoader(new JDBCStore())
              .fetchPersistentState(false).purgeOnStartup(true)
              .addProperty("url", "jdbc:oracle:thin:@localhost:1521:XE")
              .addProperty("user", "......")
              .addProperty("password", "......")
              .addProperty("driverClassName", "oracle.jdbc.driver.OracleDriver")      
              .build();
                      
              SampleCacheContainer.getCacheContainer().defineConfiguration(CACHE_NAME, loc);        
              
              Cache<Long, String> writerCache = SampleCacheContainer.getCacheContainer().getCache(CACHE_NAME);
              writerCache.put(1, "aaaaaa");
              writerCache.put(2, "bbbbbb");
              writerCache.put(3, "cccccc");    
      

       

      it fails with:

       

       

      java.lang.reflect.InvocationTargetException
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
      java:39)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
      sorImpl.java:25)
              at java.lang.reflect.Method.invoke(Method.java:597)
              at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:297)
              at java.lang.Thread.run(Thread.java:662)
      Caused by: org.infinispan.CacheException: Unable to invoke method public void or
      g.infinispan.loaders.CacheLoaderManagerImpl.start() on object of type CacheLoade
      rManagerImpl
              at org.infinispan.util.ReflectionUtil.invokeAccessibly(ReflectionUtil.ja
      va:238)
              at org.infinispan.factories.AbstractComponentRegistry$PrioritizedMethod.
      invoke(AbstractComponentRegistry.java:889)
              at org.infinispan.factories.AbstractComponentRegistry.invokeStartMethods
      (AbstractComponentRegistry.java:639)
              at org.infinispan.factories.AbstractComponentRegistry.internalStart(Abst
      ractComponentRegistry.java:628)
              at org.infinispan.factories.AbstractComponentRegistry.start(AbstractComp
      onentRegistry.java:531)
              at org.infinispan.factories.ComponentRegistry.start(ComponentRegistry.ja
      va:174)
              at org.infinispan.CacheImpl.start(CacheImpl.java:521)
              at org.infinispan.manager.DefaultCacheManager.createCache(DefaultCacheMa
      nager.java:656)
              at org.infinispan.manager.DefaultCacheManager.getCache(DefaultCacheManag
      er.java:549)
              at com.sample.SampleCacheContainer.getCache(SampleCacheContainer.java:59
      )
              at com.sample.Application.registerCacheWithWriter(Application.java:118)
              at com.sample.Application.main(Application.java:133)
              ... 6 more
      Caused by: org.infinispan.CacheException: Unable to start cache loaders
              at org.infinispan.loaders.CacheLoaderManagerImpl.start(CacheLoaderManage
      rImpl.java:160)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
      java:39)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
      sorImpl.java:25)
              at java.lang.reflect.Method.invoke(Method.java:597)
              at org.infinispan.util.ReflectionUtil.invokeAccessibly(ReflectionUtil.ja
      va:236)
              ... 17 more
      Caused by: java.lang.IllegalArgumentException: Cannot load null class!
              at org.infinispan.util.Util.getInstance(Util.java:207)
              at org.infinispan.loaders.CacheLoaderManagerImpl.createCacheLoader(Cache
      LoaderManagerImpl.java:292)
              at org.infinispan.loaders.CacheLoaderManagerImpl.createCacheLoader(Cache
      LoaderManagerImpl.java:277)
              at org.infinispan.loaders.CacheLoaderManagerImpl.start(CacheLoaderManage
      rImpl.java:146)
              ... 22 more
      
      

       

      Simple test implementation of the Store looks like (I was trying to follow the JDBCStringBasedCacheStore....)  :

       

       

       

      package com.samplestore;
      
      import java.io.ObjectInput;
      import java.io.ObjectOutput;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.util.ArrayList;
      import java.util.HashSet;
      import java.util.List;
      import java.util.Set;
      
      import org.apache.commons.dbcp.BasicDataSource;
      import org.infinispan.Cache;
      import org.infinispan.container.InternalEntryFactoryImpl;
      import org.infinispan.container.entries.InternalCacheEntry;
      import org.infinispan.container.versioning.EntryVersion;
      import org.infinispan.container.versioning.InequalVersionComparisonResult;
      import org.infinispan.loaders.AbstractCacheStore;
      import org.infinispan.loaders.CacheLoaderConfig;
      import org.infinispan.loaders.CacheLoaderException;
      import org.infinispan.loaders.CacheLoaderMetadata;
      import org.infinispan.marshall.StreamingMarshaller;
      import org.springframework.jdbc.core.JdbcTemplate;
      import org.springframework.jdbc.core.RowMapper;
      
      class MyRowMapper implements RowMapper<InternalCacheEntry>
      {
          public InternalCacheEntry mapRow(ResultSet rs, int rowNum) throws SQLException {
              InternalEntryFactoryImpl impl = new InternalEntryFactoryImpl();
              return impl.create(rs.getLong("key"), rs.getString("value"), new EntryVersion() {
                  
                  @Override
                  public InequalVersionComparisonResult compareTo(EntryVersion arg0) {
                      return arg0.compareTo(this);
                  }
              });
          }
      
      }
      
      @CacheLoaderMetadata(configurationClass = MyCacheStoreConfig.class)
      public class JDBCStore extends AbstractCacheStore {
          
          private static final String TABLE = "TEST_INFINISPAN";
          
          private JdbcTemplate template;
          
          private MyCacheStoreConfig config;
          
          public void  init(CacheLoaderConfig config, Cache cache, StreamingMarshaller m) throws CacheLoaderException {
             super.init(config, cache, m);
             this.config = (MyCacheStoreConfig) config;    
             System.out.println("initializing...");
          }
          
          public void start() throws CacheLoaderException {
             super.start();
             BasicDataSource bdSource = new BasicDataSource();
              bdSource.setUrl(this.config.getUrl());
              bdSource.setUsername(this.config.getUser());
              bdSource.setPassword(this.config.getPassword());
              bdSource.setDriverClassName(this.config.getDriverClassName());
              
              template = new JdbcTemplate(bdSource);
              System.out.println("starting.......");
          }
      
          @Override
          public void clear() throws CacheLoaderException {
              // TODO Auto-generated method stub
              
          }
      
          @Override
          public void fromStream(ObjectInput arg0) throws CacheLoaderException {
              // TODO Auto-generated method stub
              
          }
      
          @Override
          public boolean remove(Object arg0) throws CacheLoaderException {
              // TODO Auto-generated method stub
              return false;
          }
      
          @Override
          public void store(InternalCacheEntry arg0) throws CacheLoaderException {
              System.out.println("store key...");
              List<Object[]> args = new ArrayList<Object[]>();
              prepareJdbcArgs(args, (Long) arg0.getKey(), (String) arg0.getValue());
              performInsert(args);                
          }
      
          @Override
          public void toStream(ObjectOutput arg0) throws CacheLoaderException {
              // TODO Auto-generated method stub
              
          }
      
          @Override
          public Class<? extends CacheLoaderConfig> getConfigurationClass() {
              return MyCacheStoreConfig.class;
          }
      
          @Override
          public InternalCacheEntry load(Object arg0) throws CacheLoaderException {
              System.out.println("load key...");
              String sql = "SELECT * FROM "+TABLE+" WHERE KEY = ?";
               
              InternalCacheEntry cacheEntry = (InternalCacheEntry)template.queryForObject(
                      sql, new Object[] { arg0 }, new MyRowMapper());
           
              return cacheEntry;        
          }
      
          @Override
          public Set<InternalCacheEntry> load(int arg0) throws CacheLoaderException {
              return loadAll();
          }
      
          @Override
          public Set<InternalCacheEntry> loadAll() throws CacheLoaderException {
              System.out.println("loading all keys...");
              return new HashSet(template.queryForList("select key from " + TABLE, Long.class));
          }
      
          @Override
          public Set<Object> loadAllKeys(Set<Object> arg0)
                  throws CacheLoaderException {
              // TODO Auto-generated method stub
              Set<Object> kSet = new HashSet<Object>();
              Set<InternalCacheEntry> lAll = loadAll();
              for (InternalCacheEntry entry: lAll) {
                  kSet.add(entry.getKey());
              }
              
              return kSet;
          }
      
          @Override
          protected void purgeInternal() throws CacheLoaderException {
              // TODO Auto-generated method stub        
          }
          
          private static void prepareJdbcArgs(List<Object[]> jdbcArgs, Long key, String map) {
              System.out.println("preparing args...");
              jdbcArgs.add(new Object[]{key, key, map});        
          }
          
          private void performInsert(List<Object[]> jdbcArgs) {
              System.out.println("performing insert...");
              template.batchUpdate("insert into " + TABLE + " (key, value) values (?,?)", jdbcArgs);
          }
      }
      

       

      Cache Store configuration looks like:

       

       

      package com.samplestore;
      
      import org.infinispan.loaders.AbstractCacheStoreConfig;
      
      public class MyCacheStoreConfig extends AbstractCacheStoreConfig {
          private static final long serialVersionUID = 1L;
      
          protected String url = "";
          protected String user = "";
          protected String password = "";
          protected String driverClassName = "";
          public String getUrl() {
              return url;
          }
          public void setUrl(String url) {
              this.url = url;
          }
          public String getUser() {
              return user;
          }
          public void setUser(String user) {
              this.user = user;
          }
          public String getPassword() {
              return password;
          }
          public void setPassword(String password) {
              this.password = password;
          }
          public String getDriverClassName() {
              return driverClassName;
          }
          public void setDriverClassName(String driverClassName) {
              this.driverClassName = driverClassName;
          }
          public static long getSerialversionuid() {
              return serialVersionUID;
          }        
      }
      

       

       

      Could some please point me onto what I'm doing wrong? Problem is that the documentation doesn't provide any example

      with creating of the own store implementation...:-((

       

      thanks a lot in advance

       

      T.

        • 1. Re: Problems with creating own JDBCStore (java.lang.IllegalArgumentException: Cannot load null class!)
          Tomáš Klouček Newbie

          I've been playing with this for a little while and exception message:

          "Caused by: java.lang.IllegalArgumentException: Cannot load null class!
                  at org.infinispan.util.Util.getInstance(Util.java:207)
                  at org.infinispan.loaders.CacheLoaderManagerImpl.createCacheLoader(Cache
          LoaderManagerImpl.java:292)
          "

           

          During getting the cache instance:

           

          ...SampleCacheContainer.getCacheContainer().getCache(CACHE_NAME);

           

          Really doesn't make any sense to me, because I have implemented the method

           

          public Class<? extends CacheLoaderConfig> getConfigurationClass()

           

          and class name of the loader is known of course....could someone please take a look at that?

           

          thanks a lot.

          • 2. Re: Problems with creating own JDBCStore (java.lang.IllegalArgumentException: Cannot load null class!)
            Tomáš Klouček Newbie

            Okay, after looking directly into Infinispan code...:-((((, class org.infinispan.loaders.CacheLoaderManagerImpl...

            I managed my test store to work!

             

            For anyone interested, Infinispan was failing in org.infinispan.loaders.CacheLoaderManagerImpl at this point:

             

            CacheLoader createCacheLoader(CacheLoaderConfig cfg, AdvancedCache<Object, Object> cache) throws Exception {

                     CacheLoader tmpLoader = (CacheLoader) Util.getInstance(cfg.getCacheLoaderClassName(), cache.getClassLoader());

                    .

                    .

             

            cfg.getCacheLoaderClassName was returning null value, so Infinispan was not able to create loader instance. The reason was that my implementation

            of AbstractCacheStoreConfig was not overriding method

             

             

            public String getCacheLoaderClassName()
            

             

             

            after I added into my MyCacheStoreConfig

             

            .

            .

             

            public String getCacheLoaderClassName() {
                    return "com.samplestore.JDBCStore";
            }
            

             

            then Infinispan started to work with my implementation of the cache store and I was able to save my cache values into DB...

             

            Anyway:

             

            • Infinispan's API for creating and configuring stores is extremely confusing...:-((( Why do I need to bind cache store and cache store config in this bi-directional way? In "cache store" I needed to implement:

             

                     public Class<? extends CacheLoaderConfig> getConfigurationClass()

             

                    and in the "Cache store" config I needed to implement getCacheLoaderClassName....?

            • I don't see any possibilities in the AbstractCacheStore interface of howto implement batching, because this class contains only "store" method with just one cache element entry...Is somehow possible to implement own batching in the own cache store implementation with Infinispan?

             

             

            best wishes

             

            Tomas