Question abount Hibernate Search FailureHandler (HS 6)

As stated in the documentation (https://docs.jboss.org/hibernate/search/6.0/reference/en-US/html_single/#mapper-orm-indexing-automatic-synchronization > Exclamation mark state failure handler), not invoked FailureHandler method but exception raised when indexing failed with write-sync setting (automatic_indexing.synchronization.strategy)

In this circumstance,
When indexing failed for the reason such as elasticsearch server down, time out etc,
i want to invoke implemented FailureHandler with write-sync setting (automatic_indexing.synchronization.strategy).
Because it is easy to recovery failed indexing data using FailureHandler(especially EntityIndexingFailureContext argument handle method).

Is there any way to solve?

Yes. Use a custom strategy: https://docs.jboss.org/hibernate/search/6.0/reference/en-US/html_single/#_custom_strategy

Something like this should work:

package com.mycompany;

import ...;

public final class MyWriteSyncAutomaticIndexingSynchronizationStrategy
		implements AutomaticIndexingSynchronizationStrategy {

	public static final MyWriteSyncAutomaticIndexingSynchronizationStrategy INSTANCE = new MyWriteSyncAutomaticIndexingSynchronizationStrategy();

	private MyWriteSyncAutomaticIndexingSynchronizationStrategy() {
	}

	@Override
	public void apply(AutomaticIndexingSynchronizationConfigurationContext context) {
		context.documentCommitStrategy( DocumentCommitStrategy.FORCE );
		context.documentRefreshStrategy( DocumentRefreshStrategy.NONE );
		FailureHandler failureHandler = context.failureHandler();
		context.indexingFutureHandler( future -> {
			// Wait for the result of indexing, so that we're sure changes were committed (or failed).
			SearchIndexingPlanExecutionReport report = future.join();
			report.throwable().ifPresent( t -> {
				EntityIndexingFailureContext.Builder contextBuilder = EntityIndexingFailureContext.builder();
				contextBuilder.throwable( throwable );
				contextBuilder.failingOperation( "automatic indexing" );
				for ( EntityReference entityReference : result.failingEntities() ) {
					contextBuilder.entityReference( entityReference );
				}
				failureHandler.handle( contextBuilder.build() );
			} );
		} );
	}
}

Make sure you’re using version 6.0.0.CR2.

Then set configuration property hibernate.search.automatic_indexing.synchronization.strategy to constructor:com.mycompany.MyWriteSyncAutomaticIndexingSynchronizationStrategy.

1 Like

Thanks your explanation.

And i intent to use EntityManager code in FailureHandler (bean registered) like below

@Component(value = "myFailureHandler")
public class MyFailureHandler implements FailureHandler {
   ...
   @PersistenceContext
   private EntityManager entityManager;
   ...
}

In this case, there are some issues,

  1. When background_failure_handler declared start with bean:,
    error occured like this
    org.hibernate.search.util.common.SearchException: HSEARCH000501: Invalid value for configuration property ‘hibernate.search.background_failure_handler’: ‘bean:myFailureHandler’. HSEARCH000579: Unable to resolve bean reference to type ‘org.hibernate.search.engine.reporting.FailureHandler’ and name ‘myFailureHandler’. Failed to resolve bean from bean manager with exception: HSEARCH000590: No configured bean manager.

  2. When background_failure_handler declared start with class: or constructor:,
    EntityManager dependency injection in MyFailureHandler not effected, so that is null

In this situation, Is there a good way the hibernate search provides?

There is no built-in solution for what you’re trying to achieve, no.

Regarding the injection of an entity manager into the failure handler, that’s probably not a good idea, since the failure handler is instantiated while the entity manager factory is being built, so it can’t be used at this time.

If you really want to do something like this, you will have to implement a dedicated Spring component that performs whatever you want to do with the entity manager, and inject that service into your failure handler with @Lazy @Autowired. See https://www.baeldung.com/spring-lazy-annotation

I have the same condition here however i am trying to inject hazelcast instance so as to cache failing entities to try index them later; Can you please give us more details about how we could achieve this?