#539 - Polishing.

Add author tags. Simplify dependency setup. Replace logger declarations with Lombok's CommonsLog. Simplify test annotations.

Disable WAN module as the WAN server does not stop after running tests. Reformat code.
This commit is contained in:
Mark Paluch
2020-02-27 10:21:46 +01:00
parent fa0021cffb
commit 54f7146e0f
121 changed files with 1160 additions and 1092 deletions

View File

@@ -6,6 +6,19 @@ This repository contains example projects for the different Spring Data modules
We have separate folders for the samples of individual modules:
## Spring Data for Apache Cassandra
* `example` - Shows core Spring Data support for Apache Cassandra.
* `java8` - Java 8 specific functionality like the support for JSR-310 types in object mapping.
* `kotlin` - Example for using Cassandra with Kotlin.
* `reactive` - Example project to show reactive template and repository support.
## Spring Data Elasticsearch
* `example` - Example how to use basic text search, geo-spatial search and facets.
* `rest` - Example how to use the High Level REST Client backing template and repository.
* `reactive` - Example how to use reactive client, template and repository features.
## Spring Data for Apache Geode
* `events` - In this example the test will make use of event handlers and async event queue to handle events.
@@ -17,6 +30,10 @@ We have separate folders for the samples of individual modules:
* `transactions` - In this example the client will perform operations within a transaction. First, it will do a successful transaction where entries are saved to the server, and then a failed transaction where all changes are reverted.
* `wan` - In these example two servers are deployed. One server populates itself with data, and the other server gets populated with that data via WAN replication.
## Spring Data JDBC
* `basic` - Basic usage of Spring Data JDBC.
## Spring Data JPA
* `eclipselink` - Sample project to show how to use Spring Data JPA with Spring Boot and [Eclipselink](https://www.eclipse.org/eclipselink/).
@@ -30,6 +47,10 @@ We have separate folders for the samples of individual modules:
* `showcase` - Refactoring show case of how to improve a plain-JPA-based persistence layer by using Spring Data JPA (read: removing close to all of the implementation code). Follow the `demo.txt` file for detailed instructions.
* `vavr` - Shows the support of [Vavr](https://www.vavr.io) collection types as return types for query methods.
## Spring Data LDAP
* `example` - Sample for Spring Data repositories to access an LDAP store.
## Spring Data MongoDB
* `aggregation` - Example project to showcase the MongoDB aggregation framework support.
@@ -46,14 +67,13 @@ We have separate folders for the samples of individual modules:
* `text-search` - Example project showing usage of MongoDB text search feature.
* `transactions` - Example project for imperative and reactive MongoDB 4.0 transaction support.
## Spring Data REST
## Spring Data Neo4j
* `headers` - A sample showing the population of HTTP headers and the usage of them to perform conditional `GET` requests.
* `multi-store` - A sample REST web-service based on both Spring Data JPA and Spring Data MongoDB.
* `projections` - A sample REST web-service showing how to use projections.
* `security` - A sample REST web-service secured using Spring Security.
* `starbucks` - A sample REST web-service built with Spring Data REST and MongoDB.
* `uri-customizations` - Example project to show URI customization capabilities.
* `example` - Example to show basic node and relationship entities and repository usage.
## Spring Data R2DBC
* `example` - Basic usage of Spring Data R2DBC.
## Spring Data Redis
@@ -64,46 +84,26 @@ We have separate folders for the samples of individual modules:
* `sentinel` - Example for Redis Sentinel support.
* `streams` - Example for [Redis Streams](https://redis.io/topics/streams-intro) support.
## Spring Data REST
* `headers` - A sample showing the population of HTTP headers and the usage of them to perform conditional `GET` requests.
* `multi-store` - A sample REST web-service based on both Spring Data JPA and Spring Data MongoDB.
* `projections` - A sample REST web-service showing how to use projections.
* `security` - A sample REST web-service secured using Spring Security.
* `starbucks` - A sample REST web-service built with Spring Data REST and MongoDB.
* `uri-customizations` - Example project to show URI customization capabilities.
## Spring Data for Apache Solr
* `example` - Example project for Spring Data repositories for Apache Solr.
* `managed-schema` - Example project to show managed schema integration.
## Spring Data Elasticsearch
* `example` - Example how to use basic text search, geo-spatial search and facets.
* `rest` - Example how to use the High Level REST Client backing template and repository.
* `reactive` - Example how to use reactive client, template and repository features.
## Spring Data Neo4j
* `example` - Example to show basic node and relationship entities and repository usage.
## Spring Data web support
* `projections` - Example for Spring Data web support for JSONPath and XPath expressions on projection interfaces.
* `querydsl` - Example for Spring Data Querydsl web integration (creating a `Predicate` from web requests).
* `web` - Example for Spring Data web integration (binding `Pageable` instances to Spring MVC controller methods, using interfaces to bind Spring MVC request payloads).
## Spring Data for Apache Cassandra
* `example` - Shows core Spring Data support for Apache Cassandra.
* `java8` - Java 8 specific functionality like the support for JSR-310 types in object mapping.
* `kotlin` - Example for using Cassandra with Kotlin.
* `reactive` - Example project to show reactive template and repository support.
## Spring Data LDAP
* `example` - Sample for Spring Data repositories to access an LDAP store.
## Spring Data JDBC
* `basic` - Basic usage of Spring Data JDBC.
## Spring Data R2DBC
* `example` - Basic usage of Spring Data R2DBC.
## Miscellaneous
* `bom` - Example project how to use the Spring Data release train bom in non-Spring-Boot scenarios.

View File

@@ -2,16 +2,14 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>example.springdata.geode</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>events</artifactId>
<modelVersion>4.0.0</modelVersion>
<dependencies>
<parent>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
</dependencies>
<artifactId>events</artifactId>
</project>
</project>

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import lombok.Data;
@@ -29,6 +28,7 @@ import java.io.Serializable;
*/
@Data
public class Address implements Serializable {
private String street;
private String city;
private String country;

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import lombok.Data;
@@ -48,4 +47,4 @@ public class Customer implements Serializable {
this.lastName = lastName;
this.addresses = Arrays.asList(addresses);
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import org.apache.geode.cache.CacheWriterException;
@@ -22,6 +21,9 @@ import org.apache.geode.cache.util.CacheWriterAdapter;
import org.apache.geode.internal.cache.EntryEventImpl;
import org.springframework.stereotype.Component;
/**
* @author Patrick Johnson
*/
@Component
public class CustomerCacheWriter extends CacheWriterAdapter<Long, Customer> {

View File

@@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import org.springframework.data.repository.CrudRepository;
/**
* @author Patrick Johnson
*/
public interface CustomerRepository extends CrudRepository<Customer, Long> {
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import lombok.Data;
@@ -28,10 +27,11 @@ import java.io.Serializable;
*/
@Data
public class EmailAddress implements Serializable {
private String value;
public EmailAddress(String value) {
this.value = value;
}
}
}

View File

@@ -13,40 +13,41 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import org.apache.geode.cache.Region;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import java.math.BigDecimal;
import java.util.List;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
@SpringBootApplication(scanBasePackageClasses = EventServerConfig.class)
import lombok.extern.apachecommons.CommonsLog;
import org.apache.geode.cache.Region;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
/**
* @author Patrick Johnson
*/
@SpringBootApplication
@CommonsLog
public class EventServer {
private Logger logger = LoggerFactory.getLogger(this.getClass());
public static void main(String[] args) {
new SpringApplicationBuilder(EventServer.class)
.web(WebApplicationType.NONE)
.build()
.run(args);
new SpringApplicationBuilder(EventServer.class).web(WebApplicationType.NONE).build().run(args);
}
@Bean
public ApplicationRunner runner(CustomerRepository customerRepository, OrderRepository orderRepository,
ProductRepository productRepository, OrderProductSummaryRepository orderProductSummaryRepository, @Qualifier("Products") Region<Long, Product> products) {
ProductRepository productRepository, OrderProductSummaryRepository orderProductSummaryRepository,
@Qualifier("Products") Region<Long, Product> products) {
return args -> {
createCustomerData(customerRepository);
@@ -54,43 +55,37 @@ public class EventServer {
createOrders(productRepository, orderRepository);
logger.info("Completed creating orders ");
log.info("Completed creating orders ");
final List<OrderProductSummary> allForProductID = orderProductSummaryRepository.findAllForProductID(3L);
allForProductID.forEach(orderProductSummary -> logger.info("orderProductSummary = " + orderProductSummary));
List<OrderProductSummary> allForProductID = orderProductSummaryRepository.findAllForProductID(3L);
allForProductID.forEach(orderProductSummary -> log.info("orderProductSummary = " + orderProductSummary));
};
}
private void createOrders(ProductRepository productRepository, OrderRepository orderRepository) {
Random random = new Random(System.nanoTime());
Address address = new Address("it", "doesn't", "matter");
LongStream.rangeClosed(1, 10).forEach((orderId) ->
LongStream.rangeClosed(1, 300).forEach((customerId) -> {
Order order = new Order(orderId, customerId, address);
IntStream.rangeClosed(0, random.nextInt(3) + 1).forEach((lineItemCount) -> {
int quantity = random.nextInt(3) + 1;
long productId = random.nextInt(3) + 1;
order.add(new LineItem(productRepository.findById(productId).get(), quantity));
});
orderRepository.save(order);
}));
LongStream.rangeClosed(1, 10).forEach((orderId) -> LongStream.rangeClosed(1, 300).forEach((customerId) -> {
Order order = new Order(orderId, customerId, address);
IntStream.rangeClosed(0, random.nextInt(3) + 1).forEach((lineItemCount) -> {
int quantity = random.nextInt(3) + 1;
long productId = random.nextInt(3) + 1;
order.add(new LineItem(productRepository.findById(productId).get(), quantity));
});
orderRepository.save(order);
}));
}
private void createProducts(ProductRepository productRepository) {
productRepository.save(new Product(1L, "Apple iPod", new BigDecimal("99.99"),
"An Apple portable music player"));
productRepository.save(new Product(2L, "Apple iPad", new BigDecimal("499.99"),
"An Apple tablet device"));
Product macbook = new Product(3L, "Apple macBook", new BigDecimal("899.99"),
"An Apple notebook computer");
productRepository.save(new Product(1L, "Apple iPod", new BigDecimal("99.99"), "An Apple portable music player"));
productRepository.save(new Product(2L, "Apple iPad", new BigDecimal("499.99"), "An Apple tablet device"));
Product macbook = new Product(3L, "Apple macBook", new BigDecimal("899.99"), "An Apple notebook computer");
macbook.addAttribute("warranty", "included");
productRepository.save(macbook);
}
private void createCustomerData(CustomerRepository customerRepository) {
LongStream.rangeClosed(0, 300)
.parallel()
.forEach(customerId ->
customerRepository.save(new Customer(customerId, new EmailAddress(customerId + "@2.com"), "John" + customerId, "Smith" + customerId)));
LongStream.rangeClosed(0, 300).parallel().forEach(customerId -> customerRepository.save(
new Customer(customerId, new EmailAddress(customerId + "@2.com"), "John" + customerId, "Smith" + customerId)));
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import org.apache.geode.cache.Cache;
@@ -48,7 +47,7 @@ public class EventServerConfig {
@Bean
AsyncEventQueueFactoryBean orderAsyncEventQueue(GemFireCache gemFireCache, AsyncEventListener orderAsyncEventListener) {
final AsyncEventQueueFactoryBean asyncEventQueueFactoryBean = new AsyncEventQueueFactoryBean((Cache) gemFireCache);
AsyncEventQueueFactoryBean asyncEventQueueFactoryBean = new AsyncEventQueueFactoryBean((Cache) gemFireCache);
asyncEventQueueFactoryBean.setBatchTimeInterval(1000);
asyncEventQueueFactoryBean.setBatchSize(5);
asyncEventQueueFactoryBean.setAsyncEventListener(orderAsyncEventListener);
@@ -57,7 +56,7 @@ public class EventServerConfig {
@Bean(name = "OrderProductSummary")
PartitionedRegionFactoryBean<Long, Order> createOrderProductSummaryRegion(GemFireCache gemFireCache) {
final PartitionedRegionFactoryBean<Long, Order> partitionedRegionFactoryBean = new PartitionedRegionFactoryBean<>();
PartitionedRegionFactoryBean<Long, Order> partitionedRegionFactoryBean = new PartitionedRegionFactoryBean<>();
partitionedRegionFactoryBean.setCache(gemFireCache);
partitionedRegionFactoryBean.setRegionName("OrderProductSummary");
partitionedRegionFactoryBean.setDataPolicy(DataPolicy.PARTITION);
@@ -66,7 +65,7 @@ public class EventServerConfig {
@Bean("Orders")
PartitionedRegionFactoryBean<Long, Order> createOrderRegion(GemFireCache gemFireCache, AsyncEventQueue orderAsyncEventQueue) {
final PartitionedRegionFactoryBean<Long, Order> partitionedRegionFactoryBean = new PartitionedRegionFactoryBean<>();
PartitionedRegionFactoryBean<Long, Order> partitionedRegionFactoryBean = new PartitionedRegionFactoryBean<>();
partitionedRegionFactoryBean.setCache(gemFireCache);
partitionedRegionFactoryBean.setRegionName("Orders");
partitionedRegionFactoryBean.setDataPolicy(DataPolicy.PARTITION);
@@ -77,7 +76,7 @@ public class EventServerConfig {
@Bean("Products")
ReplicatedRegionFactoryBean<Long, Product> createProductRegion(GemFireCache gemFireCache, CacheListener<Long, Product> loggingCacheListener,
CacheLoader<Long, Product> productCacheLoader) {
final ReplicatedRegionFactoryBean<Long, Product> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
ReplicatedRegionFactoryBean<Long, Product> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
replicatedRegionFactoryBean.setCache(gemFireCache);
replicatedRegionFactoryBean.setRegionName("Products");
replicatedRegionFactoryBean.setDataPolicy(DataPolicy.REPLICATE);
@@ -90,7 +89,7 @@ public class EventServerConfig {
ReplicatedRegionFactoryBean<Long, Customer> createCustomerRegion(GemFireCache gemFireCache,
CacheWriter<Long, Customer> customerCacheWriter,
CacheListener<Long, Customer> loggingCacheListener) {
final ReplicatedRegionFactoryBean<Long, Customer> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
ReplicatedRegionFactoryBean<Long, Customer> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
replicatedRegionFactoryBean.setCache(gemFireCache);
replicatedRegionFactoryBean.setRegionName("Customers");
replicatedRegionFactoryBean.setDataPolicy(DataPolicy.REPLICATE);
@@ -98,4 +97,4 @@ public class EventServerConfig {
replicatedRegionFactoryBean.setCacheWriter(customerCacheWriter);
return replicatedRegionFactoryBean;
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import lombok.Data;
@@ -45,4 +44,4 @@ public class LineItem implements Serializable {
public Long getProductId() {
return product.getId();
}
}
}

View File

@@ -13,32 +13,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import lombok.extern.apachecommons.CommonsLog;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.util.CacheListenerAdapter;
import org.springframework.stereotype.Component;
/**
* @author Patrick Johnson
*/
@Component
@CommonsLog
public class LoggingCacheListener<K, V> extends CacheListenerAdapter<K, V> {
private Log logger = LogFactory.getLog(LoggingCacheListener.class);
@Override
public void afterCreate(EntryEvent<K, V> event) {
logger.info("In region [" + event.getRegion().getName() + "] created key [" + event.getKey() + "] value [" + event.getNewValue() + "]");
log.info("In region [" + event.getRegion().getName() + "] created key [" + event.getKey() + "] value ["
+ event.getNewValue() + "]");
}
@Override
public void afterDestroy(EntryEvent<K, V> event) {
logger.info("In region [" + event.getRegion().getName() + "] destroyed key [" + event.getKey() + "] ");
log.info("In region [" + event.getRegion().getName() + "] destroyed key [" + event.getKey() + "] ");
}
@Override
public void afterUpdate(EntryEvent<K, V> event) {
logger.info("In region [" + event.getRegion().getName() + "] updated key [" + event.getNewValue() + "] [oldValue [" + event.getOldValue() + "]] new value [" + event.getNewValue() + "]");
log.info("In region [" + event.getRegion().getName() + "] updated key [" + event.getNewValue() + "] [oldValue ["
+ event.getOldValue() + "]] new value [" + event.getNewValue() + "]");
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import lombok.Data;
@@ -34,6 +33,7 @@ import java.util.List;
@Data
@Region("Orders")
public class Order implements Serializable {
@Id
private Long id;
private Long customerId;
@@ -69,4 +69,4 @@ public class Order implements Serializable {
public void add(LineItem lineItem) {
lineItems.add(lineItem);
}
}
}

View File

@@ -13,17 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.asyncqueue.AsyncEvent;
import org.apache.geode.cache.asyncqueue.AsyncEventListener;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
/**
* @author Patrick Johnson
*/
public class OrderAsyncQueueListener implements AsyncEventListener {
private Region<Long, OrderProductSummary> summaryRegion;
@@ -34,9 +37,9 @@ public class OrderAsyncQueueListener implements AsyncEventListener {
@Override
public boolean processEvents(List<AsyncEvent> list) {
HashMap<Long, OrderProductSummary> summaryMap = new HashMap<>();
Map<Long, OrderProductSummary> summaryMap = new HashMap<>();
list.forEach(asyncEvent -> {
final Order order = (Order) asyncEvent.getDeserializedValue();
Order order = (Order) asyncEvent.getDeserializedValue();
if (order != null) {
order.getLineItems().forEach(lineItem -> {
OrderProductSummary orderProductSummary = summaryMap.get(lineItem.getProductId());
@@ -50,14 +53,15 @@ public class OrderAsyncQueueListener implements AsyncEventListener {
});
summaryMap.forEach((orderProductSummaryKey, orderProductSummary) -> {
final OrderProductSummary productSummary = summaryRegion.get(orderProductSummaryKey);
OrderProductSummary productSummary = summaryRegion.get(orderProductSummaryKey);
if (productSummary != null) {
final BigDecimal newSummaryAmount = productSummary.getSummaryAmount().add(orderProductSummary.getSummaryAmount());
BigDecimal newSummaryAmount = productSummary.getSummaryAmount().add(orderProductSummary.getSummaryAmount());
summaryRegion.put(orderProductSummaryKey, new OrderProductSummary(orderProductSummaryKey, newSummaryAmount));
} else {
summaryRegion.put(orderProductSummaryKey, orderProductSummary);
}
});
return true;
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import lombok.Data;
@@ -43,4 +42,4 @@ public class OrderProductSummary implements Serializable {
this.summaryKey = summaryKey;
this.summaryAmount = summaryAmount;
}
}
}

View File

@@ -13,16 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import java.util.List;
import org.springframework.data.gemfire.mapping.annotation.Region;
import org.springframework.data.gemfire.repository.Query;
import org.springframework.data.gemfire.repository.query.annotation.Hint;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
/**
* @author Patrick Johnson
*/
@Region("OrderProductSummary")
public interface OrderProductSummaryRepository extends CrudRepository<OrderProductSummary, Long> {
@Hint("emailAddressIndex")

View File

@@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import org.springframework.data.repository.CrudRepository;
public interface OrderRepository extends CrudRepository<Order, Long> {
}
/**
* @author Patrick Johnson
*/
public interface OrderRepository extends CrudRepository<Order, Long> {}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import lombok.Data;

View File

@@ -13,17 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import com.github.javafaker.Faker;
import lombok.SneakyThrows;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import org.apache.geode.cache.CacheLoader;
import org.apache.geode.cache.CacheLoaderException;
import org.apache.geode.cache.LoaderHelper;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import com.github.javafaker.Faker;
/**
* @author Patrick Johnson
*/
@Component
public class ProductCacheLoader implements CacheLoader<Long, Product> {
private Faker faker = new Faker();
@@ -33,8 +40,9 @@ public class ProductCacheLoader implements CacheLoader<Long, Product> {
return new Product((long) loaderHelper.getKey(), randomStringName(), randomPrice(), "");
}
@SneakyThrows
private BigDecimal randomPrice() {
return new BigDecimal(faker.commerce().price());
return new BigDecimal(new DecimalFormat("#0.00").parse(faker.commerce().price()).toString());
}
private String randomStringName() {

View File

@@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import org.springframework.data.repository.CrudRepository;
public interface ProductRepository extends CrudRepository<Product, Long> {
}
/**
* @author Patrick Johnson
*/
public interface ProductRepository extends CrudRepository<Product, Long> {}

View File

@@ -13,32 +13,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.events;
import static org.assertj.core.api.Assertions.*;
import org.apache.geode.cache.Cache;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Patrick Johnson
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = EventServer.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@SpringBootTest
public class EventServerTests {
@Autowired
Cache cache;
@Autowired Cache cache;
@Autowired
private ProductRepository productRepository;
@Autowired private ProductRepository productRepository;
@Autowired
private OrderProductSummaryRepository orderProductSummaryRepository;
@Autowired private OrderProductSummaryRepository orderProductSummaryRepository;
@Test
public void asyncEventQueueEasConfiguredCorrectly() {
@@ -47,9 +45,12 @@ public class EventServerTests {
@Test
public void productCacheLoaderWorks() {
long size = productRepository.count();
assertThat(this.productRepository.findById(777L)).isNotNull();
assertThat(productRepository.count()).isEqualTo(size + 1);
productRepository.deleteById(777L);
}
}
}

View File

@@ -2,22 +2,22 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>example.springdata.geode</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion>
<artifactId>expiration-eviction</artifactId>
<parent>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.jayway.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>1.7.0</version>
</dependency>
</dependencies>
<artifactId>expiration-eviction</artifactId>
<dependencies>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
</project>

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.expiration.eviction;
import lombok.Data;
@@ -29,6 +28,7 @@ import java.io.Serializable;
*/
@Data
public class Address implements Serializable {
private String street;
private String city;
private String country;

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.expiration.eviction;
import org.apache.geode.cache.CustomExpiry;
@@ -21,10 +20,12 @@ import org.apache.geode.cache.ExpirationAction;
import org.apache.geode.cache.ExpirationAttributes;
import org.apache.geode.cache.Region;
/**
* @author Patrick Johnson
*/
public class CustomCustomerExpiry implements CustomExpiry<Long, Product> {
private int timeout;
private final int timeout;
public CustomCustomerExpiry(int timeout) {
this.timeout = timeout;
@@ -37,4 +38,4 @@ public class CustomCustomerExpiry implements CustomExpiry<Long, Product> {
}
return null;
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.expiration.eviction;
import lombok.Data;
@@ -48,4 +47,4 @@ public class Customer implements Serializable {
this.lastName = lastName;
this.addresses = Arrays.asList(addresses);
}
}
}

View File

@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.expiration.eviction;
import org.springframework.data.gemfire.mapping.annotation.Region;
import org.springframework.data.repository.CrudRepository;
/**
* @author Patrick Johnson
*/
@Region("Customers")
public interface CustomerRepository extends CrudRepository<Customer, Long> {
}
public interface CustomerRepository extends CrudRepository<Customer, Long> {}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.expiration.eviction;
import lombok.Data;
@@ -28,10 +27,11 @@ import java.io.Serializable;
*/
@Data
public class EmailAddress implements Serializable {
private String value;
public EmailAddress(String value) {
this.value = value;
}
}
}

View File

@@ -13,14 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.expiration.eviction;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication(scanBasePackageClasses = ExpirationEvictionServerConfig.class)
/**
* @author Patrick Johnson
*/
@SpringBootApplication
public class ExpirationEvictionServer {
public static void main(String[] args) {

View File

@@ -13,14 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.expiration.eviction;
import com.github.javafaker.Faker;
import org.apache.geode.cache.CustomExpiry;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.Scope;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -34,16 +33,19 @@ import org.springframework.data.gemfire.eviction.EvictionActionType;
import org.springframework.data.gemfire.eviction.EvictionPolicyType;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
import com.github.javafaker.Faker;
/**
* @author Patrick Johnson
*/
@Configuration
@CacheServerApplication(logLevel = "error")
@EnableLocator
@EnableGemfireRepositories(basePackageClasses = CustomerRepository.class)
@EnableExpiration
@Import(ExpirationPolicyConfig.class)
@EnableEviction(policies = @EnableEviction.EvictionPolicy(regionNames = "Orders",
maximum = 10,
action = EvictionActionType.LOCAL_DESTROY,
type = EvictionPolicyType.ENTRY_COUNT))
@EnableEviction(policies = @EnableEviction.EvictionPolicy(regionNames = "Orders", maximum = 10,
action = EvictionActionType.LOCAL_DESTROY, type = EvictionPolicyType.ENTRY_COUNT))
public class ExpirationEvictionServerConfig {
@Bean
@@ -63,9 +65,9 @@ public class ExpirationEvictionServerConfig {
@Bean("Products")
public ReplicatedRegionFactoryBean<Long, Product> createProductRegion(GemFireCache gemFireCache,
@Qualifier("IDLE") CustomExpiry<Long, Product> idleExpiry,
@Qualifier("TTL") CustomExpiry<Long, Product> ttlExpiry) {
final ReplicatedRegionFactoryBean<Long, Product> regionFactoryBean = new ReplicatedRegionFactoryBean<>();
@Qualifier("IDLE") CustomExpiry<Long, Product> idleExpiry,
@Qualifier("TTL") CustomExpiry<Long, Product> ttlExpiry) {
ReplicatedRegionFactoryBean<Long, Product> regionFactoryBean = new ReplicatedRegionFactoryBean<>();
regionFactoryBean.setCache(gemFireCache);
regionFactoryBean.setScope(Scope.DISTRIBUTED_ACK);
regionFactoryBean.setDataPolicy(DataPolicy.REPLICATE);
@@ -77,7 +79,7 @@ public class ExpirationEvictionServerConfig {
@Bean("Customers")
public ReplicatedRegionFactoryBean<Long, Customer> createCustomerRegion(GemFireCache gemFireCache) {
final ReplicatedRegionFactoryBean<Long, Customer> regionFactoryBean = new ReplicatedRegionFactoryBean<>();
ReplicatedRegionFactoryBean<Long, Customer> regionFactoryBean = new ReplicatedRegionFactoryBean<>();
regionFactoryBean.setCache(gemFireCache);
regionFactoryBean.setScope(Scope.DISTRIBUTED_ACK);
regionFactoryBean.setDataPolicy(DataPolicy.REPLICATE);
@@ -87,7 +89,7 @@ public class ExpirationEvictionServerConfig {
@Bean("Orders")
public ReplicatedRegionFactoryBean<Long, Order> createOrderRegion(GemFireCache gemFireCache) {
final ReplicatedRegionFactoryBean<Long, Order> regionFactoryBean = new ReplicatedRegionFactoryBean<>();
ReplicatedRegionFactoryBean<Long, Order> regionFactoryBean = new ReplicatedRegionFactoryBean<>();
regionFactoryBean.setCache(gemFireCache);
regionFactoryBean.setScope(Scope.DISTRIBUTED_ACK);
regionFactoryBean.setDataPolicy(DataPolicy.REPLICATE);

View File

@@ -20,12 +20,14 @@ import org.springframework.context.annotation.Profile;
import org.springframework.data.gemfire.config.annotation.EnableExpiration;
import org.springframework.data.gemfire.expiration.ExpirationActionType;
/**
* @author Patrick Johnson
*/
@Profile("!default")
@Configuration
@EnableExpiration(policies = {
@EnableExpiration.ExpirationPolicy(timeout = 4, action = ExpirationActionType.DESTROY,
regionNames = {"Customers"}, types = {EnableExpiration.ExpirationType.TIME_TO_LIVE}),
@EnableExpiration.ExpirationPolicy(timeout = 2, action = ExpirationActionType.DESTROY,
regionNames = {"Customers"}, types = {EnableExpiration.ExpirationType.IDLE_TIMEOUT})})
public class ExpirationPolicyConfig {
}
regionNames = { "Customers" }, types = { EnableExpiration.ExpirationType.TIME_TO_LIVE }),
@EnableExpiration.ExpirationPolicy(timeout = 1, action = ExpirationActionType.DESTROY,
regionNames = { "Customers" }, types = { EnableExpiration.ExpirationType.IDLE_TIMEOUT }) })
public class ExpirationPolicyConfig {}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.expiration.eviction;
import lombok.Data;
@@ -31,10 +30,11 @@ import java.io.Serializable;
* @author Patrick Johnson
*/
@Data
@IdleTimeoutExpiration(action = "DESTROY", timeout = "2")
@TimeToLiveExpiration(action = "DESTROY", timeout = "4")
@IdleTimeoutExpiration(action = "DESTROY", timeout = "1")
@TimeToLiveExpiration(action = "DESTROY", timeout = "2")
@Region("Orders")
public class Order implements Serializable {
@Id
private Long id;
private Long total;
@@ -47,4 +47,4 @@ public class Order implements Serializable {
this.billingAddress = address;
this.shippingAddress = address;
}
}
}

View File

@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.expiration.eviction;
import org.springframework.data.gemfire.mapping.annotation.Region;
import org.springframework.data.repository.CrudRepository;
/**
* @author Patrick Johnson
*/
@Region("Orders")
public interface OrderRepository extends CrudRepository<Order, Long> {
}
public interface OrderRepository extends CrudRepository<Order, Long> {}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.expiration.eviction;
import lombok.Data;

View File

@@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.expiration.eviction;
import org.springframework.data.repository.CrudRepository;
public interface ProductRepository extends CrudRepository<Product, Long> {
}
/**
* @author Patrick Johnson
*/
public interface ProductRepository extends CrudRepository<Product, Long> {}

View File

@@ -15,70 +15,68 @@
*/
package example.springdata.geode.server.expiration.eviction;
import com.github.javafaker.Faker;
import com.jayway.awaitility.Awaitility;
import static org.assertj.core.api.Assertions.*;
import lombok.extern.apachecommons.CommonsLog;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import org.awaitility.Awaitility;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
import com.github.javafaker.Faker;
/**
* @author Patrick Johnson
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = ExpirationEvictionServer.class)
@SpringBootTest
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@CommonsLog
public class EntityDefinedExpirationTests {
@Autowired
private OrderRepository orderRepository;
@Autowired private OrderRepository orderRepository;
@Autowired
Faker faker;
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired Faker faker;
@Test
public void entityDefinedExpirationIsConfiguredCorrectly() {
orderRepository.save(new Order(1L, 50L, new Address(faker.address().streetAddress(), faker.address().city(), faker.address().country())));
orderRepository.save(new Order(1L, 50L,
new Address(faker.address().streetAddress(), faker.address().city(), faker.address().country())));
assertThat(orderRepository.count()).isEqualTo(1);
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss:SSS");
logger.info("Starting TTL wait period: " + simpleDateFormat.format(new Date()));
//Due to the constant "getting" of the entry, the idle expiry timeout will not be met and the time-to-live
log.info("Starting TTL wait period: " + Instant.now());
// Due to the constant "getting" of the entry, the idle expiry timeout will not be met and the time-to-live
// will be used.
Awaitility.await()
.pollInterval(1, TimeUnit.SECONDS)
.atMost(10, TimeUnit.SECONDS)
Awaitility.await().pollInterval(1, TimeUnit.SECONDS).atMost(10, TimeUnit.SECONDS)
.until(() -> !orderRepository.findById(1L).isPresent());
assertThat(orderRepository.count()).isEqualTo(0);
logger.info("Ending TTL wait period: " + simpleDateFormat.format(new Date()));
log.info("Ending TTL wait period: " + Instant.now());
orderRepository.save(new Order(1L, 50L, new Address(faker.address().streetAddress(), faker.address().city(), faker.address().country())));
orderRepository.save(new Order(1L, 50L,
new Address(faker.address().streetAddress(), faker.address().city(), faker.address().country())));
assertThat(orderRepository.count()).isEqualTo(1);
logger.info("Starting Idle wait period: " + simpleDateFormat.format(new Date()));
log.info("Starting Idle wait period: " + Instant.now());
//Due to the delay in "getting" the entry, the idle timeout of 2s should delete the entry.
Awaitility.await()
.pollDelay(2, TimeUnit.SECONDS)
.pollInterval(100, TimeUnit.MILLISECONDS)
.atMost(10, TimeUnit.SECONDS)
.until(() -> !orderRepository.findById(1L).isPresent());
// Due to the delay in "getting" the entry, the idle timeout of 2s should delete the entry.
Awaitility.await().pollDelay(2, TimeUnit.SECONDS).pollInterval(100, TimeUnit.MILLISECONDS)
.atMost(10, TimeUnit.SECONDS).until(() -> !orderRepository.findById(1L).isPresent());
assertThat(orderRepository.count()).isEqualTo(0);
logger.info("Ending Idle wait period: " + simpleDateFormat.format(new Date()));
log.info("Ending Idle wait period: " + Instant.now());
}
}

View File

@@ -13,68 +13,64 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.expiration.eviction;
import com.github.javafaker.Faker;
import com.jayway.awaitility.Awaitility;
import static org.assertj.core.api.Assertions.*;
import lombok.extern.apachecommons.CommonsLog;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import org.awaitility.Awaitility;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
import com.github.javafaker.Faker;
/**
* @author Patrick Johnson
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = ExpirationEvictionServer.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@SpringBootTest(classes = ExpirationEvictionServer.class)
@ActiveProfiles("expiration_policy")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@CommonsLog
public class ExpirationEvictionServerTests {
@Autowired
private CustomerRepository customerRepository;
@Autowired private CustomerRepository customerRepository;
@Autowired
private ProductRepository productRepository;
@Autowired private ProductRepository productRepository;
@Autowired
private OrderRepository orderRepository;
@Autowired private OrderRepository orderRepository;
@Autowired
Faker faker;
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired Faker faker;
@Test
public void cacheDefinedExpirationIsConfiguredCorrectly() {
customerRepository.save(new Customer(1L, new EmailAddress(faker.internet().emailAddress()),
faker.name().firstName(), faker.name().lastName(),
new Address(faker.address().streetAddress(), faker.address().city(), faker.address().country())));
assertThat(customerRepository.count()).isEqualTo(1);
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss:SSS");
logger.info("Starting TTL wait period: " + simpleDateFormat.format(new Date()));
//Due to the constant "getting" of the entry, the idle expiry timeout will not be met and the time-to-live
log.info(String.format("Starting TTL wait period: %s", Instant.now()));
// Due to the constant "getting" of the entry, the idle expiry timeout will not be met and the time-to-live
// will be used.
Awaitility.await()
.pollInterval(1, TimeUnit.SECONDS)
.atMost(10, TimeUnit.SECONDS)
Awaitility.await().pollInterval(1, TimeUnit.SECONDS).atMost(10, TimeUnit.SECONDS)
.until(() -> !customerRepository.findById(1L).isPresent());
assertThat(customerRepository.count()).isEqualTo(0);
logger.info("Ending TTL wait period: " + simpleDateFormat.format(new Date()));
log.info(String.format("Ending TTL wait period: %s", Instant.now()));
customerRepository.save(new Customer(1L, new EmailAddress(faker.internet().emailAddress()),
faker.name().firstName(), faker.name().lastName(),
@@ -82,18 +78,15 @@ public class ExpirationEvictionServerTests {
assertThat(customerRepository.count()).isEqualTo(1);
logger.info("Starting Idle wait period: " + simpleDateFormat.format(new Date()));
log.info(String.format("Starting Idle wait period: %s", Instant.now()));
//Due to the delay in "getting" the entry, the idle timeout of 2s should delete the entry.
Awaitility.await()
.pollDelay(2, TimeUnit.SECONDS)
.pollInterval(100, TimeUnit.MILLISECONDS)
.atMost(10, TimeUnit.SECONDS)
.until(() -> !customerRepository.findById(1L).isPresent());
// Due to the delay in "getting" the entry, the idle timeout of 2s should delete the entry.
Awaitility.await().pollDelay(2, TimeUnit.SECONDS).pollInterval(100, TimeUnit.MILLISECONDS)
.atMost(10, TimeUnit.SECONDS).until(() -> !customerRepository.findById(1L).isPresent());
assertThat(customerRepository.count()).isEqualTo(0);
logger.info("Ending Idle wait period: " + simpleDateFormat.format(new Date()));
log.info(String.format("Ending Idle wait period: %s", Instant.now()));
}
@Test
@@ -102,36 +95,29 @@ public class ExpirationEvictionServerTests {
assertThat(productRepository.count()).isEqualTo(1);
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss:SSS");
logger.info("Starting TTL wait period: " + simpleDateFormat.format(new Date()));
//Due to the constant "getting" of the entry, the idle expiry timeout will not be met and the time-to-live
log.info(String.format("Starting TTL wait period: %s", Instant.now()));
// Due to the constant "getting" of the entry, the idle expiry timeout will not be met and the time-to-live
// will be used.
Awaitility.await()
.pollInterval(1, TimeUnit.SECONDS)
.atMost(10, TimeUnit.SECONDS)
Awaitility.await().pollInterval(1, TimeUnit.SECONDS).atMost(10, TimeUnit.SECONDS)
.until(() -> !productRepository.findById(3L).isPresent());
assertThat(productRepository.count()).isEqualTo(0);
logger.info("Ending TTL wait period: " + simpleDateFormat.format(new Date()));
log.info("Ending TTL wait period: " + Instant.now());
productRepository.save(new Product(3L, "MacBook Pro", BigDecimal.valueOf(20), "A cool computing device"));
assertThat(productRepository.count()).isEqualTo(1);
logger.info("Starting Idle wait period: " + simpleDateFormat.format(new Date()));
log.info(String.format("Starting Idle wait period: %s", Instant.now()));
//Due to the delay in "getting" the entry, the idle timeout of 2s should delete the entry.
Awaitility.await()
.pollDelay(2, TimeUnit.SECONDS)
.pollInterval(100, TimeUnit.MILLISECONDS)
.atMost(10, TimeUnit.SECONDS)
.until(() -> !productRepository.findById(3L).isPresent());
// Due to the delay in "getting" the entry, the idle timeout of 2s should delete the entry.
Awaitility.await().pollDelay(2, TimeUnit.SECONDS).pollInterval(100, TimeUnit.MILLISECONDS)
.atMost(10, TimeUnit.SECONDS).until(() -> !productRepository.findById(3L).isPresent());
assertThat(productRepository.count()).isEqualTo(0);
logger.info("Ending Idle wait period: " + simpleDateFormat.format(new Date()));
log.info(String.format("Ending Idle wait period: %s", Instant.now()));
}
@Test
@@ -139,10 +125,11 @@ public class ExpirationEvictionServerTests {
final int evictionThreshold = 10;
for (long i = 0; i < evictionThreshold + 1; i++) {
orderRepository.save(new Order(i, i, new Address(faker.address().streetName(), faker.address().city(), faker.address().country())));
orderRepository.save(new Order(i, i,
new Address(faker.address().streetName(), faker.address().city(), faker.address().country())));
}
assertThat(orderRepository.count()).isEqualTo(evictionThreshold);
orderRepository.deleteAll();
}
}
}

View File

@@ -2,17 +2,14 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>example.springdata.geode</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>function-invocation</artifactId>
<version>1.0-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<dependencies>
<parent>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
</dependencies>
<artifactId>function-invocation</artifactId>
</project>
</project>

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function;
import lombok.Data;
@@ -29,6 +28,7 @@ import java.io.Serializable;
*/
@Data
public class Address implements Serializable {
private String street;
private String city;
private String country;

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function;
import lombok.Data;
@@ -55,4 +54,4 @@ public class Customer implements Serializable {
public void add(Address address) {
this.addresses.add(address);
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function;
import lombok.Data;
@@ -28,10 +27,11 @@ import java.io.Serializable;
*/
@Data
public class EmailAddress implements Serializable {
private String value;
public EmailAddress(String value) {
this.value = value;
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function;
import lombok.Data;
@@ -41,4 +40,4 @@ public class LineItem implements Serializable {
public BigDecimal calcTotal() {
return product.getPrice().multiply(BigDecimal.valueOf(amount));
}
}
}

View File

@@ -34,6 +34,7 @@ import java.util.List;
@Data
@Region("Orders")
public class Order implements Serializable {
@Id
private Long id;
private Long customerId;
@@ -70,4 +71,4 @@ public class Order implements Serializable {
public void add(LineItem lineItem) {
lineItems.add(lineItem);
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function;
import lombok.Data;

View File

@@ -13,18 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.client;
import example.springdata.geode.client.function.Customer;
import org.springframework.data.gemfire.function.annotation.FunctionId;
import org.springframework.data.gemfire.function.annotation.OnRegion;
import java.util.List;
import org.springframework.data.gemfire.function.annotation.FunctionId;
import org.springframework.data.gemfire.function.annotation.OnRegion;
/**
* @author Patrick Johnson
*/
@OnRegion(region = "Customers")
public interface CustomerFunctionExecutions {
@FunctionId("listConsumersForEmailAddressesFnc")
List<List<Customer>> listAllCustomersForEmailAddress(String... emailAddresses);
}
}

View File

@@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.client;
import example.springdata.geode.client.function.Customer;
import java.util.List;
import org.springframework.data.gemfire.mapping.annotation.ClientRegion;
import org.springframework.data.gemfire.repository.Query;
import org.springframework.data.gemfire.repository.query.annotation.Hint;
@@ -24,8 +26,9 @@ import org.springframework.data.gemfire.repository.query.annotation.Limit;
import org.springframework.data.gemfire.repository.query.annotation.Trace;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
/**
* @author Patrick Johnson
*/
@ClientRegion("Customers")
public interface CustomerRepository extends CrudRepository<Customer, Long> {
@@ -39,4 +42,4 @@ public interface CustomerRepository extends CrudRepository<Customer, Long> {
@Limit(100)
@Query("select * from /Customers customer where customer.firstName = $1")
List<Customer> findByFirstNameUsingIndex(String firstName);
}
}

View File

@@ -13,14 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.client;
import example.springdata.geode.client.function.Customer;
import example.springdata.geode.client.function.Order;
import example.springdata.geode.client.function.Product;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
@@ -35,11 +36,11 @@ import org.springframework.data.gemfire.transaction.config.EnableGemfireCacheTra
* @author Udo Kohlmeyer
* @author Patrick Johnson
*/
@Configuration
@EnableGemfireRepositories(basePackageClasses = CustomerRepository.class)
@EnableGemfireFunctionExecutions(basePackageClasses = CustomerFunctionExecutions.class)
@ClientCacheApplication(name = "FunctionInvocationClient", logLevel = "error", pingInterval = 5000L, readTimeout = 15000, retryAttempts = 1)
@ClientCacheApplication(name = "FunctionInvocationClient", logLevel = "error", pingInterval = 5000L,
readTimeout = 15000, retryAttempts = 1)
@EnableGemfireCacheTransactions
public class FunctionInvocationClientApplicationConfig {
@@ -69,4 +70,4 @@ public class FunctionInvocationClientApplicationConfig {
clientRegionFactoryBean.setShortcut(ClientRegionShortcut.PROXY);
return clientRegionFactoryBean;
}
}
}

View File

@@ -13,18 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.client;
import org.springframework.data.gemfire.function.annotation.FunctionId;
import org.springframework.data.gemfire.function.annotation.OnRegion;
import java.math.BigDecimal;
import java.util.List;
import org.springframework.data.gemfire.function.annotation.FunctionId;
import org.springframework.data.gemfire.function.annotation.OnRegion;
/**
* @author Patrick Johnson
*/
@OnRegion(region = "Orders")
public interface OrderFunctionExecutions {
@FunctionId("sumPricesForAllProductsForOrderFnc")
List<BigDecimal> sumPricesForAllProductsForOrder(Long orderId);
}
}

View File

@@ -13,14 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.client;
import example.springdata.geode.client.function.Order;
import org.springframework.data.gemfire.mapping.annotation.ClientRegion;
import org.springframework.data.repository.CrudRepository;
/**
* @author Patrick Johnson
*/
@ClientRegion("Orders")
public interface OrderRepository extends CrudRepository<Order, Long> {
}
public interface OrderRepository extends CrudRepository<Order, Long> {}

View File

@@ -13,18 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.client;
import org.springframework.data.gemfire.function.annotation.FunctionId;
import org.springframework.data.gemfire.function.annotation.OnRegion;
import java.math.BigDecimal;
import java.util.List;
import org.springframework.data.gemfire.function.annotation.FunctionId;
import org.springframework.data.gemfire.function.annotation.OnRegion;
/**
* @author Patrick Johnson
*/
@OnRegion(region = "Products")
public interface ProductFunctionExecutions {
@FunctionId("sumPricesForAllProductsFnc")
List<BigDecimal> sumPricesForAllProducts();
}
}

View File

@@ -13,14 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.client;
import example.springdata.geode.client.function.Product;
import org.springframework.data.gemfire.mapping.annotation.ClientRegion;
import org.springframework.data.repository.CrudRepository;
/**
* @author Patrick Johnson
*/
@ClientRegion("Products")
public interface ProductRepository extends CrudRepository<Product, Long> {
}
public interface ProductRepository extends CrudRepository<Product, Long> {}

View File

@@ -13,25 +13,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.server;
import example.springdata.geode.client.function.Customer;
import org.springframework.data.gemfire.function.annotation.GemfireFunction;
import org.springframework.data.gemfire.function.annotation.RegionData;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.data.gemfire.function.annotation.GemfireFunction;
import org.springframework.data.gemfire.function.annotation.RegionData;
import org.springframework.stereotype.Component;
/**
* @author Patrick Johnson
*/
@Component
public class CustomerFunctions {
@GemfireFunction(id = "listConsumersForEmailAddressesFnc", HA = true, optimizeForWrite = true, batchSize = 3, hasResult = true)
@GemfireFunction(id = "listConsumersForEmailAddressesFnc", HA = true, optimizeForWrite = true, batchSize = 3,
hasResult = true)
public List<Customer> listAllCustomersForEmailAddress(@RegionData Map<Long, Customer> customerData,
String... emailAddresses) {
String... emailAddresses) {
List<String> emailAddressesAsList = Arrays.asList(emailAddresses);
List<Customer> collect = customerData.values().parallelStream()
.filter((customer) -> emailAddressesAsList.contains(customer.getEmailAddress().getValue()))

View File

@@ -13,14 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.server;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication(scanBasePackageClasses = FunctionServerApplicationConfig.class)
/**
* @author Patrick Johnson
*/
@SpringBootApplication
public class FunctionServer {
public static void main(String[] args) {

View File

@@ -13,16 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.server;
import example.springdata.geode.client.function.Customer;
import example.springdata.geode.client.function.Order;
import example.springdata.geode.client.function.Product;
import example.springdata.geode.client.function.client.CustomerRepository;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.Scope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@@ -34,6 +35,9 @@ import org.springframework.data.gemfire.config.annotation.EnableManager;
import org.springframework.data.gemfire.function.config.EnableGemfireFunctions;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
/**
* @author Patrick Johnson
*/
@Configuration
@ComponentScan(basePackageClasses = CustomerFunctions.class)
@EnableGemfireFunctions

View File

@@ -13,17 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.server;
import example.springdata.geode.client.function.Order;
import org.springframework.data.gemfire.function.annotation.GemfireFunction;
import org.springframework.data.gemfire.function.annotation.RegionData;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.Map;
import org.springframework.data.gemfire.function.annotation.GemfireFunction;
import org.springframework.data.gemfire.function.annotation.RegionData;
import org.springframework.stereotype.Component;
/**
* @author Patrick Johnson
*/
@Component
public class OrderFunctions {

View File

@@ -13,21 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.server;
import example.springdata.geode.client.function.Product;
import org.springframework.data.gemfire.function.annotation.GemfireFunction;
import org.springframework.data.gemfire.function.annotation.RegionData;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.Map;
import org.springframework.data.gemfire.function.annotation.GemfireFunction;
import org.springframework.data.gemfire.function.annotation.RegionData;
import org.springframework.stereotype.Component;
/**
* @author Patrick Johnson
*/
@Component
public class ProductFunctions {
@GemfireFunction(id = "sumPricesForAllProductsFnc", HA = true, optimizeForWrite = false, hasResult = true)
@GemfireFunction(id = "sumPricesForAllProductsFnc", HA = true, hasResult = true)
public BigDecimal sumPricesForAllProductsFnc(@RegionData Map<Long, Product> productData) {
return productData.values().stream().map(Product::getPrice).reduce(BigDecimal::add).get();
}

View File

@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.function.client;
import static org.assertj.core.api.Assertions.*;
import example.springdata.geode.client.function.Address;
import example.springdata.geode.client.function.Customer;
import example.springdata.geode.client.function.EmailAddress;
@@ -23,19 +24,8 @@ import example.springdata.geode.client.function.LineItem;
import example.springdata.geode.client.function.Order;
import example.springdata.geode.client.function.Product;
import example.springdata.geode.client.function.server.FunctionServer;
import org.apache.geode.cache.Region;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import lombok.extern.apachecommons.CommonsLog;
import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
@@ -43,41 +33,43 @@ import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import static org.assertj.core.api.Assertions.assertThat;
import javax.annotation.Resource;
import org.apache.geode.cache.Region;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author Patrick Johnson
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = FunctionInvocationClientApplicationConfig.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@SpringBootTest(classes = FunctionInvocationClientApplicationConfig.class)
@CommonsLog
public class FunctionInvocationClientTests extends ForkingClientServerIntegrationTestsSupport {
@Autowired
private CustomerRepository customerRepository;
@Autowired private CustomerRepository customerRepository;
@Autowired
private OrderRepository orderRepository;
@Autowired private OrderRepository orderRepository;
@Autowired
private ProductRepository productRepository;
@Autowired private ProductRepository productRepository;
@Autowired
private CustomerFunctionExecutions customerFunctionExecutions;
@Autowired private CustomerFunctionExecutions customerFunctionExecutions;
@Autowired
private OrderFunctionExecutions orderFunctionExecutions;
@Autowired private OrderFunctionExecutions orderFunctionExecutions;
@Autowired
private ProductFunctionExecutions productFunctionExecutions;
@Autowired private ProductFunctionExecutions productFunctionExecutions;
@Resource(name = "Customers")
private Region<Long, Customer> customers;
@Resource(name = "Customers") private Region<Long, Customer> customers;
@Resource(name = "Orders")
private Region<Long, Order> orders;
@Resource(name = "Orders") private Region<Long, Order> orders;
@Resource(name = "Products")
private Region<Long, Product> products;
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource(name = "Products") private Region<Long, Product> products;
@BeforeClass
public static void setup() throws IOException {
@@ -90,56 +82,60 @@ public class FunctionInvocationClientTests extends ForkingClientServerIntegratio
List<Customer> cust = customerFunctionExecutions.listAllCustomersForEmailAddress("2@2.com", "3@3.com").get(0);
assertThat(cust.size()).isEqualTo(2);
logger.info("All customers for emailAddresses:3@3.com,2@2.com using function invocation: \n\t " + cust);
log.info("All customers for emailAddresses:3@3.com,2@2.com using function invocation: \n\t " + cust);
createProducts();
BigDecimal sum = productFunctionExecutions.sumPricesForAllProducts().get(0);
assertThat(sum).isEqualTo(BigDecimal.valueOf(1499.97));
logger.info("Running function to sum up all product prices: \n\t" + sum);
log.info("Running function to sum up all product prices: \n\t" + sum);
createOrders();
sum = orderFunctionExecutions.sumPricesForAllProductsForOrder(1L).get(0);
assertThat(sum).isGreaterThanOrEqualTo(BigDecimal.valueOf(99.99));
logger.info("Running function to sum up all order lineItems prices for order 1: \n\t" + sum);
log.info("Running function to sum up all order lineItems prices for order 1: \n\t" + sum);
Order order = orderRepository.findById(1L).get();
logger.info("For order: \n\t " + order);
log.info("For order: \n\t " + order);
}
public void createCustomerData() {
logger.info("Inserting 3 entries for keys: 1, 2, 3");
log.info("Inserting 3 entries for keys: 1, 2, 3");
customerRepository.save(new Customer(1L, new EmailAddress("2@2.com"), "John", "Smith"));
customerRepository.save(new Customer(2L, new EmailAddress("3@3.com"), "Frank", "Lamport"));
customerRepository.save(new Customer(3L, new EmailAddress("5@5.com"), "Jude", "Simmons"));
assertThat(customers.keySetOnServer().size()).isEqualTo(3);
}
public void createProducts() {
productRepository.save(new Product(1L, "Apple iPod", new BigDecimal("99.99"),
"An Apple portable music player"));
productRepository.save(new Product(2L, "Apple iPad", new BigDecimal("499.99"),
"An Apple tablet device"));
Product macbook = new Product(3L, "Apple macBook", new BigDecimal("899.99"),
"An Apple notebook computer");
productRepository.save(new Product(1L, "Apple iPod", new BigDecimal("99.99"), "An Apple portable music player"));
productRepository.save(new Product(2L, "Apple iPad", new BigDecimal("499.99"), "An Apple tablet device"));
Product macbook = new Product(3L, "Apple macBook", new BigDecimal("899.99"), "An Apple notebook computer");
macbook.addAttribute("warranty", "included");
productRepository.save(macbook);
assertThat(products.keySetOnServer().size()).isEqualTo(3);
}
public void createOrders() {
Random random = new Random();
Address address = new Address("it", "doesn't", "matter");
LongStream.rangeClosed(1, 100).forEach((orderId) ->
LongStream.rangeClosed(1, 3).forEach((customerId) -> {
Order order = new Order(orderId, customerId, address);
IntStream.rangeClosed(0, random.nextInt(3) + 1).forEach((lineItemCount) -> {
int quantity = random.nextInt(3) + 1;
long productId = random.nextInt(3) + 1;
order.add(new LineItem(productRepository.findById(productId).get(), quantity));
});
orderRepository.save(order);
}));
LongStream.rangeClosed(1, 100).forEach((orderId) -> LongStream.rangeClosed(1, 3).forEach((customerId) -> {
Order order = new Order(orderId, customerId, address);
IntStream.rangeClosed(0, random.nextInt(3) + 1).forEach((lineItemCount) -> {
int quantity = random.nextInt(3) + 1;
long productId = random.nextInt(3) + 1;
order.add(new LineItem(productRepository.findById(productId).get(), quantity));
});
orderRepository.save(order);
}));
assertThat(orders.keySetOnServer().size()).isEqualTo(100);
}
}
}

View File

@@ -2,127 +2,78 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion>
<groupId>example.springdata.geode</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>1.0-SNAPSHOT</version>
<url>https://github.com/spring-projects/spring-geode-examples</url>
<packaging>pom</packaging>
<artifactId>spring-data-geode-examples</artifactId>
<packaging>pom</packaging>
<modules>
<module>events</module>
<module>expiration-eviction</module>
<module>function-invocation</module>
<module>queries</module>
<module>security</module>
<module>storage</module>
<module>transactions</module>
<module>wan</module>
</modules>
<parent>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-examples</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
<organization>
<name>SpringSource</name>
<url>http://springsource.org</url>
</organization>
<name>Spring Data for Apache Geode - Examples</name>
<description>Sample projects for Spring Data for Apache Geode</description>
<url>https://projects.spring.io/spring-data-geode</url>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<modules>
<module>events</module>
<module>expiration-eviction</module>
<module>function-invocation</module>
<module>queries</module>
<module>security</module>
<module>storage</module>
<module>transactions</module>
<parent>
<groupId>org.springframework.data.build</groupId>
<artifactId>spring-data-parent</artifactId>
<version>2.2.5.BUILD-SNAPSHOT</version>
</parent>
<!-- WAN Server does not stop. Disabled for now -->
<!-- <module>wan</module> -->
</modules>
<properties>
<log4j.version>2.12.1</log4j.version>
<slf4j.log4j.version>1.7.28</slf4j.log4j.version>
<spring.boot.version>2.2.4.BUILD-SNAPSHOT</spring.boot.version>
<spring.test.data.geode.version>0.0.12.RELEASE</spring.test.data.geode.version>
<spring.data.releasetrain.version>Moore-RELEASE</spring.data.releasetrain.version>
</properties>
<properties>
<spring.test.data.geode.version>0.0.12.RELEASE</spring.test.data.geode.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>${spring.data.releasetrain.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>4.0.2</version>
</dependency>
<dependency>
<groupId>org.iq80.snappy</groupId>
<artifactId>snappy</artifactId>
<version>0.4</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-geode</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-geode-test</artifactId>
<version>${spring.test.data.geode.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring.boot.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.log4j.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-geode</artifactId>
</dependency>
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-geode-test</artifactId>
<version>${spring.test.data.geode.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
</project>

View File

@@ -2,23 +2,22 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>example.springdata.geode</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion>
<groupId>example.springdata.geode.client</groupId>
<artifactId>queries</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>3.1.6</version>
<scope>test</scope>
</dependency>
</dependencies>
<parent>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
</project>
<artifactId>queries</artifactId>
<dependencies>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -33,11 +33,10 @@ import java.io.Serializable;
@Data
@PartitionRegion(name = "Customers")
public class Customer implements Serializable {
@Id
private Long id;
private EmailAddress emailAddress;
private String firstName;
@LuceneIndexed(name = "lastName_lucene")
@@ -49,4 +48,4 @@ public class Customer implements Serializable {
this.firstName = firstName;
this.lastName = lastName;
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.queries;
import lombok.Data;
@@ -28,10 +27,11 @@ import java.io.Serializable;
*/
@Data
public class EmailAddress implements Serializable {
private String value;
public EmailAddress(String value) {
this.value = value;
}
}
}

View File

@@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.queries.client;
import example.springdata.geode.client.queries.Customer;
import java.util.List;
import org.springframework.data.gemfire.mapping.annotation.ClientRegion;
import org.springframework.data.gemfire.repository.Query;
import org.springframework.data.gemfire.repository.query.annotation.Hint;
@@ -24,10 +26,12 @@ import org.springframework.data.gemfire.repository.query.annotation.Limit;
import org.springframework.data.gemfire.repository.query.annotation.Trace;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
/**
* @author Patrick Johnson
*/
@ClientRegion(name = "Customers")
public interface CustomerRepository extends CrudRepository<Customer, Long> {
@Trace
@Limit(100)
@Hint("emailAddressIndex")

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.queries.client;
import org.apache.geode.cache.GemFireCache;
@@ -28,9 +27,13 @@ import org.springframework.data.gemfire.config.annotation.EnableContinuousQuerie
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
import org.springframework.data.gemfire.search.lucene.LuceneTemplate;
/**
* @author Patrick Johnson
*/
@Configuration
@EnableGemfireRepositories(basePackageClasses = CustomerRepository.class)
@ClientCacheApplication(name = "CQClientCache", logLevel = "error", pingInterval = 5000L, readTimeout = 15000, subscriptionEnabled = true, readyForEvents = true)
@EnableGemfireRepositories
@ClientCacheApplication(name = "CQClientCache", logLevel = "error", pingInterval = 5000L, readTimeout = 15000,
subscriptionEnabled = true, readyForEvents = true)
@EnableContinuousQueries
@EnableClusterDefinedRegions(clientRegionShortcut = ClientRegionShortcut.PROXY)
public class QueryClientConfig {
@@ -45,4 +48,4 @@ public class QueryClientConfig {
LuceneTemplate createCustomerLuceneTemplate() {
return new LuceneTemplate("lastName_lucene", "/Customers");
}
}
}

View File

@@ -13,17 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.queries.server;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication(scanBasePackageClasses = QueryServerConfig.class)
/**
* @author Patrick Johnson
*/
@SpringBootApplication
public class QueryServer {
public static void main(String[] args) {
new SpringApplicationBuilder(QueryServer.class).web(WebApplicationType.NONE).build().run(args);
}
}
}

View File

@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.queries.server;
import example.springdata.geode.client.queries.Customer;
import example.springdata.geode.client.queries.client.CustomerRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
@@ -27,6 +27,9 @@ import org.springframework.data.gemfire.config.annotation.EnableIndexing;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
import org.springframework.data.gemfire.search.lucene.LuceneTemplate;
/**
* @author Patrick Johnson
*/
@Configuration
@CacheServerApplication(logLevel = "error")
@EnableGemfireRepositories(basePackageClasses = CustomerRepository.class)
@@ -39,4 +42,4 @@ public class QueryServerConfig {
LuceneTemplate createCustomerLuceneTemplate() {
return new LuceneTemplate("lastName_lucene", "/Customers");
}
}
}

View File

@@ -13,12 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.queries;
import static org.assertj.core.api.Assertions.*;
import example.springdata.geode.client.queries.client.CustomerRepository;
import example.springdata.geode.client.queries.client.QueryClientConfig;
import example.springdata.geode.client.queries.server.QueryServer;
import lombok.extern.apachecommons.CommonsLog;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Resource;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.lucene.LuceneResultStruct;
import org.apache.geode.cache.query.CqEvent;
@@ -27,8 +37,7 @@ import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.gemfire.GemfireTemplate;
@@ -36,41 +45,28 @@ import org.springframework.data.gemfire.listener.ContinuousQueryListenerContaine
import org.springframework.data.gemfire.listener.annotation.ContinuousQuery;
import org.springframework.data.gemfire.search.lucene.LuceneTemplate;
import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Patrick Johnson
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = QueryClientConfig.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@SpringBootTest(classes = QueryClientConfig.class)
@CommonsLog
public class QueryTests extends ForkingClientServerIntegrationTestsSupport {
@Autowired
private ContinuousQueryListenerContainer container;
@Autowired private ContinuousQueryListenerContainer container;
@Autowired
private CustomerRepository customerRepository;
@Autowired private CustomerRepository customerRepository;
@Autowired
private GemfireTemplate customerTemplate;
@Autowired private GemfireTemplate customerTemplate;
@Resource(name = "Customers")
private Region<Long, Customer> customers;
@Resource(name = "Customers") private Region<Long, Customer> customers;
@Autowired
private LuceneTemplate luceneTemplate;
@Autowired private LuceneTemplate luceneTemplate;
private AtomicInteger counter = new AtomicInteger(0);
private Logger logger = LoggerFactory.getLogger(this.getClass());
@BeforeClass
public static void setup() throws IOException {
startGemFireServer(QueryServer.class);
@@ -88,14 +84,14 @@ public class QueryTests extends ForkingClientServerIntegrationTestsSupport {
List<LuceneResultStruct<Long, Customer>> lastName = luceneTemplate.query("D*", "lastName", 10);
assertThat(lastName.size()).isEqualTo(3);
logger.info("Customers with last names beginning with 'D':");
lastName.forEach(result -> logger.info(result.getValue().toString()));
log.info("Customers with last names beginning with 'D':");
lastName.forEach(result -> log.info(result.getValue().toString()));
}
@Test
public void oqlQueriesConfiguredCorrectly() {
logger.info("Inserting 3 entries for keys: 1, 2, 3");
log.info("Inserting 3 entries for keys: 1, 2, 3");
Customer john = new Customer(1L, new EmailAddress("2@2.com"), "John", "Smith");
Customer frank = new Customer(2L, new EmailAddress("3@3.com"), "Frank", "Lamport");
Customer jude = new Customer(3L, new EmailAddress("5@5.com"), "Jude", "Simmons");
@@ -106,11 +102,11 @@ public class QueryTests extends ForkingClientServerIntegrationTestsSupport {
Customer customer = customerRepository.findById(2L).get();
assertThat(customer).isEqualTo(frank);
logger.info("Find customer with key=2 using GemFireRepository: " + customer);
log.info("Find customer with key=2 using GemFireRepository: " + customer);
List customerList = customerTemplate.find("select * from /Customers where id=$1", 2L).asList();
assertThat(customerList.size()).isEqualTo(1);
assertThat(customerList.contains(frank)).isTrue();
logger.info("Find customer with key=2 using GemFireTemplate: " + customerList);
log.info("Find customer with key=2 using GemFireTemplate: " + customerList);
customer = new Customer(1L, new EmailAddress("3@3.com"), "Jude", "Smith");
customerRepository.save(customer);
@@ -120,25 +116,33 @@ public class QueryTests extends ForkingClientServerIntegrationTestsSupport {
assertThat(customerList.size()).isEqualTo(2);
assertThat(customerList.contains(frank)).isTrue();
assertThat(customerList.contains(customer)).isTrue();
logger.info("Find customers with emailAddress=3@3.com: " + customerList);
log.info("Find customers with emailAddress=3@3.com: " + customerList);
customerList = customerRepository.findByFirstNameUsingIndex("Frank");
assertThat(customerList.get(0)).isEqualTo(frank);
logger.info("Find customers with firstName=Frank: " + customerList);
log.info("Find customers with firstName=Frank: " + customerList);
customerList = customerRepository.findByFirstNameUsingIndex("Jude");
assertThat(customerList.size()).isEqualTo(2);
assertThat(customerList.contains(jude)).isTrue();
assertThat(customerList.contains(customer)).isTrue();
logger.info("Find customers with firstName=Jude: " + customerList);
log.info("Find customers with firstName=Jude: " + customerList);
}
@Test
public void continuousQueryWorkingCorrectly() {
assertThat(this.customers).isEmpty();
logger.info("Inserting 3 entries for keys: 1, 2, 3");
log.info("Inserting 3 entries for keys: 1, 2, 3");
customerRepository.save(new Customer(1L, new EmailAddress("2@2.com"), "John", "Smith"));
customerRepository.save(new Customer(2L, new EmailAddress("3@3.com"), "Frank", "Lamport"));
customerRepository.save(new Customer(3L, new EmailAddress("5@5.com"), "Jude", "Simmons"));
assertThat(customers.keySetOnServer().size()).isEqualTo(3);
Awaitility.await().atMost(30, TimeUnit.SECONDS).until(() -> this.counter.get() == 3);
@@ -146,7 +150,7 @@ public class QueryTests extends ForkingClientServerIntegrationTestsSupport {
@ContinuousQuery(name = "CustomerCQ", query = "SELECT * FROM /Customers")
public void handleEvent(CqEvent event) {
logger.info("Received message for CQ 'CustomerCQ'" + event);
log.info("Received message for CQ 'CustomerCQ'" + event);
counter.incrementAndGet();
}
@@ -155,4 +159,4 @@ public class QueryTests extends ForkingClientServerIntegrationTestsSupport {
customerRepository.deleteAll(customerRepository.findAll());
container.getQueryService().closeCqs();
}
}
}

View File

@@ -2,41 +2,33 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>example.springdata.geode</groupId>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>1.0-SNAPSHOT</version>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>security</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.codeprimate</groupId>
<artifactId>cp-elements</artifactId>
<version>1.0.0.M5</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
</dependencies>
</project>
</project>

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security;
/**

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security;
import lombok.Data;
@@ -44,4 +43,4 @@ public class Customer implements Serializable {
this.firstName = firstName;
this.lastName = lastName;
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security;
import lombok.Data;
@@ -34,4 +33,4 @@ public class EmailAddress implements Serializable {
this.value = value;
}
}
}

View File

@@ -13,12 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security;
import lombok.Data;
import org.apache.geode.security.ResourcePermission;
import org.cp.elements.lang.Identifiable;
import java.io.Serializable;
import java.util.Arrays;
@@ -26,6 +23,8 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import org.apache.geode.security.ResourcePermission;
/**
* The [Role] class is an Abstract Data Type (ADT) modeling a role of a user (e.g. Admin).
*
@@ -34,11 +33,10 @@ import java.util.Iterator;
* @see Comparable
* @see Iterable
* @see ResourcePermission
* @see org.cp.elements.lang.Identifiable
* @since 1.0.0
*/
@Data
public class Role implements Comparable<Role>, Identifiable<String>, Iterable<ResourcePermission>, Serializable {
public class Role implements Comparable<Role>, Iterable<ResourcePermission>, Serializable {
private String name;
private HashSet<ResourcePermission> permissions = new HashSet<>();
@@ -47,12 +45,10 @@ public class Role implements Comparable<Role>, Identifiable<String>, Iterable<Re
this.name = name;
}
@Override
public String getId() {
return name;
}
@Override
public void setId(String id) {
throw new UnsupportedOperationException("Operation Not Supported");
}
@@ -69,8 +65,8 @@ public class Role implements Comparable<Role>, Identifiable<String>, Iterable<Re
* Determines whether this [Role] has been assigned (granted) the given [permission][ResourcePermission].
*
* @param permission [ResourcePermission] to evaluate.
* @return a boolean value indicating whether this [Role] has been assigned (granted)
* the given [permission][ResourcePermission].
* @return a boolean value indicating whether this [Role] has been assigned (granted) the given
* [permission][ResourcePermission].
* @see ResourcePermission
*/
public boolean hasPermission(ResourcePermission permission) {

View File

@@ -13,12 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security;
import lombok.Data;
import org.apache.geode.security.ResourcePermission;
import org.cp.elements.lang.Identifiable;
import java.io.Serializable;
import java.security.Principal;
@@ -28,8 +25,13 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.apache.geode.security.ResourcePermission;
/**
* @author Patrick Johnson
*/
@Data
public class User implements Comparable<User>, Cloneable, Principal, Serializable, Iterable<Role>, Identifiable<String> {
public class User implements Comparable<User>, Cloneable, Principal, Serializable, Iterable<Role> {
private String name;
private List<Role> roles;
@@ -42,15 +44,13 @@ public class User implements Comparable<User>, Cloneable, Principal, Serializabl
}
public User(String name) {
this(name, new ArrayList<Role>());
this(name, new ArrayList<>());
}
@Override
public void setId(String id) {
throw new UnsupportedOperationException("Operation Not Supported");
}
@Override
public String getId() {
return name;
}
@@ -80,8 +80,7 @@ public class User implements Comparable<User>, Cloneable, Principal, Serializabl
* Determines whether this [User] has been granted (assigned) the given [permission][ResourcePermission].
*
* @param permission [ResourcePermission] to evalute.
* @return a boolean value indicating whether this [User] has been granted (assigned)
* the given [ResourcePermission].
* @return a boolean value indicating whether this [User] has been granted (assigned) the given [ResourcePermission].
* @see ResourcePermission
*/
public boolean hasPermission(ResourcePermission permission) {

View File

@@ -13,14 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security.client;
import example.springdata.geode.client.security.Customer;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
/**
* @author Patrick Johnson
*/
public interface CustomerRepository extends CrudRepository<Customer, Long> {
@Override
List<Customer> findAll();
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security.client;
import example.springdata.geode.client.security.Customer;
@@ -30,4 +29,4 @@ import org.springframework.data.gemfire.repository.config.EnableGemfireRepositor
@ClientCacheApplication(name = "SecurityClient", logLevel = "error", pingInterval = 5000L, readTimeout = 15000, retryAttempts = 1)
@EnableEntityDefinedRegions(basePackageClasses = Customer.class, clientRegionShortcut = ClientRegionShortcut.CACHING_PROXY)
public class SecurityEnabledClientConfiguration {
}
}

View File

@@ -1,3 +1,18 @@
/*
* Copyright 2020 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 example.springdata.geode.client.security.server;
import org.springframework.context.annotation.Configuration;
@@ -7,5 +22,4 @@ import org.springframework.data.gemfire.config.annotation.EnableSecurity;
@Configuration
@EnableSecurity(shiroIniResourcePath = "shiro.ini")
@Profile("shiro-ini-configuration")
public class ApacheShiroIniConfiguration {
}
public class ApacheShiroIniConfiguration {}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security.server;
import example.springdata.geode.client.security.User;
@@ -31,6 +30,7 @@ import java.util.Map;
* @since 1.0.0
*/
public abstract class CachingSecurityRepository implements SecurityRepository {
private Map<String, User> users = new HashMap<>();
@Override

View File

@@ -1,13 +1,28 @@
/*
* Copyright 2020 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 example.springdata.geode.client.security.server;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.gemfire.config.annotation.EnableSecurity;
/**
* @author Patrick Johnson
*/
@Configuration
@EnableSecurity(securityManagerClassName = "example.springdata.geode.client.security.server.SecurityManagerProxy")
@Profile({"default", "geode-security-manager-proxy-configuration"})
public class GeodeIntegratedSecurityProxyConfiguration {
}
@Profile({ "default", "geode-security-manager-proxy-configuration" })
public class GeodeIntegratedSecurityProxyConfiguration {}

View File

@@ -13,42 +13,40 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security.server;
import example.springdata.geode.client.security.Role;
import example.springdata.geode.client.security.User;
import org.apache.geode.security.ResourcePermission;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import lombok.extern.apachecommons.CommonsLog;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@Repository
public class JdbcSecurityRepository extends CachingSecurityRepository implements InitializingBean {
import org.apache.geode.security.ResourcePermission;
private Logger logger = LoggerFactory.getLogger(this.getClass());
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
/**
* @author Patrick Johnson
*/
@Repository
@CommonsLog
public class JdbcSecurityRepository extends CachingSecurityRepository implements InitializingBean {
private final JdbcTemplate jdbcTemplate;
private static final String ROLES_QUERY = "SELECT name FROM geode_security.roles";
private static final String ROLE_PERMISSIONS_QUERY = ""
+ " SELECT rolePerms.resource, rolePerms.operation, rolePerms.region_name, rolePerms.key_name"
+ " FROM geode_security.roles_permissions rolePerms"
+ " INNER JOIN geode_security.roles roles ON roles.id = rolePerms.role_id "
+ " WHERE roles.name = ?";
+ " INNER JOIN geode_security.roles roles ON roles.id = rolePerms.role_id " + " WHERE roles.name = ?";
private static final String USERS_QUERY = "SELECT name, credentials FROM geode_security.users";
private static final String USER_ROLES_QUERY = ""
+ " SELECT roles.name"
+ " FROM geode_security.roles roles"
private static final String USER_ROLES_QUERY = "" + " SELECT roles.name" + " FROM geode_security.roles roles"
+ " INNER JOIN geode_security.users_roles userRoles ON roles.id = userRoles.role_id"
+ " INNER JOIN geode_security.users users ON userRoles.user_id = users.id"
+ " WHERE users.name = ?";
+ " INNER JOIN geode_security.users users ON userRoles.user_id = users.id" + " WHERE users.name = ?";
public JdbcSecurityRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
@@ -61,15 +59,14 @@ public class JdbcSecurityRepository extends CachingSecurityRepository implements
roles.forEach((role) -> {
this.jdbcTemplate.query(ROLE_PERMISSIONS_QUERY, Collections.singleton(role.getName()).toArray(),
(RowMapper<Object>) (resultSet, i) -> role.withPermissions(newResourcePermission(
resultSet.getString(1), resultSet.getString(2),
resultSet.getString(3), resultSet.getString(4))));
(RowMapper<Object>) (resultSet, i) -> role.withPermissions(newResourcePermission(resultSet.getString(1),
resultSet.getString(2), resultSet.getString(3), resultSet.getString(4))));
roleMapping.put(role.getName(), role);
});
List<User> users = this.jdbcTemplate.query(USERS_QUERY, (resultSet, i) ->
createUser(resultSet.getString(1)).withCredentials(resultSet.getString(2)));
List<User> users = this.jdbcTemplate.query(USERS_QUERY,
(resultSet, i) -> createUser(resultSet.getString(1)).withCredentials(resultSet.getString(2)));
users.forEach((role) -> {
this.jdbcTemplate.query(USER_ROLES_QUERY, Collections.singleton(role.getName()).toArray(),
@@ -78,7 +75,7 @@ public class JdbcSecurityRepository extends CachingSecurityRepository implements
save(role);
});
logger.debug("Users {}", users);
log.debug(String.format("Users %s", users));
}
protected ResourcePermission newResourcePermission(String resource, String operation, String region, String key) {

View File

@@ -13,19 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security.server;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication(scanBasePackageClasses = SecurityEnabledServerConfiguration.class)
/**
* @author Patrick Johnson
*/
@SpringBootApplication
public class SecurityEnabledServer {
public static void main(String[] args) {
new SpringApplicationBuilder(SecurityEnabledServer.class)
.web(WebApplicationType.NONE)
.build()
.run(args);
new SpringApplicationBuilder(SecurityEnabledServer.class).web(WebApplicationType.NONE).build().run(args);
}
}
}

View File

@@ -13,11 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security.server;
import example.springdata.geode.client.security.Customer;
import javax.sql.DataSource;
import org.apache.geode.cache.RegionShortcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -29,32 +32,25 @@ import org.springframework.data.gemfire.config.annotation.EnableManager;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
/**
* @author Patrick Johnson
*/
@Configuration
@EnableLocator
@EnableIndexing
@EnableManager
@Import({ApacheShiroIniConfiguration.class, GeodeIntegratedSecurityProxyConfiguration.class})
@Import({ ApacheShiroIniConfiguration.class, GeodeIntegratedSecurityProxyConfiguration.class })
@CacheServerApplication(port = 0, logLevel = "error")
@EnableEntityDefinedRegions(basePackageClasses = Customer.class, serverRegionShortcut = RegionShortcut.REPLICATE)
public class SecurityEnabledServerConfiguration {
@Bean
DataSource hsqlDataSource() {
return new EmbeddedDatabaseBuilder()
.setName("geode_security")
.setScriptEncoding("UTF-8")
.setType(EmbeddedDatabaseType.HSQL)
.addScript("sql/geode-security-schema-ddl.sql")
.addScript("sql/define-roles-table-ddl.sql")
.addScript("sql/define-roles-permissions-table-ddl.sql")
.addScript("sql/define-users-table-ddl.sql")
.addScript("sql/define-users-roles-table-ddl.sql")
.addScript("sql/insert-roles-dml.sql")
.addScript("sql/insert-roles-permissions-dml.sql")
.addScript("sql/insert-users-dml.sql")
.addScript("sql/insert-users-roles-dml.sql")
.build();
return new EmbeddedDatabaseBuilder().setName("geode_security").setScriptEncoding("UTF-8")
.setType(EmbeddedDatabaseType.HSQL).addScript("sql/geode-security-schema-ddl.sql")
.addScript("sql/define-roles-table-ddl.sql").addScript("sql/define-roles-permissions-table-ddl.sql")
.addScript("sql/define-users-table-ddl.sql").addScript("sql/define-users-roles-table-ddl.sql")
.addScript("sql/insert-roles-dml.sql").addScript("sql/insert-roles-permissions-dml.sql")
.addScript("sql/insert-users-dml.sql").addScript("sql/insert-users-roles-dml.sql").build();
}
}

View File

@@ -13,22 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security.server;
import org.apache.geode.security.AuthenticationFailedException;
import org.apache.geode.security.ResourcePermission;
import org.cp.elements.lang.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.gemfire.support.LazyWiringDeclarableSupport;
import java.util.Properties;
import org.apache.geode.security.AuthenticationFailedException;
import org.apache.geode.security.ResourcePermission;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.gemfire.support.LazyWiringDeclarableSupport;
import org.springframework.util.Assert;
/**
* The {@link SecurityManagerProxy} class is a Proxy delegating to an underlying Apache Geode
* {@link org.apache.geode.security.SecurityManager} implementation, that maybe a Spring managed bean
* in a Spring context that may have been configured and auto-wired the Spring container, or possibly
* other managed environment (Cloud or Java EE Server, etc).
* {@link org.apache.geode.security.SecurityManager} implementation, that maybe a Spring managed bean in a Spring
* context that may have been configured and auto-wired the Spring container, or possibly other managed environment
* (Cloud or Java EE Server, etc).
*
* @author John Blum
* @see org.apache.geode.security.SecurityManager
@@ -42,8 +42,8 @@ public class SecurityManagerProxy extends LazyWiringDeclarableSupport
private org.apache.geode.security.SecurityManager securityManager;
/**
* Constructs an instance of the {@link SecurityManagerProxy}, whick will delegate all Apache Geode
* security operations to a Spring managed {@link org.apache.geode.security.SecurityManager} bean.
* Constructs an instance of the {@link SecurityManagerProxy}, whick will delegate all Apache Geode security
* operations to a Spring managed {@link org.apache.geode.security.SecurityManager} bean.
*/
public SecurityManagerProxy() {
// TODO remove init() call when GEODE-2083 (https://issues.apache.org/jira/browse/GEODE-2083) is resolved!
@@ -56,13 +56,13 @@ public class SecurityManagerProxy extends LazyWiringDeclarableSupport
}
/**
* Returns a reference to the Apache Geode {@link org.apache.geode.security.SecurityManager} instance
* delegated to by this {@link SecurityManagerProxy}.
* Returns a reference to the Apache Geode {@link org.apache.geode.security.SecurityManager} instance delegated to by
* this {@link SecurityManagerProxy}.
*
* @return a reference to the underlying, Apache Geode {@link org.apache.geode.security.SecurityManager}
* instance delegated to by this {@link SecurityManagerProxy}.
* @throws IllegalStateException if the configured Apache Geode {@link org.apache.geode.security.SecurityManager}
* was not properly initialized.
* @return a reference to the underlying, Apache Geode {@link org.apache.geode.security.SecurityManager} instance
* delegated to by this {@link SecurityManagerProxy}.
* @throws IllegalStateException if the configured Apache Geode {@link org.apache.geode.security.SecurityManager} was
* not properly initialized.
* @see org.apache.geode.security.SecurityManager
*/
protected org.apache.geode.security.SecurityManager getSecurityManager() {
@@ -71,13 +71,13 @@ public class SecurityManagerProxy extends LazyWiringDeclarableSupport
}
/**
* Sets a reference to the Apache Geode {@link org.apache.geode.security.SecurityManager} instance
* delegated to by this {@link SecurityManagerProxy}.
* Sets a reference to the Apache Geode {@link org.apache.geode.security.SecurityManager} instance delegated to by
* this {@link SecurityManagerProxy}.
*
* @param securityManager reference to the underlying, Apache Geode {@link org.apache.geode.security.SecurityManager}
* instance delegated to by this {@link SecurityManagerProxy}.
* @throws IllegalArgumentException if the Apache Geode {@link org.apache.geode.security.SecurityManager} reference
* is {@literal null}.
* instance delegated to by this {@link SecurityManagerProxy}.
* @throws IllegalArgumentException if the Apache Geode {@link org.apache.geode.security.SecurityManager} reference is
* {@literal null}.
* @see org.apache.geode.security.SecurityManager
*/
@Autowired

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security.server;
import example.springdata.geode.client.security.Constants;

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security.server;
import example.springdata.geode.client.security.Role;
@@ -24,8 +23,8 @@ import java.util.Arrays;
import java.util.List;
/**
* The [SecurityRepository] interface is a contract for Data Access Objects (DAO) implementing this interface
* to perform CRUD and query operations on [User] information, pertinent to the security of the system.
* The [SecurityRepository] interface is a contract for Data Access Objects (DAO) implementing this interface to perform
* CRUD and query operations on [User] information, pertinent to the security of the system.
*
* @author John Blum
* @author Udo Kohlmeyer
@@ -35,6 +34,7 @@ import java.util.List;
* @since 1.0.0
*/
public interface SecurityRepository {
/**
* Finds all [Users][User] of the system.
*
@@ -154,4 +154,3 @@ public interface SecurityRepository {
return saved;
}
}

View File

@@ -13,20 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security.server;
import example.springdata.geode.client.security.Role;
import example.springdata.geode.client.security.User;
import org.apache.geode.security.AuthenticationFailedException;
import org.apache.geode.security.ResourcePermission;
import org.springframework.stereotype.Service;
import java.util.Properties;
import org.apache.geode.security.AuthenticationFailedException;
import org.apache.geode.security.ResourcePermission;
import org.springframework.stereotype.Service;
/**
* The [SimpleSecurityManager] class is an example Apache Geode [SecurityManager] provider implementation
* used to secure Apache Geode.
* The [SimpleSecurityManager] class is an example Apache Geode [SecurityManager] provider implementation used to secure
* Apache Geode.
*
* @author John Blum
* @see SecurityManagerSupport
@@ -81,8 +82,8 @@ public class SimpleSecurityManager extends SecurityManagerSupport {
*/
@Override
public boolean authorize(Object principal, ResourcePermission permission) {
logDebug("Principal [{}] is requesting access to a Resource {} with the required Permission [{}]",
principal, permission.getResource(), permission);
logDebug("Principal [{}] is requesting access to a Resource {} with the required Permission [{}]", principal,
permission.getResource(), permission);
return isAuthorized(principal, permission);
}

View File

@@ -13,42 +13,43 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security.client;
import static org.assertj.core.api.Assertions.*;
import example.springdata.geode.client.security.Customer;
import example.springdata.geode.client.security.EmailAddress;
import example.springdata.geode.client.security.server.SecurityEnabledServer;
import lombok.extern.apachecommons.CommonsLog;
import java.io.IOException;
import java.util.List;
import javax.annotation.Resource;
import org.apache.geode.cache.Region;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Patrick Johnson
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = SecurityEnabledClientConfiguration.class)
@SpringBootTest(classes = SecurityEnabledClientConfiguration.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@CommonsLog
public class SecurityEnabledClientShiroTests extends ForkingClientServerIntegrationTestsSupport {
@Autowired
private CustomerRepository customerRepository;
@Autowired private CustomerRepository customerRepository;
@Resource(name = "Customers")
private Region<Long, Customer> customers;
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource(name = "Customers") private Region<Long, Customer> customers;
@BeforeClass
public static void setup() throws IOException {
@@ -57,20 +58,27 @@ public class SecurityEnabledClientShiroTests extends ForkingClientServerIntegrat
@Test
public void securityWasConfiguredCorrectly() {
logger.info("Inserting 3 entries for keys: 1, 2, 3");
log.info("Inserting 3 entries for keys: 1, 2, 3");
Customer john = new Customer(1L, new EmailAddress("2@2.com"), "John", "Smith");
Customer frank = new Customer(2L, new EmailAddress("3@3.com"), "Frank", "Lamport");
Customer jude = new Customer(3L, new EmailAddress("5@5.com"), "Jude", "Simmons");
customerRepository.save(john);
customerRepository.save(frank);
customerRepository.save(jude);
assertThat(customers.keySetOnServer().size()).isEqualTo(3);
logger.info("Customers saved on server:");
log.info("Customers saved on server:");
List<Customer> customerList = customerRepository.findAll();
assertThat(customerList.size()).isEqualTo(3);
assertThat(customerList.contains(john)).isTrue();
assertThat(customerList.contains(frank)).isTrue();
assertThat(customerList.contains(jude)).isTrue();
customerList.forEach(customer -> logger.info("\t Entry: \n \t\t " + customer));
customerList.forEach(customer -> log.info("\t Entry: \n \t\t " + customer));
}
}
}

View File

@@ -13,42 +13,43 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.security.client;
import static org.assertj.core.api.Assertions.*;
import example.springdata.geode.client.security.Customer;
import example.springdata.geode.client.security.EmailAddress;
import example.springdata.geode.client.security.server.SecurityEnabledServer;
import lombok.extern.apachecommons.CommonsLog;
import java.io.IOException;
import java.util.List;
import javax.annotation.Resource;
import org.apache.geode.cache.Region;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Patrick Johnson
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = SecurityEnabledClientConfiguration.class)
@SpringBootTest(classes = SecurityEnabledClientConfiguration.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@CommonsLog
public class SecurityEnabledClientTests extends ForkingClientServerIntegrationTestsSupport {
@Autowired
private CustomerRepository customerRepository;
@Autowired private CustomerRepository customerRepository;
@Resource(name = "Customers")
private Region<Long, Customer> customers;
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource(name = "Customers") private Region<Long, Customer> customers;
@BeforeClass
public static void setup() throws IOException {
@@ -57,20 +58,28 @@ public class SecurityEnabledClientTests extends ForkingClientServerIntegrationTe
@Test
public void SecurityWasConfiguredCorrectly() {
logger.info("Inserting 3 entries for keys: 1, 2, 3");
log.info("Inserting 3 entries for keys: 1, 2, 3");
Customer john = new Customer(1L, new EmailAddress("2@2.com"), "John", "Smith");
Customer frank = new Customer(2L, new EmailAddress("3@3.com"), "Frank", "Lamport");
Customer jude = new Customer(3L, new EmailAddress("5@5.com"), "Jude", "Simmons");
customerRepository.save(john);
customerRepository.save(frank);
customerRepository.save(jude);
assertThat(customers.keySetOnServer().size()).isEqualTo(3);
logger.info("Customers saved on server:");
assertThat(customers.keySetOnServer()).hasSize(3);
log.info("Customers saved on server:");
List<Customer> customerList = customerRepository.findAll();
assertThat(customerList.size()).isEqualTo(3);
assertThat(customerList.contains(john)).isTrue();
assertThat(customerList.contains(frank)).isTrue();
assertThat(customerList.contains(jude)).isTrue();
customerList.forEach(customer -> logger.info("\t Entry: \n \t\t " + customer));
customerList.forEach(customer -> log.info("\t Entry: \n \t\t " + customer));
}
}
}

View File

@@ -2,21 +2,21 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-data-geode-examples</artifactId>
<groupId>example.springdata.geode</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion>
<artifactId>storage</artifactId>
<parent>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.iq80.snappy</groupId>
<artifactId>snappy</artifactId>
<version>0.4</version>
</dependency>
</dependencies>
<artifactId>storage</artifactId>
</project>
<dependencies>
<dependency>
<groupId>org.iq80.snappy</groupId>
<artifactId>snappy</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.storage;
import lombok.Data;
@@ -29,6 +28,7 @@ import java.io.Serializable;
*/
@Data
public class Address implements Serializable {
private String street;
private String city;
private String country;

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.storage;
import lombok.Data;
@@ -48,4 +47,4 @@ public class Customer implements Serializable {
this.lastName = lastName;
this.addresses = Arrays.asList(addresses);
}
}
}

View File

@@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.storage;
import org.springframework.data.repository.CrudRepository;
/**
* @author Patrick Johnson
*/
public interface CustomerRepository extends CrudRepository<Customer, Long> {
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.storage;
import lombok.Data;
@@ -28,10 +27,11 @@ import java.io.Serializable;
*/
@Data
public class EmailAddress implements Serializable {
private String value;
public EmailAddress(String value) {
this.value = value;
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.storage;
import lombok.Data;
@@ -41,4 +40,4 @@ public class LineItem implements Serializable {
public BigDecimal calcTotal() {
return product.getPrice().multiply(BigDecimal.valueOf(amount));
}
}
}

View File

@@ -13,18 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.storage;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.annotation.Region;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.annotation.Region;
/**
* Orders object used in the examples
*
@@ -34,8 +34,8 @@ import java.util.List;
@Data
@Region("Orders")
public class Order implements Serializable {
@Id
private Long id;
@Id private Long id;
private Long customerId;
private Address billingAddress;
private Address shippingAddress;
@@ -69,4 +69,4 @@ public class Order implements Serializable {
public void add(LineItem lineItem) {
lineItems.add(lineItem);
}
}
}

View File

@@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.storage;
import org.springframework.data.repository.CrudRepository;
public interface OrderRepository extends CrudRepository<Order, Long> {
}
/**
* @author Patrick Johnson
*/
public interface OrderRepository extends CrudRepository<Order, Long> {}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.storage;
import lombok.Data;

View File

@@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.storage;
import org.springframework.data.repository.CrudRepository;
public interface ProductRepository extends CrudRepository<Product, Long> {
}
/**
* @author Patrick Johnson
*/
public interface ProductRepository extends CrudRepository<Product, Long> {}

View File

@@ -13,12 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.storage;
import lombok.extern.apachecommons.CommonsLog;
import java.math.BigDecimal;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import org.apache.geode.cache.Region;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.WebApplicationType;
@@ -26,26 +31,20 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import java.math.BigDecimal;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
@SpringBootApplication(scanBasePackageClasses = StorageServerConfig.class)
/**
* @author Patrick Johnson
*/
@SpringBootApplication
@CommonsLog
public class StorageServer {
private Logger logger = LoggerFactory.getLogger(this.getClass());
public static void main(String[] args) {
new SpringApplicationBuilder(StorageServer.class)
.web(WebApplicationType.NONE)
.build()
.run(args);
new SpringApplicationBuilder(StorageServer.class).web(WebApplicationType.NONE).build().run(args);
}
@Bean
public ApplicationRunner runner(CustomerRepository customerRepository, OrderRepository orderRepository,
ProductRepository productRepository, @Qualifier("Products") Region<Long, Product> products) {
ProductRepository productRepository, @Qualifier("Products") Region<Long, Product> products) {
return args -> {
createCustomerData(customerRepository);
@@ -53,40 +52,34 @@ public class StorageServer {
createOrders(productRepository, orderRepository);
logger.info("Completed creating orders ");
log.info("Completed creating orders ");
};
}
private void createOrders(ProductRepository productRepository, OrderRepository orderRepository) {
Random random = new Random(System.nanoTime());
Address address = new Address("it", "doesn't", "matter");
LongStream.rangeClosed(1, 10).forEach((orderId) ->
LongStream.rangeClosed(1, 300).forEach((customerId) -> {
Order order = new Order(orderId, customerId, address);
IntStream.rangeClosed(0, random.nextInt(3) + 1).forEach((lineItemCount) -> {
int quantity = random.nextInt(3) + 1;
long productId = random.nextInt(3) + 1;
order.add(new LineItem(productRepository.findById(productId).get(), quantity));
});
orderRepository.save(order);
}));
LongStream.rangeClosed(1, 10).forEach((orderId) -> LongStream.rangeClosed(1, 300).forEach((customerId) -> {
Order order = new Order(orderId, customerId, address);
IntStream.rangeClosed(0, random.nextInt(3) + 1).forEach((lineItemCount) -> {
int quantity = random.nextInt(3) + 1;
long productId = random.nextInt(3) + 1;
order.add(new LineItem(productRepository.findById(productId).get(), quantity));
});
orderRepository.save(order);
}));
}
private void createProducts(ProductRepository productRepository) {
productRepository.save(new Product(1L, "Apple iPod", new BigDecimal("99.99"),
"An Apple portable music player"));
productRepository.save(new Product(2L, "Apple iPad", new BigDecimal("499.99"),
"An Apple tablet device"));
Product macbook = new Product(3L, "Apple macBook", new BigDecimal("899.99"),
"An Apple notebook computer");
productRepository.save(new Product(1L, "Apple iPod", new BigDecimal("99.99"), "An Apple portable music player"));
productRepository.save(new Product(2L, "Apple iPad", new BigDecimal("499.99"), "An Apple tablet device"));
Product macbook = new Product(3L, "Apple macBook", new BigDecimal("899.99"), "An Apple notebook computer");
macbook.addAttribute("warranty", "included");
productRepository.save(macbook);
}
private void createCustomerData(CustomerRepository customerRepository) {
LongStream.rangeClosed(0, 300)
.parallel()
.forEach(customerId ->
customerRepository.save(new Customer(customerId, new EmailAddress(customerId + "@2.com"), "John" + customerId, "Smith" + customerId)));
LongStream.rangeClosed(0, 300).parallel().forEach(customerId -> customerRepository.save(
new Customer(customerId, new EmailAddress(customerId + "@2.com"), "John" + customerId, "Smith" + customerId)));
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.storage;
import org.apache.geode.cache.DataPolicy;
@@ -33,11 +32,14 @@ import org.springframework.data.gemfire.config.annotation.CacheServerApplication
import org.springframework.data.gemfire.config.annotation.EnableOffHeap;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
/**
* @author Patrick Johnson
*/
@Configuration
@ComponentScan
@CacheServerApplication(logLevel = "error")
@EnableGemfireRepositories(basePackageClasses = CustomerRepository.class)
@EnableOffHeap(memorySize = "8192m", regionNames = "Products")
@EnableOffHeap(memorySize = "512m", regionNames = "Products")
public class StorageServerConfig {
@Bean
@@ -47,22 +49,23 @@ public class StorageServerConfig {
@Bean
RegionAttributesFactoryBean<Long, Order> regionAttributes(PartitionAttributes<Long, Order> partitionAttributes) {
final RegionAttributesFactoryBean<Long, Order> regionAttributesFactoryBean = new RegionAttributesFactoryBean<>();
RegionAttributesFactoryBean<Long, Order> regionAttributesFactoryBean = new RegionAttributesFactoryBean<>();
regionAttributesFactoryBean.setPartitionAttributes(partitionAttributes);
return regionAttributesFactoryBean;
}
@Bean
PartitionAttributesFactoryBean<Long, Order> partitionAttributes() {
final PartitionAttributesFactoryBean<Long, Order> partitionAttributesFactoryBean = new PartitionAttributesFactoryBean<>();
PartitionAttributesFactoryBean<Long, Order> partitionAttributesFactoryBean = new PartitionAttributesFactoryBean<>();
partitionAttributesFactoryBean.setTotalNumBuckets(11);
partitionAttributesFactoryBean.setRedundantCopies(1);
return partitionAttributesFactoryBean;
}
@Bean("Orders")
PartitionedRegionFactoryBean<Long, Order> createOrderRegion(GemFireCache gemFireCache, RegionAttributes<Long, Order> regionAttributes) {
final PartitionedRegionFactoryBean<Long, Order> partitionedRegionFactoryBean = new PartitionedRegionFactoryBean<>();
PartitionedRegionFactoryBean<Long, Order> createOrderRegion(GemFireCache gemFireCache,
RegionAttributes<Long, Order> regionAttributes) {
PartitionedRegionFactoryBean<Long, Order> partitionedRegionFactoryBean = new PartitionedRegionFactoryBean<>();
partitionedRegionFactoryBean.setCache(gemFireCache);
partitionedRegionFactoryBean.setRegionName("Orders");
partitionedRegionFactoryBean.setDataPolicy(DataPolicy.PARTITION);
@@ -72,7 +75,7 @@ public class StorageServerConfig {
@Bean("Products")
ReplicatedRegionFactoryBean<Long, Product> createProductRegion(GemFireCache gemFireCache) {
final ReplicatedRegionFactoryBean<Long, Product> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
ReplicatedRegionFactoryBean<Long, Product> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
replicatedRegionFactoryBean.setCache(gemFireCache);
replicatedRegionFactoryBean.setRegionName("Products");
replicatedRegionFactoryBean.setDataPolicy(DataPolicy.REPLICATE);
@@ -81,11 +84,11 @@ public class StorageServerConfig {
@Bean("Customers")
ReplicatedRegionFactoryBean<Long, Customer> createCustomerRegion(GemFireCache gemFireCache, Compressor compressor) {
final ReplicatedRegionFactoryBean<Long, Customer> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
ReplicatedRegionFactoryBean<Long, Customer> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
replicatedRegionFactoryBean.setCache(gemFireCache);
replicatedRegionFactoryBean.setRegionName("Customers");
replicatedRegionFactoryBean.setDataPolicy(DataPolicy.REPLICATE);
replicatedRegionFactoryBean.setCompressor(compressor);
return replicatedRegionFactoryBean;
}
}
}

View File

@@ -13,39 +13,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.server.storage;
import static org.assertj.core.api.Assertions.*;
import javax.annotation.Resource;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.Region;
import org.apache.geode.compression.SnappyCompressor;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Patrick Johnson
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = StorageServer.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@SpringBootTest
public class StorageServerTests {
@Resource(name = "Customers")
private Region<Long, Customer> customers;
@Resource(name = "Orders")
private Region<Long, Order> orders;
@Resource(name = "Customers") private Region<Long, Customer> customers;
@Resource(name = "Products")
private Region<Long, Product> products;
@Resource(name = "Orders") private Region<Long, Order> orders;
@Autowired
Cache cache;
@Resource(name = "Products") private Region<Long, Product> products;
@Autowired Cache cache;
@Test
public void partitionAttributesConfiguredCorrectly() {
@@ -55,9 +53,13 @@ public class StorageServerTests {
@Test
public void compressorIsEnabled() {
assertThat(customers.getAttributes().getCompressor()).isInstanceOf(SnappyCompressor.class);
GemFireCacheImpl impl = (GemFireCacheImpl) cache;
assertThat(impl.getCachePerfStats().getTotalPostCompressedBytes()).isLessThan(impl.getCachePerfStats().getTotalPreCompressedBytes());
assertThat(impl.getCachePerfStats().getTotalPostCompressedBytes())
.isLessThan(impl.getCachePerfStats().getTotalPreCompressedBytes());
}
@Test
@@ -65,4 +67,4 @@ public class StorageServerTests {
assertThat(products.getAttributes().getOffHeap()).isTrue();
assertThat(customers.getAttributes().getOffHeap()).isFalse();
}
}
}

View File

@@ -2,18 +2,14 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>example.springdata.geode</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion>
<artifactId>transactions</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.data.examples</groupId>
<artifactId>spring-data-geode-examples</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
<artifactId>transactions</artifactId>
</dependencies>
</project>
</project>

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.transactions;
import lombok.Data;
@@ -42,4 +41,4 @@ public class Customer {
this.firstName = firstName;
this.lastName = lastName;
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.springdata.geode.client.transactions;
import lombok.Data;
@@ -26,9 +25,10 @@ import lombok.Data;
*/
@Data
public class EmailAddress {
private String value;
public EmailAddress(String value) {
this.value = value;
}
}
}

Some files were not shown because too many files have changed in this diff Show More