diff --git a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/impl/ElasticsearchBackendImpl.java b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/impl/ElasticsearchBackendImpl.java index 28e77e8a3ce..3a49dcfc997 100644 --- a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/impl/ElasticsearchBackendImpl.java +++ b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/impl/ElasticsearchBackendImpl.java @@ -94,6 +94,7 @@ class ElasticsearchBackendImpl implements BackendImplementor, private final ElasticsearchSimpleWorkOrchestrator generalPurposeOrchestrator; private final ElasticsearchIndexFieldTypeFactoryProvider typeFactoryProvider; + private final Gson userFacingGson; private final MultiTenancyStrategy multiTenancyStrategy; private final BeanHolder indexLayoutStrategyHolder; private final TypeNameMapping typeNameMapping; @@ -120,6 +121,7 @@ class ElasticsearchBackendImpl implements BackendImplementor, ); this.multiTenancyStrategy = multiTenancyStrategy; this.typeFactoryProvider = typeFactoryProvider; + this.userFacingGson = userFacingGson; this.indexLayoutStrategyHolder = indexLayoutStrategyHolder; this.typeNameMapping = typeNameMapping; @@ -304,7 +306,7 @@ private IndexSettings customIndexSettings(BackendBuildContext buildContext, throw log.customIndexSettingsFileNotFound( filePath, indexEventContext ); } try ( Reader reader = new InputStreamReader( inputStream, StandardCharsets.UTF_8 ) ) { - return link.getGsonProvider().getGson().fromJson( reader, IndexSettings.class ); + return userFacingGson.fromJson( reader, IndexSettings.class ); } } catch (IOException e) { @@ -329,7 +331,7 @@ private RootTypeMapping customIndexMappings(BackendBuildContext buildContext, throw log.customIndexMappingFileNotFound( filePath, indexEventContext ); } try ( Reader reader = new InputStreamReader( inputStream, StandardCharsets.UTF_8 ) ) { - return link.getGsonProvider().getGson().fromJson( reader, RootTypeMapping.class ); + return userFacingGson.fromJson( reader, RootTypeMapping.class ); } } catch (IOException e) { diff --git a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/impl/ElasticsearchLinkImpl.java b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/impl/ElasticsearchLinkImpl.java index 7baca3dd639..6c6d136899c 100644 --- a/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/impl/ElasticsearchLinkImpl.java +++ b/backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/impl/ElasticsearchLinkImpl.java @@ -161,7 +161,7 @@ void onStop() { private void checkStarted() { if ( clientImplementor == null ) { throw new AssertionFailure( - "Attempt to retrieve Elasticsearch client or related information before the backend was started." + "Attempt to retrieve Elasticsearch client or related information before the Elasticsearch client was started." ); } } diff --git a/integrationtest/backend/elasticsearch/src/test/java/org/hibernate/search/integrationtest/backend/elasticsearch/bootstrap/ElasticsearchBootstrapIT.java b/integrationtest/backend/elasticsearch/src/test/java/org/hibernate/search/integrationtest/backend/elasticsearch/bootstrap/ElasticsearchBootstrapIT.java index e9720897c80..67725157de8 100644 --- a/integrationtest/backend/elasticsearch/src/test/java/org/hibernate/search/integrationtest/backend/elasticsearch/bootstrap/ElasticsearchBootstrapIT.java +++ b/integrationtest/backend/elasticsearch/src/test/java/org/hibernate/search/integrationtest/backend/elasticsearch/bootstrap/ElasticsearchBootstrapIT.java @@ -9,12 +9,14 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.hibernate.search.util.impl.integrationtest.common.assertion.SearchResultAssert.assertThatQuery; +import static org.hibernate.search.util.impl.test.JsonHelper.assertJsonEqualsIgnoringUnknownFields; import java.util.HashMap; import java.util.Map; import org.hibernate.search.backend.elasticsearch.ElasticsearchVersion; import org.hibernate.search.backend.elasticsearch.cfg.ElasticsearchBackendSettings; +import org.hibernate.search.backend.elasticsearch.cfg.ElasticsearchIndexSettings; import org.hibernate.search.backend.elasticsearch.cfg.spi.ElasticsearchBackendSpiSettings; import org.hibernate.search.backend.elasticsearch.client.spi.ElasticsearchRequest; import org.hibernate.search.engine.cfg.BackendSettings; @@ -25,6 +27,7 @@ import org.hibernate.search.integrationtest.backend.tck.testsupport.util.rule.SearchSetupHelper; import org.hibernate.search.util.common.SearchException; import org.hibernate.search.util.impl.integrationtest.backend.elasticsearch.dialect.ElasticsearchTestDialect; +import org.hibernate.search.util.impl.integrationtest.backend.elasticsearch.rule.TestElasticsearchClient; import org.hibernate.search.util.impl.integrationtest.common.FailureReportUtils; import org.hibernate.search.util.impl.integrationtest.mapper.stub.StubMappedIndex; import org.hibernate.search.util.impl.integrationtest.mapper.stub.StubMappingSchemaManagementStrategy; @@ -42,6 +45,9 @@ public class ElasticsearchBootstrapIT { @Rule public ElasticsearchClientSpy elasticsearchClientSpy = new ElasticsearchClientSpy(); + @Rule + public TestElasticsearchClient elasticsearchClient = new TestElasticsearchClient(); + private final StubMappedIndex index = StubMappedIndex.withoutFields(); /** @@ -270,6 +276,49 @@ public void noVersionCheck_versionOverrideOnStart_compatibleVersion() { assertThat( elasticsearchClientSpy.getRequestCount() ).isNotZero(); } + /** + * Check custom settings/mapping can be parsed when version_check.enabled is false, + * meaning the elasticsearch link is only established *after* + * the custom settings/mapping are parsed. + */ + @Test + @TestForIssue(jiraKey = {"HSEARCH-4435"}) + public void noVersionCheck_customSettingsAndMapping() { + ElasticsearchVersion actualVersion = ElasticsearchTestDialect.getActualVersion(); + String versionWithMajorAndMinorOnly = actualVersion.distribution() + ":" + + actualVersion.major() + "." + actualVersion.minor().getAsInt(); + + SearchSetupHelper.PartialSetup partialSetup = setupHelper.start() + .withBackendProperty( ElasticsearchBackendSettings.VERSION, versionWithMajorAndMinorOnly ) + .withBackendProperty( ElasticsearchBackendSpiSettings.CLIENT_FACTORY, + elasticsearchClientSpy.factoryReference() ) + .withBackendProperty( ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_SETTINGS_FILE, + "bootstrap-it/custom-settings.json" ) + .withBackendProperty( ElasticsearchIndexSettings.SCHEMA_MANAGEMENT_MAPPING_FILE, + "bootstrap-it/custom-mapping.json" ) + .withSchemaManagement( StubMappingSchemaManagementStrategy.DROP_ON_SHUTDOWN_ONLY ) + .withIndex( index ) + .setupFirstPhaseOnly(); + // We do not expect the client to be created in the first phase + assertThat( elasticsearchClientSpy.getCreatedClientCount() ).isZero(); + + Map runtimeProperties = new HashMap<>(); + runtimeProperties.put( BackendSettings.backendKey( ElasticsearchBackendSettings.VERSION_CHECK_ENABLED ), false ); + partialSetup.doSecondPhase( AllAwareConfigurationPropertySource.fromMap( runtimeProperties ) ); + checkBackendWorks(); + + assertThat( elasticsearchClient.index( index.name() ).settings( "index.number_of_replicas" ).get() ) + .isEqualTo( "\"42\"" ); + assertJsonEqualsIgnoringUnknownFields( + "{" + + "'properties': {" + + "'custom': {" + + "}" + + "}" + + "}", + elasticsearchClient.index( index.name() ).type().getMapping() ); + } + private void checkBackendWorks() { index.schemaManager().createIfMissing().join(); assertThatQuery( index.query().where( f -> f.matchAll() ) ).hasNoHits(); diff --git a/integrationtest/backend/elasticsearch/src/test/resources/bootstrap-it/custom-mapping.json b/integrationtest/backend/elasticsearch/src/test/resources/bootstrap-it/custom-mapping.json new file mode 100644 index 00000000000..5ab294aec1a --- /dev/null +++ b/integrationtest/backend/elasticsearch/src/test/resources/bootstrap-it/custom-mapping.json @@ -0,0 +1,7 @@ +{ + "properties":{ + "custom":{ + "type":"keyword" + } + } +} \ No newline at end of file diff --git a/integrationtest/backend/elasticsearch/src/test/resources/bootstrap-it/custom-settings.json b/integrationtest/backend/elasticsearch/src/test/resources/bootstrap-it/custom-settings.json new file mode 100644 index 00000000000..258c9af0977 --- /dev/null +++ b/integrationtest/backend/elasticsearch/src/test/resources/bootstrap-it/custom-settings.json @@ -0,0 +1,3 @@ +{ + "number_of_replicas": "42" +} \ No newline at end of file