Merge pull request #7469 from vpavic:gh-4918

* pr/7469:
  Polish "Add auto-configuration support for Hazelcast client"
  Add auto-configuration support for Hazelcast client
pull/2934/merge
Stephane Nicoll 8 years ago
commit 39a1c5e6ea

@ -75,6 +75,11 @@
<artifactId>hazelcast</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-client</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-spring</artifactId>

@ -16,21 +16,13 @@
package org.springframework.boot.autoconfigure.hazelcast;
import java.io.IOException;
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.context.annotation.Import;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Hazelcast. Creates a
@ -38,59 +30,14 @@ import org.springframework.core.io.Resource;
* configuration file is found in the environment.
*
* @author Stephane Nicoll
* @author Madhura Bhave
* @author Vedran Pavic
* @since 1.3.0
* @see HazelcastConfigResourceCondition
*/
@Configuration
@ConditionalOnClass(HazelcastInstance.class)
@ConditionalOnMissingBean(HazelcastInstance.class)
@EnableConfigurationProperties(HazelcastProperties.class)
@Import({ HazelcastClientConfiguration.class, HazelcastServerConfiguration.class })
public class HazelcastAutoConfiguration {
@Configuration
@ConditionalOnMissingBean(Config.class)
@Conditional(ConfigAvailableCondition.class)
static class HazelcastConfigFileConfiguration {
private final HazelcastProperties hazelcastProperties;
HazelcastConfigFileConfiguration(HazelcastProperties hazelcastProperties) {
this.hazelcastProperties = hazelcastProperties;
}
@Bean
public HazelcastInstance hazelcastInstance() throws IOException {
Resource config = this.hazelcastProperties.resolveConfigLocation();
if (config != null) {
return new HazelcastInstanceFactory(config).getHazelcastInstance();
}
return Hazelcast.newHazelcastInstance();
}
}
@Configuration
@ConditionalOnSingleCandidate(Config.class)
static class HazelcastConfigConfiguration {
@Bean
public HazelcastInstance hazelcastInstance(Config config) {
return new HazelcastInstanceFactory(config).getHazelcastInstance();
}
}
/**
* {@link HazelcastConfigResourceCondition} that checks if the
* {@code spring.hazelcast.config} configuration key is defined.
*/
static class ConfigAvailableCondition extends HazelcastConfigResourceCondition {
ConfigAvailableCondition() {
super("spring.hazelcast.config");
}
}
}

@ -0,0 +1,86 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.hazelcast;
import java.io.IOException;
import com.hazelcast.client.HazelcastClient;
import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.core.HazelcastInstance;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
/**
* Configuration for Hazelcast client.
*
* @author Vedran Pavic
* @author Stephane Nicoll
*/
@ConditionalOnClass(HazelcastClient.class)
@ConditionalOnMissingBean(HazelcastInstance.class)
class HazelcastClientConfiguration {
static final String CONFIG_SYSTEM_PROPERTY = "hazelcast.client.config";
@Configuration
@ConditionalOnMissingBean(ClientConfig.class)
@Conditional(ConfigAvailableCondition.class)
static class HazelcastClientConfigFileConfiguration {
@Bean
public HazelcastInstance hazelcastInstance(HazelcastProperties properties)
throws IOException {
Resource config = properties.resolveConfigLocation();
if (config != null) {
return new HazelcastClientFactory(config).getHazelcastInstance();
}
return HazelcastClient.newHazelcastClient();
}
}
@Configuration
@ConditionalOnSingleCandidate(ClientConfig.class)
static class HazelcastClientConfigConfiguration {
@Bean
public HazelcastInstance hazelcastInstance(ClientConfig config) {
return new HazelcastClientFactory(config).getHazelcastInstance();
}
}
/**
* {@link HazelcastConfigResourceCondition} that checks if the
* {@code spring.hazelcast.config} configuration key is defined.
*/
static class ConfigAvailableCondition extends HazelcastConfigResourceCondition {
ConfigAvailableCondition() {
super(CONFIG_SYSTEM_PROPERTY, "file:./hazelcast-client.xml",
"classpath:/hazelcast-client.xml");
}
}
}

@ -0,0 +1,78 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.hazelcast;
import java.io.IOException;
import java.net.URL;
import com.hazelcast.client.HazelcastClient;
import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.client.config.XmlClientConfigBuilder;
import com.hazelcast.core.HazelcastInstance;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Factory that can be used to create a client {@link HazelcastInstance}.
*
* @author Vedran Pavic
* @since 2.0.0
*/
public class HazelcastClientFactory {
private final ClientConfig clientConfig;
/**
* Create a {@link HazelcastClientFactory} for the specified configuration location.
* @param clientConfigLocation the location of the configuration file
* @throws IOException if the configuration location could not be read
*/
public HazelcastClientFactory(Resource clientConfigLocation) throws IOException {
this.clientConfig = getClientConfig(clientConfigLocation);
}
/**
* Create a {@link HazelcastClientFactory} for the specified configuration.
* @param clientConfig the configuration
*/
public HazelcastClientFactory(ClientConfig clientConfig) {
Assert.notNull(clientConfig, "ClientConfig must not be null");
this.clientConfig = clientConfig;
}
private ClientConfig getClientConfig(Resource clientConfigLocation)
throws IOException {
URL configUrl = clientConfigLocation.getURL();
return new XmlClientConfigBuilder(configUrl).build();
}
/**
* Get the {@link HazelcastInstance}.
* @return the {@link HazelcastInstance}
*/
public HazelcastInstance getHazelcastInstance() {
if (StringUtils.hasText(this.clientConfig.getInstanceName())) {
return HazelcastClient.getHazelcastClientByName(
this.clientConfig.getInstanceName());
}
return HazelcastClient.newHazelcastClient(this.clientConfig);
}
}

@ -21,6 +21,7 @@ import org.springframework.boot.autoconfigure.condition.ResourceCondition;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.Assert;
/**
* {@link SpringBootCondition} used to check if the Hazelcast configuration is available.
@ -29,22 +30,26 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
*
* @author Stephane Nicoll
* @author Madhura Bhave
* @author Vedran Pavic
* @since 1.3.0
*/
public abstract class HazelcastConfigResourceCondition extends ResourceCondition {
static final String CONFIG_SYSTEM_PROPERTY = "hazelcast.config";
private final String configSystemProperty;
protected HazelcastConfigResourceCondition(String property) {
super("Hazelcast", property, "file:./hazelcast.xml", "classpath:/hazelcast.xml");
protected HazelcastConfigResourceCondition(String configSystemProperty,
String... resourceLocations) {
super("Hazelcast", "spring.hazelcast.config", resourceLocations);
Assert.notNull(configSystemProperty, "ConfigSystemProperty must not be null");
this.configSystemProperty = configSystemProperty;
}
@Override
protected ConditionOutcome getResourceOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
if (System.getProperty(CONFIG_SYSTEM_PROPERTY) != null) {
if (System.getProperty(this.configSystemProperty) != null) {
return ConditionOutcome.match(startConditionMessage()
.because("System property '" + CONFIG_SYSTEM_PROPERTY + "' is set."));
.because("System property '" + this.configSystemProperty + "' is set."));
}
return super.getResourceOutcome(context, metadata);
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2015 the original author or authors.
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -38,7 +38,7 @@ import org.springframework.util.StringUtils;
*/
public class HazelcastInstanceFactory {
private Config config;
private final Config config;
/**
* Create a {@link HazelcastInstanceFactory} for the specified configuration location.

@ -0,0 +1,84 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.hazelcast;
import java.io.IOException;
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
/**
* Configuration for Hazelcast server.
*
* @author Stephane Nicoll
* @author Vedran Pavic
*/
@ConditionalOnMissingBean(HazelcastInstance.class)
class HazelcastServerConfiguration {
static final String CONFIG_SYSTEM_PROPERTY = "hazelcast.config";
@Configuration
@ConditionalOnMissingBean(Config.class)
@Conditional(ConfigAvailableCondition.class)
static class HazelcastServerConfigFileConfiguration {
@Bean
public HazelcastInstance hazelcastInstance(HazelcastProperties properties)
throws IOException {
Resource config = properties.resolveConfigLocation();
if (config != null) {
return new HazelcastInstanceFactory(config).getHazelcastInstance();
}
return Hazelcast.newHazelcastInstance();
}
}
@Configuration
@ConditionalOnSingleCandidate(Config.class)
static class HazelcastServerConfigConfiguration {
@Bean
public HazelcastInstance hazelcastInstance(Config config) {
return new HazelcastInstanceFactory(config).getHazelcastInstance();
}
}
/**
* {@link HazelcastConfigResourceCondition} that checks if the
* {@code spring.hazelcast.config} configuration key is defined.
*/
static class ConfigAvailableCondition extends HazelcastConfigResourceCondition {
ConfigAvailableCondition() {
super(CONFIG_SYSTEM_PROPERTY, "file:./hazelcast.xml",
"classpath:/hazelcast.xml");
}
}
}

@ -49,12 +49,15 @@ import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.cache.support.MockCachingProvider;
import org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration;
import org.springframework.boot.junit.runner.classpath.ClassPathExclusions;
import org.springframework.boot.junit.runner.classpath.ModifiedClassPathRunner;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
@ -91,6 +94,8 @@ import static org.mockito.Mockito.verify;
* @author Stephane Nicoll
* @author Eddú Meléndez
*/
@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions("hazelcast-client-*.jar")
public class CacheAutoConfigurationTests {
@Rule

@ -0,0 +1,159 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.hazelcast;
import java.io.IOException;
import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.client.impl.HazelcastClientProxy;
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link HazelcastAutoConfiguration} specific to the client.
*
* @author Vedran Pavic
* @author Stephane Nicoll
*/
public class HazelcastAutoConfigurationClientTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
private AnnotationConfigApplicationContext context;
/**
* Servers the test clients will connect to.
*/
private static HazelcastInstance hazelcastServer;
@BeforeClass
public static void init() {
hazelcastServer = Hazelcast.newHazelcastInstance();
}
@AfterClass
public static void close() {
if (hazelcastServer != null) {
hazelcastServer.shutdown();
}
}
@After
public void closeContext() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void systemProperty() throws IOException {
System.setProperty(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY,
"classpath:org/springframework/boot/autoconfigure/hazelcast/" +
"hazelcast-client-specific.xml");
try {
load();
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class);
assertThat(hazelcastInstance.getName()).startsWith("hz.client_");
}
finally {
System.clearProperty(HazelcastClientConfiguration.CONFIG_SYSTEM_PROPERTY);
}
}
@Test
public void explicitConfigFile() throws IOException {
load("spring.hazelcast.config=org/springframework/boot/autoconfigure/"
+ "hazelcast/hazelcast-client-specific.xml");
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class);
assertThat(hazelcastInstance.getName()).startsWith("hz.client_");
}
@Test
public void explicitConfigUrl() throws IOException {
load("spring.hazelcast.config=hazelcast-client-default.xml");
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class);
assertThat(hazelcastInstance.getName()).startsWith("hz.client_");
}
@Test
public void unknownConfigFile() {
this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("foo/bar/unknown.xml");
load("spring.hazelcast.config=foo/bar/unknown.xml");
}
@Test
public void clientConfigTakesPrecedence() {
load(HazelcastServerAndClientConfig.class, "spring.hazelcast.config=this-is-ignored.xml");
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance).isInstanceOf(HazelcastClientProxy.class);
}
private void load(String... environment) {
load(null, environment);
}
private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
if (config != null) {
applicationContext.register(config);
}
applicationContext.register(HazelcastAutoConfiguration.class);
applicationContext.refresh();
this.context = applicationContext;
}
@Configuration
static class HazelcastServerAndClientConfig {
@Bean
public Config config() {
return new Config();
}
@Bean
public ClientConfig clientConfig() {
return new ClientConfig();
}
}
}

@ -0,0 +1,184 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.hazelcast;
import java.io.IOException;
import java.util.Map;
import com.hazelcast.config.Config;
import com.hazelcast.config.QueueConfig;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.junit.runner.classpath.ClassPathExclusions;
import org.springframework.boot.junit.runner.classpath.ModifiedClassPathRunner;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link HazelcastAutoConfiguration} when the client library is not present.
*
* @author Stephane Nicoll
*/
@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions("hazelcast-client-*.jar")
public class HazelcastAutoConfigurationServerTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
private AnnotationConfigApplicationContext context;
@After
public void closeContext() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void defaultConfigFile() throws IOException {
load(); // hazelcast.xml present in root classpath
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance.getConfig().getConfigurationUrl())
.isEqualTo(new ClassPathResource("hazelcast.xml").getURL());
}
@Test
public void systemProperty() throws IOException {
System.setProperty(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY,
"classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml");
try {
load();
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
Map<String, QueueConfig> queueConfigs = hazelcastInstance.getConfig()
.getQueueConfigs();
assertThat(queueConfigs).hasSize(1).containsKey("foobar");
}
finally {
System.clearProperty(HazelcastServerConfiguration.CONFIG_SYSTEM_PROPERTY);
}
}
@Test
public void explicitConfigFile() throws IOException {
load("spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/"
+ "hazelcast-specific.xml");
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance.getConfig().getConfigurationFile()).isEqualTo(
new ClassPathResource("org/springframework/boot/autoconfigure/hazelcast"
+ "/hazelcast-specific.xml").getFile());
}
@Test
public void explicitConfigUrl() throws IOException {
load("spring.hazelcast.config=hazelcast-default.xml");
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance.getConfig().getConfigurationUrl())
.isEqualTo(new ClassPathResource("hazelcast-default.xml").getURL());
}
@Test
public void unknownConfigFile() {
this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("foo/bar/unknown.xml");
load("spring.hazelcast.config=foo/bar/unknown.xml");
}
@Test
public void configInstanceWithName() {
Config config = new Config("my-test-instance");
HazelcastInstance existingHazelcastInstance = Hazelcast
.newHazelcastInstance(config);
try {
load(HazelcastConfigWithName.class,
"spring.hazelcast.config=this-is-ignored.xml");
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance.getConfig().getInstanceName())
.isEqualTo("my-test-instance");
// Should reuse any existing instance by default.
assertThat(hazelcastInstance).isEqualTo(existingHazelcastInstance);
}
finally {
existingHazelcastInstance.shutdown();
}
}
@Test
public void configInstanceWithoutName() {
load(HazelcastConfigNoName.class, "spring.hazelcast.config=this-is-ignored.xml");
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
Map<String, QueueConfig> queueConfigs = hazelcastInstance.getConfig()
.getQueueConfigs();
assertThat(queueConfigs).hasSize(1).containsKey("another-queue");
}
private void load(String... environment) {
load(null, environment);
}
private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
if (config != null) {
applicationContext.register(config);
}
applicationContext.register(HazelcastAutoConfiguration.class);
applicationContext.refresh();
this.context = applicationContext;
}
@Configuration
static class HazelcastConfigWithName {
@Bean
public Config myHazelcastConfig() {
return new Config("my-test-instance");
}
}
@Configuration
static class HazelcastConfigNoName {
@Bean
public Config anotherHazelcastConfig() {
Config config = new Config();
config.addQueueConfig(new QueueConfig("another-queue"));
return config;
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2016 the original author or authors.
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,36 +17,24 @@
package org.springframework.boot.autoconfigure.hazelcast;
import java.io.IOException;
import java.util.Map;
import com.hazelcast.config.Config;
import com.hazelcast.config.QueueConfig;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link HazelcastAutoConfiguration}.
* Tests for {@link HazelcastAutoConfiguration} with full classpath.
*
* @author Stephane Nicoll
*/
public class HazelcastAutoConfigurationTests {
@Rule
public final ExpectedException thrown = ExpectedException.none();
private AnnotationConfigApplicationContext context;
@After
@ -58,122 +46,19 @@ public class HazelcastAutoConfigurationTests {
@Test
public void defaultConfigFile() throws IOException {
load(); // hazelcast.xml present in root classpath
load(); // no hazelcast-client.xml and hazelcast.xml is present in root classpath
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance.getConfig().getConfigurationUrl())
.isEqualTo(new ClassPathResource("hazelcast.xml").getURL());
}
@Test
public void systemProperty() throws IOException {
System.setProperty(HazelcastConfigResourceCondition.CONFIG_SYSTEM_PROPERTY,
"classpath:org/springframework/boot/autoconfigure/hazelcast/hazelcast-specific.xml");
try {
load();
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
Map<String, QueueConfig> queueConfigs = hazelcastInstance.getConfig()
.getQueueConfigs();
assertThat(queueConfigs).hasSize(1).containsKey("foobar");
}
finally {
System.clearProperty(HazelcastConfigResourceCondition.CONFIG_SYSTEM_PROPERTY);
}
}
@Test
public void explicitConfigFile() throws IOException {
load("spring.hazelcast.config=org/springframework/boot/autoconfigure/hazelcast/"
+ "hazelcast-specific.xml");
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance.getConfig().getConfigurationFile()).isEqualTo(
new ClassPathResource("org/springframework/boot/autoconfigure/hazelcast"
+ "/hazelcast-specific.xml").getFile());
}
@Test
public void explicitConfigUrl() throws IOException {
load("spring.hazelcast.config=hazelcast-default.xml");
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance.getConfig().getConfigurationUrl())
.isEqualTo(new ClassPathResource("hazelcast-default.xml").getURL());
}
@Test
public void unknownConfigFile() {
this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("foo/bar/unknown.xml");
load("spring.hazelcast.config=foo/bar/unknown.xml");
}
@Test
public void configInstanceWithName() {
Config config = new Config("my-test-instance");
HazelcastInstance existingHazelcastInstance = Hazelcast
.newHazelcastInstance(config);
try {
load(HazelcastConfigWithName.class,
"spring.hazelcast.config=this-is-ignored.xml");
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
assertThat(hazelcastInstance.getConfig().getInstanceName())
.isEqualTo("my-test-instance");
// Should reuse any existing instance by default.
assertThat(hazelcastInstance).isEqualTo(existingHazelcastInstance);
}
finally {
existingHazelcastInstance.shutdown();
}
}
@Test
public void configInstanceWithoutName() {
load(HazelcastConfigNoName.class, "spring.hazelcast.config=this-is-ignored.xml");
HazelcastInstance hazelcastInstance = this.context
.getBean(HazelcastInstance.class);
Map<String, QueueConfig> queueConfigs = hazelcastInstance.getConfig()
.getQueueConfigs();
assertThat(queueConfigs).hasSize(1).containsKey("another-queue");
}
private void load(String... environment) {
load(null, environment);
}
private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
if (config != null) {
applicationContext.register(config);
}
applicationContext.register(HazelcastAutoConfiguration.class);
applicationContext.refresh();
this.context = applicationContext;
}
@Configuration
static class HazelcastConfigWithName {
@Bean
public Config myHazelcastConfig() {
return new Config("my-test-instance");
}
}
@Configuration
static class HazelcastConfigNoName {
@Bean
public Config anotherHazelcastConfig() {
Config config = new Config();
config.addQueueConfig(new QueueConfig("another-queue"));
return config;
}
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(ctx, environment);
ctx.register(HazelcastAutoConfiguration.class);
ctx.refresh();
this.context = ctx;
}
}

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<hazelcast-client xmlns="http://www.hazelcast.com/schema/client-config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.hazelcast.com/schema/client-config hazelcast-client-config-3.8.xsd">
</hazelcast-client>

@ -5111,9 +5111,8 @@ provide good examples of how to write XA wrappers.
[[boot-features-hazelcast]]
== Hazelcast
If hazelcast is on the classpath, Spring Boot will auto-configure an `HazelcastInstance`
that you can inject in your application. The `HazelcastInstance` is only created if a
configuration is found.
If hazelcast is on the classpath and a suitable configuration is found, Spring Boot
will auto-configure an `HazelcastInstance` that you can inject in your application.
You can define a `com.hazelcast.config.Config` bean and we'll use that. If your
configuration defines an instance name, we'll try to locate an existing instance rather
@ -5132,6 +5131,14 @@ classpath. We also check if the `hazelcast.config` system property is set. Check
http://docs.hazelcast.org/docs/latest/manual/html-single/[Hazelcast documentation] for
more details.
If `hazelcast-client` is present on the classpath, Spring Boot will first attempt to
create a client with similar rules as above, that is:
* The presence of a `com.hazelcast.client.config.ClientConfig` bean
* A configuration file defined by the `spring.hazelcast.config` property
* The presence of the `hazelcast.client.config` system property
* A `hazelcast-client.xml` in the working directory or at the root of the classpath
NOTE: Spring Boot also has an
<<boot-features-caching-provider-hazelcast,explicit caching support for Hazelcast>>. The
`HazelcastInstance` is automatically wrapped in a `CacheManager` implementation if

Loading…
Cancel
Save