Search code examples
javaspring-datahazelcast

spring-data-hazelcast @Query annotation gives NullPointerException


https://github.com/hazelcast/spring-data-hazelcast library used in SpringBootTest retrieves list succesfully when findAll() used as below.

@Override
public List<Store> getStores() {
    return storeRepository.findAll();
}

However when @Query annotation used as below it gives NullPointerException.

@Override
public List<Store> (String cityId, String countryId) {
    return storeRepository.getStores(cityId,countryId);
}

StoreRepository

public interface StoreRepository extends HazelcastRepository<Store,String> {

    @Query("cityId=%s and countryId=%s")
    public List<Store> getStores(String cityId, String countryId);

}

Exception is below.

java.lang.NullPointerException: Retrieving a map instance with a null name is not allowed!

    at com.hazelcast.util.Preconditions.checkNotNull(Preconditions.java:59)
    at com.hazelcast.instance.HazelcastInstanceImpl.getMap(HazelcastInstanceImpl.java:183)
    at com.hazelcast.instance.HazelcastInstanceProxy.getMap(HazelcastInstanceProxy.java:99)
    at org.springframework.data.hazelcast.repository.support.StringBasedHazelcastRepositoryQuery.getMap(StringBasedHazelcastRepositoryQuery.java:68)
    at org.springframework.data.hazelcast.repository.support.StringBasedHazelcastRepositoryQuery.execute(StringBasedHazelcastRepositoryQuery.java:48)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:605)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$invoke$3(RepositoryFactorySupport.java:595)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:595)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)

Is a property missing? If that is the case, why does it work with findAll() ?


Solution

  • Default findAll() method calls Spring Data in SimpleKeyValueRepository instance and it consumes KeyValueTemplate(this instance has HazelcastKeyValueAdapter) findAll() method.

    So, @Query annoted queries Hazelcast Spring data implementation's HazelcastQueryMethod.class looks for @KeySpace annotation with value. StringBasedHazelcastRepositoryQuery.class getMap method calls hazelcastInstance's getMap method with that keySpace's value which is map key.

    In short, you need to add @KeySpace("yourMapName") annotation to your Store class.


    Extra information; when you don't put @KeySpace("yourMapName") over your class, it will store with exact package name like com.yourpackage.model.Store.