Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

HSEARCH-1268 Make it possible to plug in a custom MassIndexer implementation #380

Closed
wants to merge 4 commits into from

2 participants

@DavideD
Collaborator

https://hibernate.onjira.com/browse/HSEARCH-1268

I have a couple of question. I will ask as inline comments

@DavideD
Collaborator

I don't think I can leave on inline comment on this one because it's about file I didn't change, anyway:

ClassLoaderHelper#classForName is using the contextClassloader before using the one passed as a parameter. Shouldn't be the opposite?

@Sanne
Owner

ClassLoaderHelper#classForName is using the contextClassloader before using the one passed as a parameter. Shouldn't be the opposite?

Order is not important, it only has a performance impact as it might try the correct one first, avoiding one reource access.
We expect most things to be found on the contextClassLoader as that's where the user resources are (like lists of stopwords, custom analyzers, any other extension)

...e/search/hcore/impl/MassIndexerFactoryIntegrator.java
((48 lines not shown))
+
+ public static final String MASS_INDEXER_FACTORY_CLASS_PROP = "hibernate.search.indexer.factory";
+
+ @Override
+ public Class<MassIndexerFactory> getServiceInitiated() {
+ return MassIndexerFactory.class;
+ }
+
+ @Override
+ public MassIndexerFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
+ String factoryClassName = (String) configurationValues.get( MASS_INDEXER_FACTORY_CLASS_PROP );
+ return factoryClassName == null ? DEFAULT_FACTORY : createFactory( factoryClassName );
+ }
+
+ private MassIndexerFactory createFactory(String factoryClassName) {
+ return ClassLoaderHelper.instanceFromName( MassIndexerFactory.class, factoryClassName, getClass()
@Sanne Owner
Sanne added a note

did you check if ORM isn't providing you the classloader as a Service?

 getClass().getClassLoader()

If we still use this code, then the fix in the previous commit isn't as useful as I thought it would be.

@DavideD Collaborator
DavideD added a note

I didn't check.

I will take a look at it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@DavideD
Collaborator

ClassLoaderHelper#classForName is using the contextClassloader before using the one passed as a parameter. Shouldn't be the opposite?

Order is not important, it only has a performance impact as it might try the correct one first, avoiding one reource access.
We expect most things to be found on the contextClassLoader as that's where the user resources are (like lists of stopwords, custom analyzers, any other extension)

I'm asking because It's seems a bit awkward that I pass the classloader that I want to use and then another one is used. By the way, I've noticed this writing some unit tests.

@DavideD
Collaborator

Added some documentation and javadoc

@DavideD
Collaborator

Rebased. All the changes should be applied now.

@DavideD
Collaborator

Changed a comment

@Sanne
Owner

merged!

@Sanne Sanne closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
132 hibernate-search-documentation/src/main/docbook/en-US/modules/batchindex.xml
@@ -287,65 +287,99 @@ transaction.commit();</programlisting>
able to find results and the system load might be too high
anyway.</para>
</note>
- </section>
-
- <para>Other parameters which affect indexing time and memory consumption
- are:</para>
-
- <itemizedlist>
- <listitem>
- <literal>hibernate.search.[default|&lt;indexname&gt;].exclusive_index_use</literal>
- </listitem>
-
- <listitem>
- <literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.max_buffered_docs</literal>
- </listitem>
- <listitem>
- <literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.max_merge_docs</literal>
- </listitem>
+ <section id="search-batchindex-custommassindexer">
+ <title>Custom</title>
+ <para>It is possible to use a custom implementation of the <classname>MassIndexer</classname> instead of using the one shipped with Hibernate Search.
+ The steps to follow are:</para>
- <listitem>
- <literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.merge_factor</literal>
- </listitem>
+ <orderedlist>
+ <listitem>
+ <para>create an implementation of the <classname>org.hibernate.search.spi.MassIndexerFactory</classname> interface;</para>
+ </listitem>
+ <listitem>
+ <para>set the property <code>hibernate.search.massindexer.factoryclass</code> with the qualified class name of the factory implementation.</para>
+ </listitem>
+ </orderedlist>
- <listitem>
- <literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.merge_min_size</literal>
- </listitem>
+ <example>
+ <title>Custom <code>MassIndexerFactory</code> example</title>
+ <programlisting language="JAVA" role="JAVA">package org.myproject
- <listitem>
- <literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.merge_max_size</literal>
- </listitem>
+import org.hibernate.search.spi.MassIndexerFactory
- <listitem>
- <literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.merge_max_optimize_size</literal>
- </listitem>
+...
- <listitem>
- <literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.merge_calibrate_by_deletes</literal>
- </listitem>
+public class CustomIndexerFactory implements MassIndexerFactory {
- <listitem>
- <literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.ram_buffer_size</literal>
- </listitem>
+ public void initialize(Properties properties) {
+ }
- <listitem>
- <literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.term_index_interval</literal>
- </listitem>
- </itemizedlist>
+ public MassIndexer createMassIndexer(...) {
+ return new CustomIndexer();
+ }
- <para>Previous versions also had a <literal>max_field_length</literal> but
- this was removed from Lucene, it's possible to obtain a similar effect by
- using a <classname>LimitTokenCountAnalyzer</classname>.</para>
+} </programlisting>
+ </example>
- <para>All <literal>.indexwriter</literal> parameters are Lucene specific
- and Hibernate Search is just passing these parameters through - see <xref
- linkend="lucene-indexing-performance"/> for more details.</para>
+ <example>
+ <title>Set the factory class name in a properties file</title>
+ <programlisting>hibernate.search.massindexer.factoryclass = org.myproject.CustomIndexerFactory</programlisting>
+ </example>
+ </section>
+ </section>
- <para>The <classname>MassIndexer</classname> uses a forward only
- scrollable result to iterate on the primary keys to be loaded, but MySQL's
- JDBC driver will load all values in memory; to avoid this "optimisation"
- set <literal>idFetchSize</literal> to
- <literal>Integer.MIN_VALUE</literal>.</para>
+ <section>
+ <title>Useful parameters for batch indexing</title>
+ <para>Other parameters which affect indexing time and memory consumption
+ are:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>hibernate.search.[default|&lt;indexname&gt;].exclusive_index_use</literal></para>
+ </listitem>
+ <listitem>
+ <para><literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.max_buffered_docs</literal></para>
+ </listitem>
+ <listitem>
+ <para><literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.max_merge_docs</literal></para>
+ </listitem>
+ <listitem>
+ <para><literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.merge_factor</literal></para>
+ </listitem>
+ <listitem>
+ <para><literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.merge_min_size</literal></para>
+ </listitem>
+ <listitem>
+ <para><literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.merge_max_size</literal></para>
+ </listitem>
+ <listitem>
+ <para><literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.merge_max_optimize_size</literal></para>
+ </listitem>
+ <listitem>
+ <para><literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.merge_calibrate_by_deletes</literal></para>
+ </listitem>
+ <listitem>
+ <para><literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.ram_buffer_size</literal></para>
+ </listitem>
+ <listitem>
+ <para><literal>hibernate.search.[default|&lt;indexname&gt;].indexwriter.term_index_interval</literal></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Previous versions also had a <literal>max_field_length</literal> but
+ this was removed from Lucene, it's possible to obtain a similar effect by
+ using a <classname>LimitTokenCountAnalyzer</classname>.</para>
+
+ <para>All <literal>.indexwriter</literal> parameters are Lucene specific
+ and Hibernate Search is just passing these parameters through - see <xref
+ linkend="lucene-indexing-performance"/> for more details.</para>
+
+ <para>The <classname>MassIndexer</classname> uses a forward only
+ scrollable result to iterate on the primary keys to be loaded, but MySQL's
+ JDBC driver will load all values in memory; to avoid this "optimisation"
+ set <literal>idFetchSize</literal> to
+ <literal>Integer.MIN_VALUE</literal>.</para>
+ </section>
</section>
</chapter>
View
32 hibernate-search-engine/src/main/java/org/hibernate/search/util/impl/ClassLoaderHelper.java
@@ -100,11 +100,39 @@ private static void getResources(String resourceName, ClassLoader cl, Set<URL> u
* @return a new instance of classNameToLoad
* @throws SearchException wrapping other error types with a proper error message for all kind of problems, like
* classNotFound, missing proper constructor, wrong type, security errors.
+ *
+ * @deprecated Use {@link ClassLoaderHelper#instanceFromName(Class, String, ClassLoader, String)} instead
*/
+ @Deprecated
public static <T> T instanceFromName(Class<T> targetSuperType, String classNameToLoad,
Class<?> caller, String componentDescription) {
- final Class<?> clazzDef;
- clazzDef = classForName( classNameToLoad, caller.getClassLoader(), componentDescription );
+ return instanceFromName( targetSuperType, classNameToLoad, caller.getClassLoader(), componentDescription );
+ }
+
+ /**
+ * Creates an instance of a target class specified by the fully qualified class name using a {@link ClassLoader}
+ * as fallback when the class cannot be found in the context one.
+ *
+ * @param <T>
+ * matches the type of targetSuperType: defines the return type
+ * @param targetSuperType
+ * the return type of the function, the classNameToLoad will be checked
+ * to be assignable to this type.
+ * @param classNameToLoad
+ * a fully qualified class name, whose type is assignable to targetSuperType
+ * @param fallbackClassLoader
+ * the ClassLoader used when the class cannot be found in the context one
+ * @param componentDescription
+ * a meaningful description of the role the instance will have,
+ * used to enrich error messages to describe the context of the error
+ * @return a new instance of classNameToLoad
+ * @throws SearchException
+ * wrapping other error types with a proper error message for all kind of problems, like
+ * classNotFound, missing proper constructor, wrong type, security errors.
+ */
+ public static <T> T instanceFromName(Class<T> targetSuperType, String classNameToLoad, ClassLoader fallbackClassLoader,
+ String componentDescription) {
+ final Class<?> clazzDef = classForName( classNameToLoad, fallbackClassLoader, componentDescription );
return instanceFromClass( targetSuperType, clazzDef, componentDescription );
}
View
104 hibernate-search-orm/src/main/java/org/hibernate/search/hcore/impl/MassIndexerFactoryIntegrator.java
@@ -0,0 +1,104 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @authors tag. All rights reserved.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+package org.hibernate.search.hcore.impl;
+
+import java.util.Map;
+import java.util.Properties;
+
+import org.hibernate.cfg.Configuration;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.integrator.spi.ServiceContributingIntegrator;
+import org.hibernate.metamodel.source.MetadataImplementor;
+import org.hibernate.search.impl.DefaultMassIndexerFactory;
+import org.hibernate.search.spi.MassIndexerFactory;
+import org.hibernate.search.util.impl.ClassLoaderHelper;
+import org.hibernate.service.ServiceRegistryBuilder;
+import org.hibernate.service.spi.BasicServiceInitiator;
+import org.hibernate.service.spi.ServiceRegistryImplementor;
+import org.hibernate.service.spi.SessionFactoryServiceRegistry;
+
+/**
+ * Registers a {@link MassIndexerFactory} in the {@link org.hibernate.service.ServiceRegistry}.
+ * <p>
+ * The type of the factory can be specified in the configuration otherwise a defaul one is used.
+ *
+ * @author Davide D'Alto <davide@hibernate.org>
+ */
+public class MassIndexerFactoryIntegrator implements ServiceContributingIntegrator,
+ BasicServiceInitiator<MassIndexerFactory> {
+
+ private static final DefaultMassIndexerFactory DEFAULT_FACTORY = new DefaultMassIndexerFactory();
+
+ public static final String MASS_INDEXER_FACTORY_CLASSNAME = "hibernate.search.massindexer.factoryclass";
+
+ @Override
+ public Class<MassIndexerFactory> getServiceInitiated() {
+ return MassIndexerFactory.class;
+ }
+
+ @Override
+ public MassIndexerFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
+ String factoryClassName = (String) configurationValues.get( MASS_INDEXER_FACTORY_CLASSNAME );
+ MassIndexerFactory factory = createFactory( factoryClassName );
+ factory.initialize( properties( configurationValues ) );
+ return factory;
+ }
+
+ private Properties properties(Map configurationValues) {
+ Properties properties = new Properties();
+ properties.putAll( configurationValues );
+ return properties;
+ }
+
+ private MassIndexerFactory createFactory(String factoryClassName) {
+ if ( factoryClassName == null ) {
+ return DEFAULT_FACTORY;
+ }
+ else {
+ return customFactory( factoryClassName );
+ }
+ }
+
+ private MassIndexerFactory customFactory(String factoryClassName) {
+ return ClassLoaderHelper.instanceFromName( MassIndexerFactory.class, factoryClassName, getClass()
+ .getClassLoader(), "Mass indexer factory" );
+ }
+
+ @Override
+ public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory,
+ SessionFactoryServiceRegistry serviceRegistry) {
+ }
+
+ @Override
+ public void integrate(MetadataImplementor metadata, SessionFactoryImplementor sessionFactory,
+ SessionFactoryServiceRegistry serviceRegistry) {
+ }
+
+ @Override
+ public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
+ }
+
+ @Override
+ public void prepareServices(ServiceRegistryBuilder serviceRegistryBuilder) {
+ serviceRegistryBuilder.addInitiator( this );
+ }
+
+}
View
50 hibernate-search-orm/src/main/java/org/hibernate/search/impl/DefaultMassIndexerFactory.java
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @authors tag. All rights reserved.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+package org.hibernate.search.impl;
+
+import java.util.Properties;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.search.MassIndexer;
+import org.hibernate.search.engine.spi.SearchFactoryImplementor;
+import org.hibernate.search.spi.MassIndexerFactory;
+
+/**
+ * The {@link MassIndexer} implementation used when none is specified in the configuration.
+ *
+ * @author Davide D'Alto <davide@hibernate.org>
+ */
+public class DefaultMassIndexerFactory implements MassIndexerFactory {
+
+ private static final Class<?>[] OBJECT_ARRAY = { Object.class };
+
+ @Override
+ public void initialize(Properties properties) {
+ }
+
+ @Override
+ public MassIndexer createMassIndexer(SearchFactoryImplementor searchFactory, SessionFactory sessionFactory,
+ Class<?>... entities) {
+ final Class<?>[] types = entities.length == 0 ? OBJECT_ARRAY : entities;
+ return new MassIndexerImpl( searchFactory, sessionFactory, types );
+ }
+
+}
View
13 hibernate-search-orm/src/main/java/org/hibernate/search/impl/FullTextSessionImpl.java
@@ -81,6 +81,7 @@
import org.hibernate.search.backend.impl.EventSourceTransactionContext;
import org.hibernate.search.engine.spi.SearchFactoryImplementor;
import org.hibernate.search.query.hibernate.impl.FullTextQueryImpl;
+import org.hibernate.search.spi.MassIndexerFactory;
import org.hibernate.search.util.impl.ContextHelper;
import org.hibernate.search.util.impl.HibernateHelper;
import org.hibernate.stat.SessionStatistics;
@@ -205,12 +206,12 @@ public void flushToIndexes() {
}
public MassIndexer createIndexer(Class<?>... types) {
- if ( types.length == 0 ) {
- return new MassIndexerImpl( getSearchFactoryImplementor(), getSessionFactory(), Object.class );
- }
- else {
- return new MassIndexerImpl( getSearchFactoryImplementor(), getSessionFactory(), types );
- }
+ MassIndexerFactory factory = requestService( MassIndexerFactory.class );
+ return factory.createMassIndexer( getSearchFactoryImplementor(), getSessionFactory(), types );
+ }
+
+ private MassIndexerFactory requestService(Class<MassIndexerFactory> serviceRole) {
+ return sessionImplementor.getFactory().getServiceRegistry().getService( serviceRole );
}
public SearchFactory getSearchFactory() {
View
60 hibernate-search-orm/src/main/java/org/hibernate/search/spi/MassIndexerFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @authors tag. All rights reserved.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+package org.hibernate.search.spi;
+
+import java.util.Properties;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.search.MassIndexer;
+import org.hibernate.search.engine.spi.SearchFactoryImplementor;
+import org.hibernate.service.Service;
+
+/**
+ * Contains methods that can be used to create a {@link MassIndexer}.
+ *
+ * @author Davide D'Alto <davide@hibernate.org>
+ * @see Service
+ */
+public interface MassIndexerFactory extends Service {
+
+ /**
+ * Called after the creation of the factory, can be used to read configuration parameters.
+ *
+ * @param properties
+ * configuration properties
+ */
+ void initialize(Properties properties);
+
+ /**
+ * Create an instance of a {@link MassIndexer}.
+ *
+ * @param searchFactory
+ * the Hibernate Search factory
+ * @param sessionFactory
+ * the {@link org.hibernate.Session} factory
+ * @param entities
+ * the classes of the entities that are going to be indexed
+ * @return a new MassIndexer
+ */
+ MassIndexer createMassIndexer(SearchFactoryImplementor searchFactory, SessionFactory sessionFactory,
+ Class<?>... entities);
+
+}
View
3  hibernate-search-orm/src/main/resources/META-INF/services/org.hibernate.integrator.spi.Integrator
@@ -1 +1,2 @@
-org.hibernate.search.hcore.impl.HibernateSearchIntegrator
+org.hibernate.search.hcore.impl.HibernateSearchIntegrator
+org.hibernate.search.hcore.impl.MassIndexerFactoryIntegrator
View
172 hibernate-search-orm/src/test/java/org/hibernate/search/test/CustomMassIndexerFactoryTest.java
@@ -0,0 +1,172 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @authors tag. All rights reserved.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+package org.hibernate.search.test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hibernate.search.hcore.impl.MassIndexerFactoryIntegrator.MASS_INDEXER_FACTORY_CLASSNAME;
+import static org.junit.Assert.assertThat;
+
+import java.util.Properties;
+import java.util.concurrent.Future;
+
+import org.hibernate.CacheMode;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.MassIndexer;
+import org.hibernate.search.Search;
+import org.hibernate.search.batchindexing.MassIndexerProgressMonitor;
+import org.hibernate.search.engine.spi.SearchFactoryImplementor;
+import org.hibernate.search.spi.MassIndexerFactory;
+import org.junit.Test;
+
+/**
+ * @author Davide D'Alto <davide@hibernate.org>
+ */
+public class CustomMassIndexerFactoryTest extends SearchTestCase {
+
+ @Test
+ public void testCreationOfTheSelectedMassIndexer() throws Exception {
+ Session session = openSession();
+ FullTextSession fullTextSession = Search.getFullTextSession( session );
+ MassIndexer indexer = fullTextSession.createIndexer( Clock.class );
+
+ assertThat( indexer, is( NoopMassIndexer.class ) );
+ }
+
+ @Test
+ public void testFactoryCanReadConfiguration() throws Exception {
+ Session session = openSession();
+ FullTextSession fullTextSession = Search.getFullTextSession( session );
+ NoopMassIndexer indexer = (NoopMassIndexer) fullTextSession.createIndexer( Clock.class );
+
+ assertTrue( "The factory cannot read the configuration properties", indexer.isConfigurationReadable() );
+ }
+
+ @Override
+ protected void configure(org.hibernate.cfg.Configuration cfg) {
+ super.configure( cfg );
+ cfg.setProperty( MASS_INDEXER_FACTORY_CLASSNAME, NoopMassIndexerFactory.class.getName() );
+ }
+
+ @Override
+ protected Class<?>[] getAnnotatedClasses() {
+ return new Class[] { Clock.class };
+ }
+
+ @SuppressWarnings("serial")
+ public static class NoopMassIndexerFactory implements MassIndexerFactory {
+
+ private boolean configurationReadable = false;
+
+ @Override
+ public void initialize(Properties properties) {
+ configurationReadable = properties.get( MASS_INDEXER_FACTORY_CLASSNAME ) == NoopMassIndexerFactory.class
+ .getName();
+ }
+
+ @Override
+ public MassIndexer createMassIndexer(SearchFactoryImplementor searchFactory, SessionFactory sessionFactory,
+ Class<?>... entities) {
+ return new NoopMassIndexer( configurationReadable );
+ }
+
+ }
+
+ private static class NoopMassIndexer implements MassIndexer {
+
+ private final boolean configurationReadable;
+
+ public NoopMassIndexer(boolean configurationAccessible) {
+ this.configurationReadable = configurationAccessible;
+ }
+
+ public boolean isConfigurationReadable() {
+ return configurationReadable;
+ }
+
+ @Override
+ public MassIndexer threadsToLoadObjects(int numberOfThreads) {
+ return null;
+ }
+
+ @Override
+ public MassIndexer batchSizeToLoadObjects(int batchSize) {
+ return null;
+ }
+
+ @Override
+ public MassIndexer threadsForSubsequentFetching(int numberOfThreads) {
+ return null;
+ }
+
+ @Override
+ @Deprecated
+ public MassIndexer threadsForIndexWriter(int numberOfThreads) {
+ return null;
+ }
+
+ @Override
+ public MassIndexer progressMonitor(MassIndexerProgressMonitor monitor) {
+ return null;
+ }
+
+ @Override
+ public MassIndexer cacheMode(CacheMode cacheMode) {
+ return null;
+ }
+
+ @Override
+ public MassIndexer optimizeOnFinish(boolean optimize) {
+ return null;
+ }
+
+ @Override
+ public MassIndexer optimizeAfterPurge(boolean optimize) {
+ return null;
+ }
+
+ @Override
+ public MassIndexer purgeAllOnStart(boolean purgeAll) {
+ return null;
+ }
+
+ @Override
+ public MassIndexer limitIndexedObjectsTo(long maximum) {
+ return null;
+ }
+
+ @Override
+ public Future<?> start() {
+ return null;
+ }
+
+ @Override
+ public void startAndWait() throws InterruptedException {
+ }
+
+ @Override
+ public MassIndexer idFetchSize(int idFetchSize) {
+ return null;
+ }
+
+ }
+}
View
12 hibernate-search-orm/src/test/java/org/hibernate/search/test/batchindexing/IndexingGeneratedCorpusTest.java
@@ -23,6 +23,9 @@
*/
package org.hibernate.search.test.batchindexing;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
@@ -42,8 +45,10 @@
import org.hibernate.criterion.Projections;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
+import org.hibernate.search.MassIndexer;
import org.hibernate.search.batchindexing.MassIndexerProgressMonitor;
import org.hibernate.search.engine.spi.SearchFactoryImplementor;
+import org.hibernate.search.impl.MassIndexerImpl;
import org.hibernate.search.indexes.impl.DirectoryBasedIndexManager;
import org.hibernate.search.test.util.FullTextSessionBuilder;
import org.hibernate.search.test.util.textbuilder.SentenceInventor;
@@ -156,6 +161,13 @@ public void testBatchIndexing() throws InterruptedException, IOException {
verifyIndexIsLocked( true, Book.class ); //exclusive index enabled
}
+ @Test
+ public void testCreationOfTheDefaultMassIndexer() throws Exception {
+ FullTextSession fullTextSession = builder.openFullTextSession();
+ MassIndexer indexer = fullTextSession.createIndexer( Object.class );
+ assertThat( indexer, is( MassIndexerImpl.class ) );
+ }
+
private void reindexAll() throws InterruptedException {
FullTextSession fullTextSession = builder.openFullTextSession();
SilentProgressMonitor progressMonitor = new SilentProgressMonitor();
Something went wrong with that request. Please try again.