diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml
index 63594cb213ac..ac162597300a 100644
--- a/spring-boot-dependencies/pom.xml
+++ b/spring-boot-dependencies/pom.xml
@@ -73,6 +73,7 @@
2.3.25-incubating
2.4.1
8.2.0
+ 1.0.0-incubating
3.0.0
2.9
2.4.7
@@ -147,6 +148,7 @@
1.6.4.BUILD-SNAPSHOT
1.2.3.RELEASE
3.0.7.RELEASE
+ 1.0.0.INCUBATING-RELEASE
Ingalls-M1
0.21.0.RELEASE
5.0.0.BUILD-SNAPSHOT
@@ -324,6 +326,11 @@
spring-boot-starter-data-gemfire
2.0.0.BUILD-SNAPSHOT
+
+ org.springframework.boot
+ spring-boot-starter-data-geode
+ 2.0.0.BUILD-SNAPSHOT
+
org.springframework.boot
spring-boot-starter-data-jpa
@@ -672,6 +679,17 @@
gemfire
${gemfire.version}
+
+ org.apache.geode
+ geode-core
+ ${geode.version}
+
+
+ org.apache.shiro
+ shiro-core
+
+
+
com.github.ben-manes.caffeine
caffeine
diff --git a/spring-boot-samples/pom.xml b/spring-boot-samples/pom.xml
index 1310311924db..a28c7abdf9b2 100644
--- a/spring-boot-samples/pom.xml
+++ b/spring-boot-samples/pom.xml
@@ -37,6 +37,7 @@
spring-boot-sample-data-couchbase
spring-boot-sample-data-elasticsearch
spring-boot-sample-data-gemfire
+ spring-boot-sample-data-geode
spring-boot-sample-data-jpa
spring-boot-sample-data-mongodb
spring-boot-sample-data-neo4j
diff --git a/spring-boot-samples/spring-boot-sample-data-geode/pom.xml b/spring-boot-samples/spring-boot-sample-data-geode/pom.xml
new file mode 100644
index 000000000000..80f3c5b6ee7a
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-data-geode/pom.xml
@@ -0,0 +1,45 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-samples
+ 2.0.0.BUILD-SNAPSHOT
+
+ spring-boot-sample-data-geode
+ Spring Boot Data Geode Sample
+ Spring Boot Data Geode Sample
+ http://projects.spring.io/spring-boot/
+
+ Pivotal Software, Inc.
+ http://www.spring.io
+
+
+ ${basedir}/../..
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-data-geode
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/spring-boot-samples/spring-boot-sample-data-geode/src/main/java/sample/data/geode/SampleDataGeodeApplication.java b/spring-boot-samples/spring-boot-sample-data-geode/src/main/java/sample/data/geode/SampleDataGeodeApplication.java
new file mode 100644
index 000000000000..b7b3c9fab561
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-data-geode/src/main/java/sample/data/geode/SampleDataGeodeApplication.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2010-2013 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 sample.data.geode;
+
+import org.apache.geode.cache.CacheLoader;
+import org.apache.geode.cache.CacheLoaderException;
+import org.apache.geode.cache.GemFireCache;
+import org.apache.geode.cache.LoaderHelper;
+import org.apache.geode.cache.RegionAttributes;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.gemfire.GemfireTemplate;
+import org.springframework.data.gemfire.PartitionedRegionFactoryBean;
+import org.springframework.data.gemfire.RegionAttributesFactoryBean;
+import org.springframework.data.gemfire.config.annotation.PeerCacheApplication;
+
+import sample.data.geode.config.SampleDataGeodeApplicationProperties;
+import sample.data.geode.service.Calculator;
+import sample.data.geode.service.factory.CalculatorFactory;
+
+/**
+ * SampleDataGeodeApplication class is a Spring Boot, Apache Geode peer cache application
+ * using Apache Geode to perform and store mathematical calculations.
+ *
+ * @author John Blum
+ * @see org.springframework.boot.SpringApplication
+ * @see org.springframework.boot.autoconfigure.SpringBootApplication
+ * @see org.springframework.boot.context.properties.ConfigurationProperties
+ * @see org.springframework.context.ApplicationContext
+ * @see org.springframework.context.annotation.Bean
+ * @see org.springframework.data.gemfire.CacheFactoryBean
+ * @see org.springframework.data.gemfire.GemfireTemplate
+ * @see org.springframework.data.gemfire.PartitionedRegionFactoryBean
+ * @see org.apache.geode.cache.Cache
+ * @see org.apache.geode.cache.CacheLoader
+ * @see sample.data.geode.service.Calculator
+ * @see sample.data.geode.service.factory.CalculatorFactory
+ * @since 1.5.0
+ */
+@SpringBootApplication
+@PeerCacheApplication(name = "SampleDataGeodeApplication", logLevel = "config")
+@EnableConfigurationProperties(SampleDataGeodeApplicationProperties.class)
+@SuppressWarnings("unused")
+public class SampleDataGeodeApplication {
+
+ protected static final String CALCULATIONS_REGION_NAME = "Calculations";
+
+ public static void main(final String[] args) {
+ SpringApplication.run(SampleDataGeodeApplication.class, args);
+ }
+
+ @Autowired
+ SampleDataGeodeApplicationProperties applicationProperties;
+
+ @Bean(CALCULATIONS_REGION_NAME)
+ PartitionedRegionFactoryBean calculationsRegion(GemFireCache gemfireCache,
+ RegionAttributes calculationsRegionAttributes,
+ @Qualifier("calculationsRegionLoader") CacheLoader calculationsLoader) {
+
+ PartitionedRegionFactoryBean calculationsRegion =
+ new PartitionedRegionFactoryBean();
+
+ calculationsRegion.setAttributes(calculationsRegionAttributes);
+ calculationsRegion.setCache(gemfireCache);
+ calculationsRegion.setCacheLoader(calculationsLoader);
+ calculationsRegion.setClose(false);
+ calculationsRegion.setPersistent(false);
+
+ return calculationsRegion;
+ }
+
+ @Bean
+ @SuppressWarnings("unchecked")
+ RegionAttributesFactoryBean calculationsRegionAttributes() {
+ RegionAttributesFactoryBean calculationsRegionAttributes =
+ new RegionAttributesFactoryBean();
+
+ calculationsRegionAttributes.setKeyConstraint(Long.class);
+ calculationsRegionAttributes.setValueConstraint(Long.class);
+
+ return calculationsRegionAttributes;
+ }
+
+ @Bean
+ CacheLoader calculationsRegionLoader(
+ @Qualifier("calculatorResolver") Calculator calculator) {
+
+ return new CacheLoader() {
+ @Override
+ public Long load(LoaderHelper loaderHelper)
+ throws CacheLoaderException {
+
+ Long operand = loaderHelper.getKey();
+
+ return calculator.calculate(operand);
+ }
+
+ @Override
+ public void close() {
+ }
+ };
+ }
+
+ @Bean
+ GemfireTemplate calculationsRegionTemplate(GemFireCache gemfireCache) {
+ return new GemfireTemplate(gemfireCache.getRegion(CALCULATIONS_REGION_NAME));
+ }
+
+ @Bean
+ @SuppressWarnings("unchecked")
+ Calculator calculatorResolver(ApplicationContext context) {
+ return context.getBean(applicationProperties.getCalculator(), Calculator.class);
+ }
+
+ @Bean
+ Calculator addition() {
+ return CalculatorFactory.addition();
+ }
+
+ @Bean
+ Calculator factorial() {
+ return CalculatorFactory.factorial();
+ }
+
+ @Bean
+ Calculator multiplication() {
+ return CalculatorFactory.multiplication();
+ }
+}
diff --git a/spring-boot-samples/spring-boot-sample-data-geode/src/main/java/sample/data/geode/config/SampleDataGeodeApplicationProperties.java b/spring-boot-samples/spring-boot-sample-data-geode/src/main/java/sample/data/geode/config/SampleDataGeodeApplicationProperties.java
new file mode 100644
index 000000000000..364f06a57fa5
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-data-geode/src/main/java/sample/data/geode/config/SampleDataGeodeApplicationProperties.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010-2013 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 sample.data.geode.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.util.StringUtils;
+
+/**
+ * The {@link SampleDataGeodeApplicationProperties} class encapsulates properties
+ * used to configure the {@link sample.data.geode.SampleDataGeodeApplication}.
+ *
+ * @author John Blum
+ * @see org.springframework.boot.context.properties.ConfigurationProperties
+ * @since 1.5.0
+ */
+@ConfigurationProperties(prefix = "sample.data.geode")
+@SuppressWarnings("unused")
+public class SampleDataGeodeApplicationProperties {
+
+ protected static final String DEFAULT_CALCULATOR = "factorial";
+
+ private String calculator;
+
+ protected String defaultIfEmpty(String value, String defaultValue) {
+ return (StringUtils.hasText(value) ? value : defaultValue);
+ }
+
+ public String getCalculator() {
+ return defaultIfEmpty(calculator, DEFAULT_CALCULATOR);
+ }
+
+ public void setCalculator(String calculator) {
+ this.calculator = calculator;
+ }
+}
diff --git a/spring-boot-samples/spring-boot-sample-data-geode/src/main/java/sample/data/geode/service/Calculator.java b/spring-boot-samples/spring-boot-sample-data-geode/src/main/java/sample/data/geode/service/Calculator.java
new file mode 100644
index 000000000000..311dde756849
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-data-geode/src/main/java/sample/data/geode/service/Calculator.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010-2013 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 sample.data.geode.service;
+
+/**
+ * The {@link Calculator} interface represents a mathematical computation
+ * of an operand with itself.
+ *
+ * @author John Blum
+ * @since 1.5.0
+ */
+public interface Calculator {
+
+ /**
+ * Calculates the value of the operand with itself.
+ *
+ * @param operand the operand to used in the calculation.
+ * @return the result of the operand calculated with itself.
+ */
+ T calculate(S operand);
+
+}
diff --git a/spring-boot-samples/spring-boot-sample-data-geode/src/main/java/sample/data/geode/service/factory/CalculatorFactory.java b/spring-boot-samples/spring-boot-sample-data-geode/src/main/java/sample/data/geode/service/factory/CalculatorFactory.java
new file mode 100644
index 000000000000..589af3aaab22
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-data-geode/src/main/java/sample/data/geode/service/factory/CalculatorFactory.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2010-2013 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 sample.data.geode.service.factory;
+
+import org.springframework.util.Assert;
+
+import sample.data.geode.service.Calculator;
+
+/**
+ * {@link CalculatorFactory} is an abstract factory class that constructs different instances
+ * of the {@link Calculator} interface to compute the mathematical operations of an operand
+ * applied to itself.
+ *
+ * In other words, given an operand (n), then f(n) = some calculation on (n).
+ *
+ * For example, addition(n) = n + n = 2n, multiplication(n) = n * n = n^2
+ * and factorial(n) = n!, etc.
+ *
+ * @author John Blum
+ * @see sample.data.geode.service.Calculator
+ * @since 1.5.0
+ */
+@SuppressWarnings("unused")
+public abstract class CalculatorFactory {
+
+ /* (non-Javadoc) */
+ public static Calculator addition() {
+ return new Calculator() {
+ @Override
+ public Long calculate(Long operand) {
+ Assert.notNull(operand, "operand must not be null");
+ return (operand + operand);
+ }
+
+ @Override
+ public String toString() {
+ return "addition";
+ }
+ };
+ }
+
+ /* (non-Javadoc) */
+ public static Calculator factorial() {
+ return new Calculator() {
+ @Override
+ public Long calculate(Long operand) {
+ Assert.notNull(operand, "operand must not be null");
+ Assert.isTrue(operand > -1, String.format(
+ "operand [%1$s] must be greater than equal to 0", operand));
+
+ if (operand <= 2l) {
+ return (operand < 2l ? 1l : 2l);
+ }
+
+ long result = operand;
+
+ while (--operand > 1) {
+ result *= operand;
+ }
+
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "factorial";
+ }
+ };
+ }
+
+ /* (non-Javadoc) */
+ public static Calculator multiplication() {
+ return new Calculator() {
+ @Override
+ public Long calculate(Long operand) {
+ Assert.notNull(operand, "operand must not be null");
+ return (operand * operand);
+ }
+
+ @Override
+ public String toString() {
+ return "multiplication";
+ }
+ };
+ }
+}
diff --git a/spring-boot-samples/spring-boot-sample-data-geode/src/test/java/sample/data/geode/SampleDataGeodeApplicationTests.java b/spring-boot-samples/spring-boot-sample-data-geode/src/test/java/sample/data/geode/SampleDataGeodeApplicationTests.java
new file mode 100644
index 000000000000..d808d27277fd
--- /dev/null
+++ b/spring-boot-samples/spring-boot-sample-data-geode/src/test/java/sample/data/geode/SampleDataGeodeApplicationTests.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010-2013 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 sample.data.geode;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.gemfire.GemfireTemplate;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import sample.data.geode.config.SampleDataGeodeApplicationProperties;
+import sample.data.geode.service.Calculator;
+
+/**
+ * Integration tests for {@link SampleDataGeodeApplication}.
+ *
+ * @author John Blum
+ * @see org.junit.Test
+ * @see org.springframework.data.gemfire.GemfireTemplate
+ * @see org.springframework.test.context.ContextConfiguration
+ * @see org.springframework.test.context.junit4.SpringRunner
+ * @see sample.data.geode.SampleDataGeodeApplication
+ * @since 1.5.0
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = SampleDataGeodeApplication.class)
+@SuppressWarnings("unused")
+public class SampleDataGeodeApplicationTests {
+
+ @Autowired
+ @Qualifier("calculatorResolver")
+ private Calculator calculator;
+
+ @Autowired
+ private GemfireTemplate calculationsTemplate;
+
+ @Autowired
+ private SampleDataGeodeApplicationProperties applicationProperties;
+
+ @Before
+ public void setup() {
+ assertThat(calculator).isNotNull();
+ assertThat(calculationsTemplate).isNotNull();
+ assertThat(applicationProperties).isNotNull();
+ assertThat(calculator.toString()).isEqualTo(applicationProperties.getCalculator());
+ System.err.printf("%1$s(%2$d) = %3$d%n", calculator.toString(), 0l, calculator.calculate(0l));
+ System.err.printf("%1$s(%2$d) = %3$d%n", calculator.toString(), 2l, calculator.calculate(2l));
+ System.err.printf("%1$s(%2$d) = %3$d%n", calculator.toString(), 4l, calculator.calculate(4l));
+ System.err.printf("%1$s(%2$d) = %3$d%n", calculator.toString(), 8l, calculator.calculate(8l));
+ }
+
+ @Test
+ public void verifyCalculationsAreCorrect() {
+ assertThat(calculationsTemplate.get(0l)).isEqualTo(calculator.calculate(0l));
+ assertThat(calculationsTemplate.get(1l)).isEqualTo(calculator.calculate(1l));
+ assertThat(calculationsTemplate.get(2l)).isEqualTo(calculator.calculate(2l));
+ assertThat(calculationsTemplate.get(3l)).isEqualTo(calculator.calculate(3l));
+ assertThat(calculationsTemplate.get(4l)).isEqualTo(calculator.calculate(4l));
+ assertThat(calculationsTemplate.get(5l)).isEqualTo(calculator.calculate(5l));
+ assertThat(calculationsTemplate.get(6l)).isEqualTo(calculator.calculate(6l));
+ assertThat(calculationsTemplate.get(7l)).isEqualTo(calculator.calculate(7l));
+ assertThat(calculationsTemplate.get(8l)).isEqualTo(calculator.calculate(8l));
+ assertThat(calculationsTemplate.get(9l)).isEqualTo(calculator.calculate(9l));
+ }
+}
diff --git a/spring-boot-starters/pom.xml b/spring-boot-starters/pom.xml
index 6dda14cb0d41..ea0a45806f32 100644
--- a/spring-boot-starters/pom.xml
+++ b/spring-boot-starters/pom.xml
@@ -32,6 +32,7 @@
spring-boot-starter-data-couchbase
spring-boot-starter-data-elasticsearch
spring-boot-starter-data-gemfire
+ spring-boot-starter-data-geode
spring-boot-starter-data-jpa
spring-boot-starter-data-mongodb
spring-boot-starter-data-neo4j
diff --git a/spring-boot-starters/spring-boot-starter-data-geode/pom.xml b/spring-boot-starters/spring-boot-starter-data-geode/pom.xml
new file mode 100644
index 000000000000..8024c5f7f4e7
--- /dev/null
+++ b/spring-boot-starters/spring-boot-starter-data-geode/pom.xml
@@ -0,0 +1,63 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starters
+ 2.0.0.BUILD-SNAPSHOT
+
+ spring-boot-starter-data-geode
+ Spring Boot Data Geode Starter
+ Spring Boot Data Geode Starter
+ http://projects.spring.io/spring-boot/
+
+ Pivotal Software, Inc.
+ http://www.spring.io
+
+
+ ${basedir}/../..
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.data
+ spring-data-geode
+ ${spring-data-geode.version}
+
+
+ commons-logging
+ commons-logging
+
+
+ commons-logging
+ commons-logging-api
+
+
+
+
+
+
+
+ org.basepom.maven
+ duplicate-finder-maven-plugin
+
+
+ duplicate-dependencies
+ validate
+
+ check
+
+
+
+ changelog.txt
+
+
+
+
+
+
+
+
diff --git a/spring-boot-starters/spring-boot-starter-data-geode/src/main/resources/META-INF/spring.provides b/spring-boot-starters/spring-boot-starter-data-geode/src/main/resources/META-INF/spring.provides
new file mode 100644
index 000000000000..e44977168914
--- /dev/null
+++ b/spring-boot-starters/spring-boot-starter-data-geode/src/main/resources/META-INF/spring.provides
@@ -0,0 +1 @@
+provides: spring-data-geode