Open JorgenRingen opened 5 years ago
@JorgenRingen the contract with Spring Boot always has been that the cache infrastructure is available before the JPA entity manager kicks in. The main reasoning behind that is that if you don't do this and you use second level cache, Hibernate will attempt to initialize a cache manager and create a duplicate.
Several things:
I don't see how we could support both use case and having the cache infrastructure initialized by the time hibernate starts (if you're using that) makes sense to me. Can't you defer the registration of the MapStore
rather than doing it from the get go?
Okey, I see we should've avoided the cycle in the first place.
Are there any preferable way of deferring the registration? As a first draft I'm doing a "lazy-lookup" from the ApplicationContext on the first call on FooRepository from FooMapStore, but it feels a bit awkward :-)
public class FooMapStore implements MapStore<Long, Foo> {
@Autowired
private ApplicationContext applicationContext;
private FooRepository fooRepository;
@Override
public void store(Long key, Foo value) {
fooRepository().findAll();
}
...
private FooRepository fooRepository() {
if (this.fooRepository == null) {
this.fooRepository = applicationContext.getBean(FooRepository.class);
}
return fooRepository;
}
Thanks for the feedback. That's not really what I have in mind. I was more thinking about retrieving the HazelcastInstance
later and alter its configuration to register an extra store. Is that a use case that Hazelcast supports?
I thought about registering the MapStore in a BeanPostProcessor, but according to com.hazelcast.config.Config [Config instances] should not be modified after they are used to create HazelcastInstance
.
The creation of the HazelcastInstance bean instantiates it (return Hazelcast.getOrCreateHazelcastInstance(config);
) so a BeanPostProcessor is too late. I could also add FooRepository to FooMapStore in a BeanPostProcessor but I think that just adds another layer of confusion compared to looking it up from the ApplicationContext.
@JorgenRingen that's not what this issue indicates. I've tried and got another Hazelcast problem that I don't really understand:
Caused by: com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable serializer for class com.example.cachemanagercurrentlyincreationerror.FooMapStore
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.serializerFor(AbstractSerializationService.java:491) ~[hazelcast-3.9.4.jar:3.9.4]
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.writeObject(AbstractSerializationService.java:254) ~[hazelcast-3.9.4.jar:3.9.4]
... 44 common frames omitted
I've submitted a PR to your repro project.
Interesting. This error only occurs when the mapstore is added in the postconstruct. As far as I understand hazelcast does some kind of broadcasting of the config if the config is updated after initialisation and thats what causing the serialization issue. From stacktrace:
Caused by: com.hazelcast.nio.serialization.HazelcastSerializationException: Failed to serialize 'com.hazelcast.config.MapConfig'
at com.hazelcast.internal.serialization.impl.SerializationUtil.handleSerializeException(SerializationUtil.java:75) ~[hazelcast-3.9.4.jar:3.9.4]
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toBytes(AbstractSerializationService.java:161) ~[hazelcast-3.9.4.jar:3.9.4]
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toBytes(AbstractSerializationService.java:137) ~[hazelcast-3.9.4.jar:3.9.4]
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toData(AbstractSerializationService.java:122) ~[hazelcast-3.9.4.jar:3.9.4]
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toData(AbstractSerializationService.java:110) ~[hazelcast-3.9.4.jar:3.9.4]
at com.hazelcast.internal.dynamicconfig.ClusterWideConfigurationService.cloneConfig(ClusterWideConfigurationService.java:227) ~[hazelcast-3.9.4.jar:3.9.4]
at com.hazelcast.internal.dynamicconfig.ClusterWideConfigurationService.broadcastConfigAsync(ClusterWideConfigurationService.java:219) ~[hazelcast-3.9.4.jar:3.9.4]
at com.hazelcast.internal.dynamicconfig.ClusterWideConfigurationService.broadcastConfig(ClusterWideConfigurationService.java:199) ~[hazelcast-3.9.4.jar:3.9.4]
Notice "broadcastConfigurationAsync".
I'll try to experiment with the deferred registration in the application where the problem originally occurred a bit later. My example-app is over-simplified with regards to hazelcast in order to show the circular reference problem. Might have to do some additional configuration somewhere in order to do updates of the hazelcast-config after hazelcast initialization.
please re-check this issue is not a duplicate with same root cause as this one - https://github.com/spring-projects/spring-boot/issues/4960 by try to exclude - HazelcastJpaDependencyAutoConfiguration on your spring boot application
@lukass77 the issue is open and we'd like to make sure this works without any modification on your end. So, no, it's not a duplicate.
I have a similar issue. I want to initialize the Hazelcast Config with one setting from my database, which then I'm hit with the cyclical issue.
Any updates on this? I'm facing a similar issue
Issue after upgrading from version 2.0.4 to 2.0.5+.
Startup fails with:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'cacheManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
I'm instantiating a HazelcastInstance bean manually and instantiation relies upon a org.springframework.data.jpa.repository.JpaRepository bean. This causes a circular reference on the cacheManager bean during initialisation.
I've debugged the dependency graph and it looks like this: entityManagerFactory -> cacheManager -> JCacheCacheConfiguration -> hazelcastPropertiesCustomizer -> hazelcastInstance -> config -> fooMapStore -> fooRepository -> (inner bean)#hash -> entityManagerFactory -> cacheManager
Sample application: https://github.com/JorgenRingen/spring-boot-error-cachemanager-currently-in-creation
Any suggestions for workarounds?