0

I have an Infinispan cache that I created through JBoss7.1 web interface. It is configured as an indexed, distributed cache.

In my jboss-deployment-structure.xml file I have added dependencies on org.infinispan and org.hibernate so I have access to my cache. I have also added a maven dependency on the following:

  <dependency>
     <groupId>org.infinispan</groupId>
     <artifactId>infinispan-core</artifactId>
     <version>5.1.7.Final</version>
     <scope>provided</scope>
  </dependency>
  <dependency>
     <groupId>org.infinispan</groupId>
     <artifactId>infinispan-query</artifactId>
     <version>5.1.7.Final</version>
  </dependency>

5.1.7.Final is the version included in the org.infinispan module in JBoss7.1.3 which I am using. This pulls in all the necessary dependencies (including lucene and hibernate-search-engine) so I do have the necessary libs in my project. However when doing the initial step mentioned here:

  SearchManager searchManager = Search.getSearchManager( cache );

It calls ComponentRegistryUtils.getComponent(cache, SearchFactoryIntegrator.class) which fails throwing IllegalArgumentException:

Indexing was not enabled on this cache. interface org.hibernate.search.spi.SearchFactoryIntegrator not found in registry

My cache has indexing enabled as can be seen by cache.getCacheConfiguration().indexing().enabled() returning true. But the application thinks it is not. Maybe this is because the cache's ComponentRegistry does not have access to the org.hibernate.search.spi.SearchFactoryIntegrator class (the cache being a JBoss global component, while the hibernate search lib is in my WAR's WEB-INF/lib directory).

Is there another way I should be doing this?

Sanne
  • 6,027
  • 19
  • 34
Shadow Man
  • 3,234
  • 1
  • 24
  • 35
  • Shadow Creeper did you perhaps ever revisit this and get the module approach to work? Facing the same problem here, http://stackoverflow.com/questions/18291687/unable-to-query-infinispan-on-jboss-7-due-to-searchfactoryintegrator-not-being-i – Kevin D Aug 18 '13 at 12:02
  • No, the module never worked for me, but I was able to exclude the JBoss module and just include the jars locally. – Shadow Man Aug 23 '13 at 00:25

3 Answers3

5

JBoss AS 7 includes an org.infinispan module as it's used internally by the clustering subsystem, but this module does not include the lucene and hibernate-search-engine dependencies.

By specifying those dependencies in your application you are (correctly) adding the missing dependencies, but the included org.infinispan doesn't "see" the extensions as the module can not load extension points from your application's classpath.

So a possible solution is to add those dependencies to the AS7 modules and patch the org.infinispan module to import these resources from your custom module.

An alternative solution is to not rely on the org.infinispan module included by the AS but include it all in your application. This way you also have more flexibility on using a different version, possibly a more recent one.

Sanne
  • 6,027
  • 19
  • 34
  • Yes, that's what I thought was happening. I was hoping there might be a way to export the libs in my WAR such that the JBoss infinispan module could get access to it or a way to create the query without depending on the cache's classloader (though I suspect the answer is no). At the moment I am trying to fiddle with https://community.jboss.org/message/799196#799196 (creating an `org.infinispan.query` jboss module) with slightly more success. If I get it working, I'll go ahead and post my JBoss7.1.3 working module to that thread. – Shadow Man May 22 '13 at 23:36
  • I was unable to get this working by creating an org.infinispan.query jboss module. I did however, get it working by including the infinispan libs in my project and creating the cache programmatically. See below for what finally worked for me. – Shadow Man May 28 '13 at 19:38
1

I ended up excluding infinispan and hibernate (rather not including them, which amounts to the same thing) from the jboss-deployment-structure.xml file.

Then I added a dependency in my pom.xml file on org.infinispan:infinispan-query:5.2.1.Final to pull all the jars into my WAR artifact's WEB-INF/lib directory.

Then I built the cache programmatically:

package com.myproduct.cache;

import org.infinispan.Cache;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.cache.ConfigurationChildBuilder;
import org.infinispan.configuration.global.GlobalConfiguration;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfigurationChildBuilder;
import org.infinispan.eviction.EvictionStrategy;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.transaction.LockingMode;
import org.infinispan.transaction.TransactionMode;
import org.infinispan.transaction.lookup.GenericTransactionManagerLookup;
import org.infinispan.util.concurrent.IsolationLevel;
import org.jetbrains.annotations.NotNull;

class MyObjectCacheFactory
{
   private static EmbeddedCacheManager m_cacheManager = null;
   private static Cache<String, MyObject> m_cache = null;

   @NotNull
   public static Cache<String, MyObject> getMyObjectCache ()
   {
      if( m_cache == null )
         createMyObjectCache();
      return m_cache;
   }

   private static synchronized void createMyObjectCache ()
   {
      if( m_cacheManager == null )
         createCacheManager();

      if( !m_cacheManager.cacheExists( "MyObjects" ) )
      {
         Configuration cacheConfig = createMyObjectCacheConfig();
         m_cacheManager.defineConfiguration( "MyObjects", cacheConfig );
      }

      if( !m_cacheManager.isRunning( "MyObjects" ) )
         m_cacheManager.getCache( "MyObjects" ).start();
      m_cache = m_cacheManager.getCache( "MyObjects" );
   }

   private static void createCacheManager ()
   {
      GlobalConfiguration globalConfiguration = createGlobalConfiguration();
      Configuration defaultCacheConfig = createDefaultCacheConfiguration();
      m_cacheManager = new DefaultCacheManager( globalConfiguration, defaultCacheConfig );
   }

   @NotNull
   private static Configuration createDefaultCacheConfiguration ()
   {
      ConfigurationChildBuilder builder = new ConfigurationBuilder();
      builder = builder.jmxStatistics().enable();
      builder = builder.clustering()
         .cacheMode( CacheMode.DIST_SYNC )
         .stateTransfer()
         .timeout( 100 );
      builder = builder.transaction()
         .transactionMode( TransactionMode.TRANSACTIONAL )
         .autoCommit( false )
         .lockingMode( LockingMode.OPTIMISTIC );
      return builder.build();
   }

   @NotNull
   private static GlobalConfiguration createGlobalConfiguration ()
   {
      GlobalConfigurationChildBuilder builder = new GlobalConfigurationBuilder().clusteredDefault();
      builder = builder.globalJmxStatistics()
         .enable()
         .cacheManagerName( "MyCacheManager" )
         .jmxDomain( "com.myproduct.cache" );
      return builder.build();
   }

   @NotNull
   private static Configuration createMyObjectCacheConfig ()
   {
      ConfigurationChildBuilder builder = new ConfigurationBuilder();
      builder = builder.jmxStatistics().enable();
      builder = builder.clustering().cacheMode( CacheMode.DIST_SYNC );
      builder = builder.transaction()
         .transactionMode( TransactionMode.TRANSACTIONAL )
         .autoCommit( false )
         .lockingMode( LockingMode.OPTIMISTIC )
         .transactionManagerLookup( new GenericTransactionManagerLookup() );
      builder = builder.locking().isolationLevel( IsolationLevel.REPEATABLE_READ );
      builder = builder.eviction().maxEntries( 100 ).strategy( EvictionStrategy.LRU );
      builder = builder.expiration().maxIdle( 30000 ).lifespan( -1 ).enableReaper();
      builder = builder.loaders().passivation( true ).addFileCacheStore().purgeOnStartup( true );
      builder = builder.indexing().enable().addProperty( "default.directory_provider", "ram" );
      return builder.build();
   }
}

and added @Field annotation to MyObject:

package com.myproduct.cache;

import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;

import java.io.Serializable;

@Indexed
public class MyObject
   implements Serializable
{
   @NotNull private String m_id;

   @Field(name = "searchNumber")
   private int m_searchNumber;

   public MyObject (
      @NotNull String id,
      int searchNumber )
   {
      m_id = id;
      m_searchNumber = searchNumber;
   }

   @NotNull
   public String getId ()
   {
      return m_id;
   }

   public int getSearchNumber ()
   {
      return m_searchNumber;
   }
}

and the search method:

import org.apache.lucene.search.Query;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.infinispan.Cache;
import org.infinispan.query.CacheQuery;
import org.infinispan.query.Search;
import org.infinispan.query.SearchManager;

[...]

   private Cache<String, MyObject> m_cache;

   @PostConstruct
   public void setup ()
   {
      m_cache = MyObjectCacheFactory.getMyObjectCache();
   }

   @NotNull
   public List<MyObject> getMyObjects ( int searchNumber )
   {
      SearchManager searchManager = Search.getSearchManager( m_cache );
      QueryBuilder queryBuilder = searchManager.buildQueryBuilderForClass( MyObject.class ).get();
      Query luceneQuery = queryBuilder.keyword().onField( "searchNumber" ).matching( searchNumber ).createQuery();
      CacheQuery cacheQuery = searchManager.getQuery( luceneQuery, MyObject.class );
      //noinspection unchecked
      return (List)cacheQuery.list();
   }
Shadow Man
  • 3,234
  • 1
  • 24
  • 35
  • Note that if your index is local (`indexLocalOnly` parameter set to `true`), then you will need to create a "clustered" query: by replacing the `cacheQuery` line with: `CacheQuery cacheQuery = searchManager.getClusteredQuery( luceneQuery, AuthToken.class );` – Shadow Man May 30 '13 at 17:45
0

I've found: https://community.jboss.org/message/807112#807112 I hope, it could be possibly helpful for you as well.

tsykora
  • 723
  • 1
  • 8
  • 19
  • Unfortunately, no, that didn't help. I tried to create the cache programmatically like he did, but had too many class loader issues and I'm not sure how to find out which modules are being included that are causing the issues. – Shadow Man May 22 '13 at 23:31