Hello,
I try to implement multi-tenant application using Hibernate Search dynamic sharding (version 4.4.2.Final). I've got expected behaviour when I use lucene backend but if I switch to master/slave JMS it doesn't work.
I would expect my master to be able to update index for many tenants. From slave, message is posted with index name x.y.z.MyClassName.ShardID (seems OK) but on master side AbstractJMSHibernateSearchController can't find matching indexManager.
So, as illustrated with code bellow, I extend
AbstractJMSHibernateSearchController to create indexManagers on startup based on initial shard names provided by
ShardIdentifierProvider. It seems to behave as I expect.
Because of using reflection to get HS private field, I'm not very happy with this solution. Do you see a better way to do it. Is there a built-in solution I've missed ?
Thanks for help.
Code:
@Override
public void afterPropertiesSet() throws Exception {
SearchFactoryImplementor factory = ContextHelper
.getSearchFactory(getSession());
Map<Class<?>, EntityIndexBinding> indexBindings = factory.getIndexBindings();
// iterate over all entityIndexBinding load on start up
for (EntityIndexBinding entityIndexBinding : indexBindings.values()) {
// if binding is dynamic sharding one then get one IndexManager per
// shard (initial ones) in order to create it => they wil exist on
// message consumption
if (entityIndexBinding instanceof DynamicShardingEntityIndexBinding) {
// get inital shards
Set<String> shards = entityIndexBinding.getShardIdentifierProvider().getAllShardIdentifiers();
// get indexBaseName by reflection... beurk
Field field = DynamicShardingEntityIndexBinding.class.getDeclaredField("rootDirectoryProviderName");
field.setAccessible(true);
String indexBaseName = (String) field.get(entityIndexBinding);
// create indexManager for all shards
for (String shard : shards) {
factory.getIndexManagerHolder().getOrCreateIndexManager(
indexBaseName,
shard,
(DynamicShardingEntityIndexBinding) entityIndexBinding);
}
}
}
}