Inject SpringManagedContext into Hazelcast configuration
This commit makes it possible to inject Spring managed beans into objects instantiated by Hazelcast. See gh-28801
This commit is contained in:
committed by
Stephane Nicoll
parent
6d55b687f7
commit
b875b55711
@@ -25,8 +25,12 @@ import com.hazelcast.config.YamlConfigBuilder;
|
|||||||
import com.hazelcast.core.Hazelcast;
|
import com.hazelcast.core.Hazelcast;
|
||||||
import com.hazelcast.core.HazelcastInstance;
|
import com.hazelcast.core.HazelcastInstance;
|
||||||
|
|
||||||
|
import com.hazelcast.spring.context.SpringManagedContext;
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Conditional;
|
import org.springframework.context.annotation.Conditional;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -60,10 +64,14 @@ class HazelcastServerConfiguration {
|
|||||||
static class HazelcastServerConfigFileConfiguration {
|
static class HazelcastServerConfigFileConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
HazelcastInstance hazelcastInstance(HazelcastProperties properties, ResourceLoader resourceLoader)
|
HazelcastInstance hazelcastInstance(HazelcastProperties properties, ResourceLoader resourceLoader,
|
||||||
|
ObjectProvider<ConfigurationCustomizer> customizerProvider)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
Resource configLocation = properties.resolveConfigLocation();
|
Resource configLocation = properties.resolveConfigLocation();
|
||||||
Config config = (configLocation != null) ? loadConfig(configLocation) : Config.load();
|
Config config = (configLocation != null) ? loadConfig(configLocation) : Config.load();
|
||||||
|
customizerProvider.ifAvailable(c -> {
|
||||||
|
c.customize(config);
|
||||||
|
});
|
||||||
config.setClassLoader(resourceLoader.getClassLoader());
|
config.setClassLoader(resourceLoader.getClassLoader());
|
||||||
return getHazelcastInstance(config);
|
return getHazelcastInstance(config);
|
||||||
}
|
}
|
||||||
@@ -93,7 +101,6 @@ class HazelcastServerConfiguration {
|
|||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@ConditionalOnSingleCandidate(Config.class)
|
@ConditionalOnSingleCandidate(Config.class)
|
||||||
static class HazelcastServerConfigConfiguration {
|
static class HazelcastServerConfigConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
HazelcastInstance hazelcastInstance(Config config) {
|
HazelcastInstance hazelcastInstance(Config config) {
|
||||||
return getHazelcastInstance(config);
|
return getHazelcastInstance(config);
|
||||||
@@ -101,6 +108,29 @@ class HazelcastServerConfiguration {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
private interface ConfigurationCustomizer {
|
||||||
|
void customize(Config configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnClass(name = "com.hazelcast.spring.context.SpringManagedContext")
|
||||||
|
static class HazelcastConfigCustomizerConfiguration {
|
||||||
|
private final ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
public HazelcastConfigCustomizerConfiguration(ApplicationContext applicationContext) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ConfigurationCustomizer springManagedContextConfigurationCustomizer() {
|
||||||
|
return configuration -> {
|
||||||
|
SpringManagedContext springManagedContext = new SpringManagedContext(applicationContext);
|
||||||
|
configuration.setManagedContext(springManagedContext);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link HazelcastConfigResourceCondition} that checks if the
|
* {@link HazelcastConfigResourceCondition} that checks if the
|
||||||
* {@code spring.hazelcast.config} configuration key is defined.
|
* {@code spring.hazelcast.config} configuration key is defined.
|
||||||
|
|||||||
@@ -22,14 +22,21 @@ import com.hazelcast.config.Config;
|
|||||||
import com.hazelcast.config.QueueConfig;
|
import com.hazelcast.config.QueueConfig;
|
||||||
import com.hazelcast.core.Hazelcast;
|
import com.hazelcast.core.Hazelcast;
|
||||||
import com.hazelcast.core.HazelcastInstance;
|
import com.hazelcast.core.HazelcastInstance;
|
||||||
|
import com.hazelcast.map.EntryProcessor;
|
||||||
|
import com.hazelcast.map.IMap;
|
||||||
|
import com.hazelcast.spring.context.SpringAware;
|
||||||
|
import com.hazelcast.spring.context.SpringManagedContext;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanCreationException;
|
import org.springframework.beans.factory.BeanCreationException;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
|
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||||
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||||
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
@@ -164,6 +171,55 @@ class HazelcastAutoConfigurationServerTests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void defaultConfigFile_injectManagedContext() {
|
||||||
|
this.contextRunner.run((context) -> {
|
||||||
|
HazelcastInstance hz = context.getBean(HazelcastInstance.class);
|
||||||
|
IMap<Integer, Integer> map = hz.getMap("myMap");
|
||||||
|
boolean contextInjected = map.executeOnKey(42, new SpringAwareEntryProcessor<>());
|
||||||
|
assertThat(contextInjected).isEqualTo(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void defaultConfigFile_injectManagedContext_SpringHazelcastModuleNotAvailable() {
|
||||||
|
this.contextRunner
|
||||||
|
.withClassLoader(new FilteredClassLoader(SpringManagedContext.class))
|
||||||
|
.run((context) -> {
|
||||||
|
HazelcastInstance hz = context.getBean(HazelcastInstance.class);
|
||||||
|
IMap<Integer, Integer> map = hz.getMap("myMap");
|
||||||
|
boolean contextInjected = map.executeOnKey(42, new SpringAwareEntryProcessor<>());
|
||||||
|
assertThat(contextInjected).isEqualTo(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void explicitConfigFile_injectManagedContext() {
|
||||||
|
this.contextRunner
|
||||||
|
.withSystemProperties(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY
|
||||||
|
+ "=classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.yaml")
|
||||||
|
.run((context) -> {
|
||||||
|
HazelcastInstance hz = context.getBean(HazelcastInstance.class);
|
||||||
|
IMap<Integer, Integer> map = hz.getMap("myMap");
|
||||||
|
boolean contextInjected = map.executeOnKey(42, new SpringAwareEntryProcessor<>());
|
||||||
|
assertThat(contextInjected).isEqualTo(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void explicitConfigFile_injectManagedContext_SpringHazelcastModuleNotAvailable() {
|
||||||
|
this.contextRunner
|
||||||
|
.withClassLoader(new FilteredClassLoader(SpringManagedContext.class))
|
||||||
|
.withSystemProperties(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY
|
||||||
|
+ "=classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.yaml")
|
||||||
|
.run((context) -> {
|
||||||
|
HazelcastInstance hz = context.getBean(HazelcastInstance.class);
|
||||||
|
IMap<Integer, Integer> map = hz.getMap("myMap");
|
||||||
|
boolean contextInjected = map.executeOnKey(42, new SpringAwareEntryProcessor<>());
|
||||||
|
assertThat(contextInjected).isEqualTo(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
static class HazelcastConfigWithName {
|
static class HazelcastConfigWithName {
|
||||||
|
|
||||||
@@ -174,6 +230,17 @@ class HazelcastAutoConfigurationServerTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SpringAware
|
||||||
|
static class SpringAwareEntryProcessor<K, V> implements EntryProcessor<K, V, Boolean> {
|
||||||
|
@Autowired
|
||||||
|
private ApplicationContext context;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean process(Map.Entry<K, V> entry) {
|
||||||
|
return context != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
static class HazelcastConfigNoName {
|
static class HazelcastConfigNoName {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user