diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml
index 6bbd95a1de..2126c5c248 100755
--- a/spring-boot-autoconfigure/pom.xml
+++ b/spring-boot-autoconfigure/pom.xml
@@ -75,6 +75,11 @@
hazelcast
true
+
+ com.hazelcast
+ hazelcast-client
+ true
+
com.hazelcast
hazelcast-spring
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfiguration.java
index 1eb7d23b81..91a146db17 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfiguration.java
@@ -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");
- }
-
- }
-
}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientConfiguration.java
new file mode 100644
index 0000000000..2a496c2365
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientConfiguration.java
@@ -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");
+ }
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientFactory.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientFactory.java
new file mode 100644
index 0000000000..75efe28ed0
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastClientFactory.java
@@ -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);
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastConfigResourceCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastConfigResourceCondition.java
index 0bec54d50a..7de04e03c6 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastConfigResourceCondition.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastConfigResourceCondition.java
@@ -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);
}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastInstanceFactory.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastInstanceFactory.java
index fffd240055..a6014a4675 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastInstanceFactory.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastInstanceFactory.java
@@ -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.
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastServerConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastServerConfiguration.java
new file mode 100644
index 0000000000..6d25ac6ac4
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastServerConfiguration.java
@@ -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");
+ }
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java
index 65258ec12c..7f40b3e1fe 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java
@@ -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
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java
new file mode 100644
index 0000000000..03d0886c81
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationClientTests.java
@@ -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();
+ }
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationServerTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationServerTests.java
new file mode 100644
index 0000000000..bb66916b4c
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationServerTests.java
@@ -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 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 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;
+ }
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationTests.java
index ef20564aed..54ced943aa 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfigurationTests.java
@@ -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 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 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;
}
}
diff --git a/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.xml b/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.xml
new file mode 100644
index 0000000000..e5596bf220
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/resources/org/springframework/boot/autoconfigure/hazelcast/hazelcast-client-specific.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
index addc18b436..6ea3bce6da 100644
--- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
+++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
@@ -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
<>. The
`HazelcastInstance` is automatically wrapped in a `CacheManager` implementation if