RE: Indexer for my custom entity doesn't trigger automatically

thumbnail
Eric COQUELIN, modified 6 Years ago. Expert Posts: 254 Join Date: 11/3/13 Recent Posts
Dear Community,
I am using Liferay 7.1 CE GA4.
I have one custom entity to which I associated an indexer (BaseIndexer<T>) and it works very well. No issue so far.
Then, I have another service builder module in the same Liferay workspace where I have another entity I wish I could have another indexer associated to it. But it doesn't trigger automatically when adding or deleting.
For both entities I have similar characteristics. From the indexer perspective, the code is nearly the same. But the second doesn't work.
When I go to the control panel, I can see my two custom entities in the search entry. And I can run reindex on both without any issue.
If at least I had an exception somewhere I may have a clue where the issue is but nothing displays. Even if I raise search/index logs.
In the documentation, Liferay says they switched to "composition instead of inheritance" thus I tried "composition" but same happens. I have added the annoation @Indexable(...) but it doesn't change anything (that annotation is not added to my other entity for which that works !)
What could block the propagation of the indexation when adding/updating/deleting each entity ?
Thank you in advance for your help,
thumbnail
David H Nebinger, modified 6 Years ago. Liferay Legend Posts: 14933 Join Date: 9/2/06 Recent Posts
Just curious, how do you know that it is not updating automatically?
thumbnail
Eric COQUELIN, modified 6 Years ago. Expert Posts: 254 Join Date: 11/3/13 Recent Posts
Because the index is not populated with the new data.
I check Elasticsearch (REMOTE) using Kibana.
If I run the bulk index (search -> entity -> reindex), it works perfectly.
I am currently reverse engeenering the code... This is where I am but I need to check that it is called because there is no log
public class IndexableAdvice
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; extends AnnotationChainableMethodAdvice<indexable> {
</indexable>
...
}
thumbnail
Eric COQUELIN, modified 6 Years ago. Expert Posts: 254 Join Date: 11/3/13 Recent Posts
THis is where it fails
protected T findAnnotation(MethodInvocation methodInvocation) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;T annotation = serviceBeanAopCacheManager.findAnnotation(
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;methodInvocation, _annotationClass, _nullAnnotation);
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (annotation == _nullAnnotation) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;serviceBeanAopCacheManager.removeMethodInterceptor(
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;methodInvocation, this);
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}

&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return annotation;
&nbsp;&nbsp; &nbsp;}
Because the variable annotation is null, the interceptor is removed and data not  indexed. But I don't understand why the cache is empty. This is a service builder project, no specific modifications have been performed.
thumbnail
Eric COQUELIN, modified 6 Years ago. Expert Posts: 254 Join Date: 11/3/13 Recent Posts
Dear Community,
After spending hours on this topic I found out a solution without understanding why it works in some cases but not in some others.
As per the document, it says that we should add the following annotation to index
@Indexable(type = IndexableType.REINDEX)
But as the code generated, it appears that when you build a cutom entity, Liferay generates for you some classes and the parent one includes already this annotation
@Indexable(type = IndexableType.REINDEX)
&nbsp;&nbsp; &nbsp;@Override
&nbsp;&nbsp; &nbsp;public Place addPlace(Place place) {
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;place.setNew(true);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return placePersistence.update(place);
&nbsp;&nbsp; &nbsp;}
As a result, if I call this method from my local Service, it should work because it calls an inherited method
place = this.addPlace(place);
By the way same works perfectly for my first entity but on my second I had to add annotation on my local services to make it work. And I finally found out that if I call
place = placeLocalService.addPlace(place)
instead of
place = this.addPlace(place);
It works...
I wish I could have clear explanations. Moreover when the same works without that trick on my first entity...
thumbnail
David H Nebinger, modified 6 Years ago. Liferay Legend Posts: 14933 Join Date: 9/2/06 Recent Posts
So the addPlace() method generated by Liferay should really be considered kind of an internal method. They weren't really intended to be called externally because, well, it breaks the idea of isolation.


I mean, the external code should not need to know how to get a new primary key value to set to the entity. Nor should it know anything about the create/modified timestamps, etc.


Ideally you're going to define a method like addPlace(final String placeName, final String description,  ..., final ServiceContext serviceContext) in your PlaceLocalServiceImpl class.  This method would be annotated with the @Indexable annotation, and then when you invoke this larger addPlace() method, your entity will be indexed. It is within this method where you set the created/modified timestamps, set the user who created the entity, etc. from the service context, plus you also have the logic to assign the primary key (via the already injected counterLocalService instance that is added to your object precisely to fulfill this requirement). This conforms to the separation of layers because it isolates these internal details related to persisting an entity from the business code that just needs to add a new Place.


The default addPlace() method is not annotated and would not be annotated because it is strictly dealing with the job of adding a new place, it is considered a pretty low-level method. If you wanted to add the annotation, you'd do just like you started, override the addPlace() method, add the annotation, but normally I then just do a "return super.addPlace(place);" sort of line.
thumbnail
Eric COQUELIN, modified 6 Years ago. Expert Posts: 254 Join Date: 11/3/13 Recent Posts
Hi David,
This is already what follow my implementations.
The default addPlace() method is not annotated and would not be annotated because it is strictly dealing with the job of adding a new place

You can check generated code for your projects and you will notice that the addPlace() equivalent has annotation. Thus I still don't understand why indexation is not propagated.
I am running 7.1 CE GA4.