Please help. It's many days i try to configure an elasticsearch indexation in my Spring Boot application, certainly i missed something in the documentation but i dont find what.
I am relatively new with spring, days from days i found it very powerful, and it is my first very long problem.
Description of the problem I have a simple object Book indexed with a @FullTextField on my own analyzer
@Entity
@Indexed
@Data
public class Book {
@Id
@GeneratedValue
private Long id;
@FullTextField(analyzer = "my_analyze_french")
private String name;
With my config
package com.mycompany.jpa.elasticsearch;
import org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurationContext;
import org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurer;
// https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#getting-started-analysis
public class CVAnalysisConfigurer implements ElasticsearchAnalysisConfigurer {
@Override
public void configure(ElasticsearchAnalysisConfigurationContext context) {
System.out.println("DEFINE a NEW ANALYZER");
// define each analyzer + associated token filter parameters
context.analyzer("my_analyze_french").custom()
.tokenizer("standard")
.tokenFilters("lowercase", "snowball_french", "asciifolding"); // warning order
// stemmer for french : regroup words by family
context.tokenFilter("snowball_french")
.type("snowball")
.param("language", "French");
System.out.println("DEFINE a NEW ANALYZER:DONE");
}
}
In my application.properties
i indicate the name of the bean to configure my analyzer
# cf https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#backend-elasticsearch-analysis
hibernate.search.backend.analysis.configurer=class:com.mycompany.jpa.elasticsearch.CVAnalysisConfigurer
When i start my application i have the error
2021-06-21 11:37:05.685 ERROR 17135 --- [port thread - 1] o.h.s.e.r.spi.RootFailureCollector : HSEARCH000521: Hibernate Search encountered a failure during bootstrap; continuing for now to list all problems, but the process will ultimately be aborted.
Context: Hibernate ORM mapping, type 'com.mycompany.jpa.elasticsearch.Book'
Failure:
org.hibernate.search.util.common.SearchException: HSEARCH400007: Elasticsearch request failed: HSEARCH400090: Elasticsearch response indicates a failure.
Request: PUT /book-000001 with parameters {}
Response: 400 'Bad Request' from 'http://localhost:9200' with body
{
"error": {
"root_cause": [
{
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: analyzer [my_analyze_french] has not been configured in mappings"
}
],
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: analyzer [my_analyze_french] has not been configured in mappings",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "analyzer [my_analyze_french] has not been configured in mappings"
}
},
"status": 400
}
at org.hibernate.search.backend.elasticsearch.work.impl.AbstractNonBulkableWork.handleResult(AbstractNonBulkableWork.java:84) ~[hibernate-search-backend-elasticsearch-6.0.4.Final.jar:6.0.4.Final]
at org.hibernate.search.backend.elasticsearch.work.impl.AbstractNonBulkableWork.lambda$execute$3(AbstractNonBulkableWork.java:66) ~[hibernate-search-backend-elasticsearch-6.0.4.Final.jar:6.0.4.Final]
at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:642) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2073) ~[na:na]
at org.hibernate.search.backend.elasticsearch.client.impl.ElasticsearchClientImpl$1.onFailure(ElasticsearchClientImpl.java:127) ~[hibernate-search-backend-elasticsearch-6.0.4.Final.jar:6.0.4.Final]
at org.elasticsearch.client.RestClient$FailureTrackingResponseListener.onDefinitiveFailure(RestClient.java:644) ~[elasticsearch-rest-client-7.13.2.jar:7.13.2]
at org.elasticsearch.client.RestClient$1.completed(RestClient.java:386) ~[elasticsearch-rest-client-7.13.2.jar:7.13.2]
at org.elasticsearch.client.RestClient$1.completed(RestClient.java:370) ~[elasticsearch-rest-client-7.13.2.jar:7.13.2]
at org.apache.http.concurrent.BasicFuture.completed(BasicFuture.java:122) ~[httpcore-4.4.14.jar:4.4.14]
at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.responseCompleted(DefaultClientExchangeHandlerImpl.java:181) ~[httpasyncclient-4.1.4.jar:4.1.4]
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.processResponse(HttpAsyncRequestExecutor.java:448) ~[httpcore-nio-4.4.14.jar:4.4.14]
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.inputReady(HttpAsyncRequestExecutor.java:338) ~[httpcore-nio-4.4.14.jar:4.4.14]
at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:265) ~[httpcore-nio-4.4.14.jar:4.4.14]
at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:81) ~[httpasyncclient-4.1.4.jar:4.1.4]
at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:39) ~[httpasyncclient-4.1.4.jar:4.1.4]
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:114) ~[httpcore-nio-4.4.14.jar:4.4.14]
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162) ~[httpcore-nio-4.4.14.jar:4.4.14]
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337) ~[httpcore-nio-4.4.14.jar:4.4.14]
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315) ~[httpcore-nio-4.4.14.jar:4.4.14]
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276) ~[httpcore-nio-4.4.14.jar:4.4.14]
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104) ~[httpcore-nio-4.4.14.jar:4.4.14]
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591) ~[httpcore-nio-4.4.14.jar:4.4.14]
at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
Caused by: org.hibernate.search.util.common.SearchException: HSEARCH400090: Elasticsearch response indicates a failure.
at org.hibernate.search.backend.elasticsearch.work.impl.DefaultElasticsearchRequestSuccessAssessor.checkSuccess(DefaultElasticsearchRequestSuccessAssessor.java:103) ~[hibernate-search-backend-elasticsearch-6.0.4.Final.jar:6.0.4.Final]
at org.hibernate.search.backend.elasticsearch.work.impl.DefaultElasticsearchRequestSuccessAssessor.checkSuccess(DefaultElasticsearchRequestSuccessAssessor.java:86) ~[hibernate-search-backend-elasticsearch-6.0.4.Final.jar:6.0.4.Final]
at org.hibernate.search.backend.elasticsearch.work.impl.AbstractNonBulkableWork.handleResult(AbstractNonBulkableWork.java:79) ~[hibernate-search-backend-elasticsearch-6.0.4.Final.jar:6.0.4.Final]
... 23 common frames omitted
2021-06-21 11:37:05.741 ERROR 17135 --- [ main] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.search.util.common.SearchException: HSEARCH000520: Hibernate Search encountered failures during bootstrap. Failures:
Hibernate ORM mapping:
type 'com.mycompany.jpa.elasticsearch.Book':
failures:
- HSEARCH400007: Elasticsearch request failed: HSEARCH400090: Elasticsearch response indicates a failure.
Request: PUT /book-000001 with parameters {}
Response: 400 'Bad Request' from 'http://localhost:9200' with body
{
"error": {
"root_cause": [
{
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: analyzer [my_analyze_french] has not been configured in mappings"
}
],
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: analyzer [my_analyze_french] has not been configured in mappings",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "analyzer [my_analyze_french] has not been configured in mappings"
}
},
"status": 400
}
2021-06-21 11:37:05.742 WARN 17135 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.search.util.common.SearchException: HSEARCH000520: Hibernate Search encountered failures during bootstrap. Failures:
Hibernate ORM mapping:
type 'com.mycompany.jpa.elasticsearch.Book':
failures:
- HSEARCH400007: Elasticsearch request failed: HSEARCH400090: Elasticsearch response indicates a failure.
Request: PUT /book-000001 with parameters {}
Response: 400 'Bad Request' from 'http://localhost:9200' with body
{
"error": {
"root_cause": [
{
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: analyzer [my_analyze_french] has not been configured in mappings"
}
],
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: analyzer [my_analyze_french] has not been configured in mappings",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "analyzer [my_analyze_french] has not been configured in mappings"
}
},
"status": 400
}
2021-06-21 11:37:05.743 INFO 17135 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2021-06-21 11:37:05.758 INFO 17135 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
2021-06-21 11:37:05.761 INFO 17135 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
My config I use spring Boot 2.3.11, my database if h2
Main dependencies are
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- for use of elastic search, automatic indexation with jpa -->
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-orm</artifactId>
<version>6.0.4.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-backend-elasticsearch</artifactId>
<version>6.0.4.Final</version>
</dependency>
I specify the version of elastic search
<properties>
<elasticsearch.version>7.13.2</elasticsearch.version>
</properties>
Version of my server is the same, i use a simple docker to test, and i delete nodes from the volume before each launch
version: '3'
services:
elasticsearchstudy:
image: docker.elastic.co/elasticsearch/elasticsearch:7.13.2
container_name: elasticsearchstudy
environment:
- "discovery.type=single-node"
volumes:
- ./elasticsearch:/usr/share/elasticsearch/data:rw
ports:
- 9200:9200
restart: unless-stopped
What i tried ? To avoid some possible problems with Spring Boot i tried to deferred the bootstrapping, but with or without it it change nothing
@SpringBootApplication
@EnableJpaRepositories(bootstrapMode = BootstrapMode.DEFERRED)
public class HibernateSearchStudy {
I tried to configure my analysis with the REST API on Postman, it is ok to analyse a document when i work on a new index created with the REST API localhost:9200/book/_analyze
but impossible to do it on my application index Book-000001 (i can't modify the analyzer of a previous created index)
Firstly i tried to do all that in a @DataJpaTest
but as it was not working (same errors), i try to test it now in a CommandLineRunner that insert data in my repo, and after that i do a search
I think my ElasticsearchAnalysisConfigurer
initialisation is never called (the trace i put in configure
never appear). How doing it ?
Any help would be greatly appreciated !!
application.properties
is a Spring Boot configuration file, not a Hibernate Search configuration file. You cannot just dump Hibernate Search properties in there.
Instead, prefix your Hibernate Search properties with spring.jpa.properties.
, so that Spring Boot passes along the properties to Hibernate ORM, which will pass them along to Hibernate Search. For example:
# cf https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#backend-elasticsearch-analysis
spring.jpa.properties.hibernate.search.backend.analysis.configurer=class:com.mycompany.jpa.elasticsearch.CVAnalysisConfigurer
EDIT: See also the section dedicated to Spring Boot in the Hibernate Search reference documentation.