Indexing issue while committing: log error instead of throwing exception?

Hi there,
we encounter rare cases where indexing fails while committing a Hibernate session e.g. due to lazy initialization issues. As I consider a inconsistent full text index more acceptable than abort/rollback the whole transaction, is there a best practice approach to e.g. log full text indexing issues only, but then to proceed with the db commit?

Thanks in advance!
Best regards,
Niko

Hello,

Short answer: it’s possible, but clearly not trivial.

That would require to re-implement a small part of Hibernate Search, namely the worker. Fortunately there’s an SPI for that: implement org.hibernate.search.backend.spi.Worker, and tell Hibernate Search to use your implementation by setting hibernate.search.worker.scope to the fully qualified name of your implementation class. See the documentation.

Implementing your own worker may be complex, because the worker is global to Hibernate Search and has to defer the execution of indexing works to the end of a transaction. You could get some inspiration from the default implementation, org.hibernate.search.backend.impl.PerTransactionWorker, but be careful about copying the code since it relies in part on Hibernate Search internals which may change at any moment. In the end, what you would want is the same implementation except PerTransactionWorker#createTransactionWorkQueueSynchronization would return a subclass of org.hibernate.search.backend.impl.PostTransactionWorkQueueSynchronization that swallows exceptions in PostTransactionWorkQueueSynchronization#beforeCompletion and does not perform the works in PostTransactionWorkQueueSynchronization#afterCompletion if beforeCompletion failed.

Note: SPIs have a weaker guarantee than APIs, we may break them without warning between minor versions of Hibernate Search (between 5.10 and 5.11 for instance). We generally try to keep the same features available, but source code compatibility may be lost.

That being said… It seems reasonable to think others will have the same need as you. I added a ticket about just that: https://hibernate.atlassian.net/browse/HSEARCH-3109 . We will see if we can implement a setting in a future version.

Thank you for the quick response. I will dig into the code and see what I can do to satisfy my requirements, but of course having an official handle for this would be great.

Hi @nikowitt ,

Could you tell us more about your lazy initialization issues? Because they shouldn’t happen in the first place.

@gsmet
You are right, these issues should not happen in the first place. Currently, this happes during a larger entity import where the persistence context might be cleared in between, I have to figure out what happens here as debugging this is really tricky (it only does not work in one specific application which a specific set of data - the import works fine in three of our test applications). In the current situation, the import cannot be finished at all, even though it is fully acceptable to have an inconsistent full text index here.

Basically, I just want to have some safety net as I want to ensure that the user can continue his work at the cost of an inconsistent full text index.

In addition, what also could be improved is stack traces like this: (at least in Hibernate Search 5.3, we’re migrating to 5.9 soon)

Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session
	at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165)
	at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286)
	at org.hibernate.search.hcore.util.impl.HibernateHelper.unproxy(HibernateHelper.java:45)
	at org.hibernate.search.engine.impl.HibernateStatelessInitializer.unproxy(HibernateStatelessInitializer.java:39)
	at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.unproxy(DocumentBuilderIndexedEntity.java:795)
	at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.buildDocumentFieldsForProperties(DocumentBuilderIndexedEntity.java:605)
	at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.buildDocumentFields(DocumentBuilderIndexedEntity.java:463)
	at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.buildDocumentFieldsForEmbeddedObjects(DocumentBuilderIndexedEntity.java:533)
	at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.buildDocumentFields(DocumentBuilderIndexedEntity.java:479)
	at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.getDocument(DocumentBuilderIndexedEntity.java:395)
	at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.createUpdateWork(DocumentBuilderIndexedEntity.java:312)
	at org.hibernate.search.engine.spi.DocumentBuilderIndexedEntity.addWorkToQueue(DocumentBuilderIndexedEntity.java:253)
	at org.hibernate.search.engine.impl.WorkPlan$PerEntityWork.enqueueLuceneWork(WorkPlan.java:518)
	at org.hibernate.search.engine.impl.WorkPlan$PerClassWork.enqueueLuceneWork(WorkPlan.java:280)
	at org.hibernate.search.engine.impl.WorkPlan.getPlannedLuceneWork(WorkPlan.java:152)
	at org.hibernate.search.backend.impl.WorkQueue.prepareWorkPlan(WorkQueue.java:114)
	at org.hibernate.search.backend.impl.BatchedQueueingProcessor.prepareWorks(BatchedQueueingProcessor.java:55)
	at org.hibernate.search.backend.impl.PostTransactionWorkQueueSynchronization.beforeCompletion(PostTransactionWorkQueueSynchronization.java:74)
	at org.hibernate.search.backend.impl.EventSourceTransactionContext$DelegateToSynchronizationOnBeforeTx.doBeforeTransactionCompletion(EventSourceTransactionContext.java:174)
	... 75 more

It is not possible to tell from this trace where the root cause is, neither the entity nor the property. Maybe there is a way to improve this as well to at least provide the entity name, id and the property fails during the indexing process?

Probably something that would make life much easier is this:
https://hibernate.atlassian.net/browse/HHH-12484

I asked the question because I know we fixed quite a lot of lazy initialization issues back in the days but it was far before 5.3 so the issues shouldn’t affect you.

I suspect there’s something wrong in the way you handle your session. It would be interesting to get to the bottom of it.

Feel free to ping us with more info when you have them.

About your ORM issue, I would say it’s a perfect thing to start contributing ;).

Well, in this particular version we’re still on Hibernate 4.3… I’m already working on the migration to 5.2.

I am sure in this old codebase, there is something wrong with the session handling :slight_smile: In this code, it was started e.g. to execute many session.updates() as the concept of dirty checking has not been understood correctly. There was also manual session handling like openSession instead of using getCurrentSession()… Probably it will just work in the updated code base that removed all the strange session stuff, but still we have to deal with product applications running on the old version.

Regarding the improved logging: you’re right, pull request is in preparation :slight_smile:

OK, so I can confirm we had a few lazy loading issues back in the days. They are now all fixed so if you migrate to more modern versions, you should be all set.

IIRC, the last lazy loading issues were fixed during the 4.x era so upgrading to Search 5.9.x should solve these issues for you.

If you still encounter them in a modern version please open an issue with a test case.