How to prevent running AfterSaveCallback on save on certain conditions (say AfterSaveCallback<Foo>)
. We would like to avoid triggering AfterSaveCallback
even when its present and registered. How to achieve this?
Refer https://docs.spring.io/spring-data/elasticsearch/docs/4.0.1.RELEASE/api/index.html?org/springframework/data/elasticsearch/core/event/AfterSaveCallback.html
AFAIK, Spring Data does not provide such functionality out-of-the-box, but you can probably achieve the desired behavior by implementing it on your own.
The AfterSaveCallback
callback is invoked by the method maybeCallbackAfterSave
defined in AbstractElasticsearchTemplate
:
protected <T> T maybeCallbackAfterSave(T entity, IndexCoordinates index) {
if (entityCallbacks != null) {
return entityCallbacks.callback(AfterSaveCallback.class, entity, index);
}
return entity;
}
The idea is to provide a custom implementation for this method by extending ElasticsearchRestTemplate
. For instance:
public class CustomElasticsearchRestTemplate extends ElasticsearchRestTemplate {
public CustomElasticsearchRestTemplate(RestHighLevelClient client) {
super(client);
}
public CustomElasticsearchRestTemplate(RestHighLevelClient client, ElasticsearchConverter elasticsearchConverter) {
super(client, elasticsearchConverter);
}
@Override
protected <T> T maybeCallbackAfterSave(T entity, IndexCoordinates index) {
// compute as necessary
boolean shouldSkipCallback = ...;
// if the conditions are met for the callback not to be applied,
// just return the entity
if (shouldSkipCallback) {
return entity;
}
// else, proceed with the default implementation
return super.maybeCallbackAfterSave(entity);
}
}
Depending on the use case an anonymous class that overwrites maybeCallbackAfterSave
will be suitable as well.
Then, use this custom ElasticsearchRestTemplate
on its own or register it as the application default in the way you consider appropriate, for example, by extending AbstractElasticsearchConfiguration
- see this great article - or by providing your own configuration directly - see this for an example.
The solution has a drawback, which is dealing with the generic T entity
argument. For that purpose it may be of help and we can take as reference the code defined in DefaultEntityCallbacks
defined for the callback processing, especially this lines:
Class<T> entityType = (Class<T>) (entity != null ? ClassUtils.getUserClass(entity.getClass())
: callbackDiscoverer.resolveDeclaredEntityType(callbackType).getRawClass());
As you can see they use the functionality implemented in ClassUtils
in order to detect the actual class type.
Maybe you can take advantage of this knowledge and do something similar to the following code to determine if the callback should be or not applied:
// Determine the class using one Spring magic
Class<T> entityType = (Class<T>)
ClassUtils.getUserClass(entity.getClass());
// Then, compare with the appropriate types that should be excluded
boolean shouldSkipCallback = entityType.isAssignableFrom(Foo.class);
As an alternative, you can provide the class of the parameterized type T
information to your AfterSaveCallback<T>
implementation: this will allow you to determine whether the callback should or not applied based on the concrete class upon the onAfterSave
method invocation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With