diff --git a/integrationtest/mapper/orm/src/test/java/org/hibernate/search/integrationtest/mapper/orm/automaticindexing/AutomaticIndexingFilterIT.java b/integrationtest/mapper/orm/src/test/java/org/hibernate/search/integrationtest/mapper/orm/automaticindexing/AutomaticIndexingFilterIT.java index ee166134708..5f57b8c952d 100644 --- a/integrationtest/mapper/orm/src/test/java/org/hibernate/search/integrationtest/mapper/orm/automaticindexing/AutomaticIndexingFilterIT.java +++ b/integrationtest/mapper/orm/src/test/java/org/hibernate/search/integrationtest/mapper/orm/automaticindexing/AutomaticIndexingFilterIT.java @@ -28,6 +28,7 @@ import org.hibernate.search.util.impl.integrationtest.mapper.orm.OrmSetupHelper; import org.hibernate.search.util.impl.integrationtest.mapper.orm.ReusableOrmSetupHolder; +import org.junit.After; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; @@ -62,6 +63,14 @@ public void setup(OrmSetupHelper.SetupContext setupContext) { ); } + @After + public void tearDown() throws Exception { + Search.automaticIndexingFilter( + setupHolder.entityManagerFactory(), + ctx -> { /*clear out any settings from tests*/ } + ); + } + @Test public void directPersistUpdateDelete() { setupHolder.runInTransaction( session -> { @@ -188,6 +197,34 @@ public void sameClassFails() { } ); } + @Test + public void applicationFilterDisableAll() { + Search.automaticIndexingFilter( + setupHolder.entityManagerFactory(), + ctx -> ctx.exclude( EntityA.class ) + ); + setupHolder.runInTransaction( session -> { + session.persist( new EntityA( 1, "test" ) ); + session.persist( new Entity1A( 2, "test" ) ); + session.persist( new Entity1B( 3, "test" ) ); + session.persist( new Entity2A( 4, "test" ) ); + } ); + backendMock.verifyExpectationsMet(); + + setupHolder.runInTransaction( session -> { + Search.session( session ).automaticIndexingFilter( ctx -> ctx.include( Entity2A.class ) ); + + session.persist( new EntityA( 10, "test" ) ); + session.persist( new Entity1A( 20, "test" ) ); + session.persist( new Entity1B( 30, "test" ) ); + session.persist( new Entity2A( 40, "test" ) ); + + backendMock.expectWorks( Entity2A.INDEX ) + .add( "40", b -> b.field( "indexedField", "test" ) ); + } ); + backendMock.verifyExpectationsMet(); + } + @Entity(name = "containing") @Indexed(index = IndexedEntity.INDEX) public static class IndexedEntity { diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/Search.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/Search.java index be1072e91f3..9e158bcb5df 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/Search.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/Search.java @@ -15,12 +15,16 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.query.Query; import org.hibernate.search.engine.search.query.SearchQuery; +import org.hibernate.search.mapper.orm.automaticindexing.filter.impl.HibernateOrmApplicationAutomaticIndexingTypeFilter; import org.hibernate.search.mapper.orm.common.impl.HibernateOrmUtils; import org.hibernate.search.mapper.orm.mapping.SearchMapping; +import org.hibernate.search.mapper.orm.mapping.impl.HibernateOrmMapping; import org.hibernate.search.mapper.orm.mapping.impl.HibernateSearchContextProviderService; import org.hibernate.search.mapper.orm.search.query.impl.HibernateOrmSearchQueryAdapter; import org.hibernate.search.mapper.orm.session.SearchSession; import org.hibernate.search.mapper.orm.session.impl.DelegatingSearchSession; +import org.hibernate.search.mapper.pojo.automaticindexing.filter.PojoAutomaticIndexingTypeFilterConfigurer; +import org.hibernate.search.util.common.annotation.Incubating; public final class Search { @@ -119,7 +123,43 @@ public static Query toOrmQuery(SearchQuery searchQuery) { return HibernateOrmSearchQueryAdapter.create( searchQuery ); } - private static SearchMapping getSearchMapping(SessionFactoryImplementor sessionFactoryImplementor) { + /** + * Set a filter configuration and define which types must be included/excluded from indexing within the current application + * using a Hibernate ORM {@link SessionFactory}. + *

+ * By default, all indexed types are included. + * + * @param sessionFactory A Hibernate ORM session factory. + * @param configurer The configurer that provides access to filter configuration. + */ + @Incubating + public static void automaticIndexingFilter(SessionFactory sessionFactory, + PojoAutomaticIndexingTypeFilterConfigurer configurer) { + HibernateOrmApplicationAutomaticIndexingTypeFilter.configureFilter( + getSearchMapping( HibernateOrmUtils.toSessionFactoryImplementor( sessionFactory ) ), + configurer + ); + } + + /** + * Set a filter configuration and define which types must be included/excluded from indexing within the current application + * using a JPA {@link EntityManagerFactory}. + *

+ * By default, all indexed types are included. + * + * @param entityManagerFactory A JPA entity manager factory. + * @param configurer The configurer that provides access to filter configuration. + */ + @Incubating + public static void automaticIndexingFilter(EntityManagerFactory entityManagerFactory, + PojoAutomaticIndexingTypeFilterConfigurer configurer) { + HibernateOrmApplicationAutomaticIndexingTypeFilter.configureFilter( + getSearchMapping( HibernateOrmUtils.toSessionFactoryImplementor( entityManagerFactory ) ), + configurer + ); + } + + private static HibernateOrmMapping getSearchMapping(SessionFactoryImplementor sessionFactoryImplementor) { HibernateSearchContextProviderService mappingContextProvider = HibernateSearchContextProviderService.get( sessionFactoryImplementor ); return mappingContextProvider.get(); diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/automaticindexing/filter/impl/HibernateOrmApplicationAutomaticIndexingTypeFilter.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/automaticindexing/filter/impl/HibernateOrmApplicationAutomaticIndexingTypeFilter.java new file mode 100644 index 00000000000..8e7e6ccf099 --- /dev/null +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/automaticindexing/filter/impl/HibernateOrmApplicationAutomaticIndexingTypeFilter.java @@ -0,0 +1,33 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.mapper.orm.automaticindexing.filter.impl; + +import org.hibernate.search.mapper.orm.mapping.impl.HibernateOrmMapping; +import org.hibernate.search.mapper.pojo.automaticindexing.filter.PojoAutomaticIndexingTypeFilterConfigurer; +import org.hibernate.search.mapper.pojo.automaticindexing.filter.spi.PojoAutomaticIndexingTypeFilterHolder; + +public final class HibernateOrmApplicationAutomaticIndexingTypeFilter { + + private static final PojoAutomaticIndexingTypeFilterHolder INDEXING_TYPE_FILTER_HOLDER = new PojoAutomaticIndexingTypeFilterHolder(); + private static final PojoAutomaticIndexingTypeFilterHolder INCLUDE_ALL_INDEXING_TYPE_FILTER_HOLDER = new PojoAutomaticIndexingTypeFilterHolder(); + + private HibernateOrmApplicationAutomaticIndexingTypeFilter() { + } + + public static void configureFilter(HibernateOrmMapping mapping, + PojoAutomaticIndexingTypeFilterConfigurer configurer) { + + HibernateOrmAutomaticIndexingTypeFilterContext context = new HibernateOrmAutomaticIndexingTypeFilterContext( + mapping.typeContextProvider() ); + configurer.configure( context ); + INDEXING_TYPE_FILTER_HOLDER.filter( context.createFilter( INCLUDE_ALL_INDEXING_TYPE_FILTER_HOLDER ) ); + } + + public static PojoAutomaticIndexingTypeFilterHolder applicationFilter() { + return INDEXING_TYPE_FILTER_HOLDER; + } +} diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/automaticindexing/filter/impl/HibernateOrmAutomaticIndexingTypeFilter.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/automaticindexing/filter/impl/HibernateOrmAutomaticIndexingTypeFilter.java index b488e130ead..98fbd712d28 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/automaticindexing/filter/impl/HibernateOrmAutomaticIndexingTypeFilter.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/automaticindexing/filter/impl/HibernateOrmAutomaticIndexingTypeFilter.java @@ -9,15 +9,17 @@ import java.util.Set; import org.hibernate.search.mapper.pojo.automaticindexing.filter.spi.PojoAutomaticIndexingTypeFilter; +import org.hibernate.search.mapper.pojo.automaticindexing.filter.spi.PojoAutomaticIndexingTypeFilterHolder; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; public class HibernateOrmAutomaticIndexingTypeFilter implements PojoAutomaticIndexingTypeFilter { - private final PojoAutomaticIndexingTypeFilter fallback; + private final PojoAutomaticIndexingTypeFilterHolder fallback; private final Set> includes; private final Set> excludes; - public HibernateOrmAutomaticIndexingTypeFilter(PojoAutomaticIndexingTypeFilter fallback, Set> includes, + public HibernateOrmAutomaticIndexingTypeFilter(PojoAutomaticIndexingTypeFilterHolder fallback, + Set> includes, Set> excludes) { this.fallback = fallback; this.includes = includes; @@ -34,6 +36,6 @@ public boolean isIncluded(PojoRawTypeIdentifier typeIdentifier) { return true; } - return fallback.isIncluded( typeIdentifier ); + return fallback.filter().isIncluded( typeIdentifier ); } } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/automaticindexing/filter/impl/HibernateOrmAutomaticIndexingTypeFilterContext.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/automaticindexing/filter/impl/HibernateOrmAutomaticIndexingTypeFilterContext.java index 0eb36abbacc..22e1583123e 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/automaticindexing/filter/impl/HibernateOrmAutomaticIndexingTypeFilterContext.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/automaticindexing/filter/impl/HibernateOrmAutomaticIndexingTypeFilterContext.java @@ -14,7 +14,7 @@ import org.hibernate.search.mapper.orm.session.impl.HibernateOrmSessionTypeContextProvider; import org.hibernate.search.mapper.pojo.automaticindexing.filter.PojoAutomaticIndexingTypeFilterContext; -import org.hibernate.search.mapper.pojo.automaticindexing.filter.spi.PojoAutomaticIndexingTypeFilter; +import org.hibernate.search.mapper.pojo.automaticindexing.filter.spi.PojoAutomaticIndexingTypeFilterHolder; import org.hibernate.search.mapper.pojo.logging.impl.Log; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; import org.hibernate.search.mapper.pojo.model.spi.PojoTypeContext; @@ -74,7 +74,7 @@ public PojoAutomaticIndexingTypeFilterContext exclude(Class clazz) { } - public HibernateOrmAutomaticIndexingTypeFilter createFilter(PojoAutomaticIndexingTypeFilter fallback) { + public HibernateOrmAutomaticIndexingTypeFilter createFilter(PojoAutomaticIndexingTypeFilterHolder fallback) { Set> allIncludes = new HashSet<>(); Set> allExcludes = new HashSet<>(); diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/SearchSession.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/SearchSession.java index d9c8512cf24..1f7518545fc 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/SearchSession.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/SearchSession.java @@ -14,6 +14,7 @@ import javax.persistence.EntityManager; import org.hibernate.Session; +import org.hibernate.SessionFactory; import org.hibernate.search.engine.search.query.dsl.SearchQuerySelectStep; import org.hibernate.search.mapper.pojo.automaticindexing.filter.PojoAutomaticIndexingTypeFilterConfigurer; import org.hibernate.search.mapper.orm.common.EntityReference; @@ -249,7 +250,8 @@ default SearchScope scope(Class expectedSuperType, String entityName) /** * Set a filter configuration and define which types must be included/excluded from indexing within the current session. - * By default, all indexed types are included. + * If the type is not explicitly included/excluded directly or as a supertype the decision will be made by + * {@link org.hibernate.search.mapper.orm.Search#automaticIndexingFilter(SessionFactory, PojoAutomaticIndexingTypeFilterConfigurer) an application filter}. * * @param configurer The configurer that provides access to filter configuration. */ diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSession.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSession.java index c25fdf334b3..dd922b3de61 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSession.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSession.java @@ -22,6 +22,7 @@ import org.hibernate.search.engine.backend.common.DocumentReference; import org.hibernate.search.engine.backend.common.spi.DocumentReferenceConverter; import org.hibernate.search.engine.search.query.dsl.SearchQuerySelectStep; +import org.hibernate.search.mapper.orm.automaticindexing.filter.impl.HibernateOrmApplicationAutomaticIndexingTypeFilter; import org.hibernate.search.mapper.orm.automaticindexing.filter.impl.HibernateOrmAutomaticIndexingTypeFilterContext; import org.hibernate.search.mapper.orm.automaticindexing.session.impl.DelegatingAutomaticIndexingSynchronizationStrategy; import org.hibernate.search.mapper.orm.automaticindexing.spi.AutomaticIndexingEventSendingSessionContext; @@ -43,7 +44,6 @@ import org.hibernate.search.mapper.orm.work.impl.SearchIndexingPlanImpl; import org.hibernate.search.mapper.orm.work.impl.SearchIndexingPlanSessionContext; import org.hibernate.search.mapper.pojo.automaticindexing.filter.PojoAutomaticIndexingTypeFilterConfigurer; -import org.hibernate.search.mapper.pojo.automaticindexing.filter.spi.PojoAutomaticIndexingTypeFilter; import org.hibernate.search.mapper.pojo.automaticindexing.filter.spi.PojoAutomaticIndexingTypeFilterHolder; import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingContext; import org.hibernate.search.mapper.pojo.model.spi.PojoRuntimeIntrospector; @@ -212,7 +212,9 @@ public void indexingPlanSynchronizationStrategy(IndexingPlanSynchronizationStrat public void automaticIndexingFilter(PojoAutomaticIndexingTypeFilterConfigurer configurer) { HibernateOrmAutomaticIndexingTypeFilterContext context = new HibernateOrmAutomaticIndexingTypeFilterContext( typeContextProvider ); configurer.configure( context ); - automaticIndexingStrategy.indexingTypeFilterHolder().filter( context.createFilter( PojoAutomaticIndexingTypeFilter.ACCEPT_ALL ) ); + automaticIndexingStrategy.indexingTypeFilterHolder().filter( context.createFilter( + HibernateOrmApplicationAutomaticIndexingTypeFilter.applicationFilter() + ) ); } @Override diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/automaticindexing/filter/spi/PojoAutomaticIndexingTypeFilterHolder.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/automaticindexing/filter/spi/PojoAutomaticIndexingTypeFilterHolder.java index 4f391db2b5d..499b5edddbe 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/automaticindexing/filter/spi/PojoAutomaticIndexingTypeFilterHolder.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/automaticindexing/filter/spi/PojoAutomaticIndexingTypeFilterHolder.java @@ -9,8 +9,15 @@ import java.util.concurrent.atomic.AtomicReference; public class PojoAutomaticIndexingTypeFilterHolder { - private AtomicReference filter = new AtomicReference<>( - PojoAutomaticIndexingTypeFilter.ACCEPT_ALL ); + private AtomicReference filter = new AtomicReference<>(); + + public PojoAutomaticIndexingTypeFilterHolder() { + this( PojoAutomaticIndexingTypeFilter.ACCEPT_ALL ); + } + + public PojoAutomaticIndexingTypeFilterHolder(PojoAutomaticIndexingTypeFilter filter) { + this.filter.set( filter ); + } public PojoAutomaticIndexingTypeFilter filter() { return filter.get();