I'm working on a Spring Boot 2.4.1 project using spring-boot-data-jpa and hazelcast. I'm trying to set up a distributed map with a read through to a database. I've implemented com.hazelcast.map.MapLoader
, but when I try to run the application it fails to start because of a circular dependency. It seems the JpaRepository needs the HazelcastInstance to be available first, but the HazelcastInstance needs the MapLoader which in turn needs the JpaRepository to be ready. At least that's what it looks like from the logs and this post.
Does anybody know how to fix this issue?
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-all</artifactId>
<version>4.1.1</version>
</dependency>
Config:
@Configuration
public class HZConfig {
@Bean
Config config(RVOLoader rvoLoader) {}
Config config = new Config();
config.getMapConfig("rvoMap").getMapStoreConfig().setImplementation(rvoLoader);
config.getMapConfig("rvoMap").getMapStoreConfig()
.setInitialLoadMode(MapStoreConfig.InitialLoadMode.EAGER);
return config;
}
@Bean
HazelcastInstance hazelcastInstance(Config config) {
HazelcastInstance hz = Hazelcast.newHazelcastInstance(config);
return hz;
}
}
MapLoader:
@Component
public class MyResourceMapLoader implements MapLoader<Long, MyResource> {
private final MyResourceRepository repo;
public MyResourceMapLoader(MyResourceRepository repo) {
this.repo = repo;
}
@Override
public MyResource load(Long key) {
return this.repo.findById(key).orElse(null);
}
@Override
public Map<Long, MyResource> loadAll(Collection<Long> keys) {
Map<Long, MyResource> myResourceMap = new HashMap<>();
for (Long key : keys) {
MyResource myResource = this.load(key);
if (myResource != null) {
myResourceMap.put(key, myResource);
}
}
return myResourceMap;
}
@Override
public Iterable<Long> loadAllKeys() {
return this.repo.findAllIds();
}
}
JpaRepository:
@Repository
public interface MyResourceRepository extends JpaRepository<MyResource, Long> {
List<MyResource> findAll();
@Query("SELECT m.id from MyResource m")
Iterable<Long> findAllIds();
}