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