#539 - Add spring-data-geode-examples module.
This commit is contained in:
committed by
Mark Paluch
parent
08dce4f0f3
commit
fa0021cffb
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* An address used in the examples.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Udo Kohlmeyer
|
||||
* @author Patrick Johnson
|
||||
*/
|
||||
@Data
|
||||
public class Address implements Serializable {
|
||||
private String street;
|
||||
private String city;
|
||||
private String country;
|
||||
|
||||
public Address(String street, String city, String country) {
|
||||
this.street = street;
|
||||
this.city = city;
|
||||
this.country = country;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.gemfire.mapping.annotation.Region;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A customer used for Lucene examples.
|
||||
*
|
||||
* @author Udo Kohlmeyer
|
||||
* @author Patrick Johnson
|
||||
*/
|
||||
@Data
|
||||
@Region(name = "Customers")
|
||||
public class Customer implements Serializable {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
private EmailAddress emailAddress;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private List<Address> addresses;
|
||||
|
||||
public Customer(Long id, EmailAddress emailAddress, String firstName, String lastName, Address... addresses) {
|
||||
this.id = id;
|
||||
this.emailAddress = emailAddress;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.addresses = Arrays.asList(addresses);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
import org.apache.geode.cache.CacheWriterException;
|
||||
import org.apache.geode.cache.EntryEvent;
|
||||
import org.apache.geode.cache.util.CacheWriterAdapter;
|
||||
import org.apache.geode.internal.cache.EntryEventImpl;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class CustomerCacheWriter extends CacheWriterAdapter<Long, Customer> {
|
||||
|
||||
@Override
|
||||
public void beforeCreate(EntryEvent<Long, Customer> event) throws CacheWriterException {
|
||||
EntryEventImpl e = (EntryEventImpl) event;
|
||||
super.beforeCreate(e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
public interface CustomerRepository extends CrudRepository<Customer, Long> {
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Value object to represent email addresses.
|
||||
*
|
||||
* @author Udo Kohlmeyer
|
||||
* @author Patrick Johnson
|
||||
*/
|
||||
@Data
|
||||
public class EmailAddress implements Serializable {
|
||||
private String value;
|
||||
|
||||
public EmailAddress(String value) {
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.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)
|
||||
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);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ApplicationRunner runner(CustomerRepository customerRepository, OrderRepository orderRepository,
|
||||
ProductRepository productRepository, OrderProductSummaryRepository orderProductSummaryRepository, @Qualifier("Products") Region<Long, Product> products) {
|
||||
return args -> {
|
||||
createCustomerData(customerRepository);
|
||||
|
||||
createProducts(productRepository);
|
||||
|
||||
createOrders(productRepository, orderRepository);
|
||||
|
||||
logger.info("Completed creating orders ");
|
||||
|
||||
final List<OrderProductSummary> allForProductID = orderProductSummaryRepository.findAllForProductID(3L);
|
||||
allForProductID.forEach(orderProductSummary -> logger.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);
|
||||
}));
|
||||
}
|
||||
|
||||
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");
|
||||
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)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
import org.apache.geode.cache.Cache;
|
||||
import org.apache.geode.cache.CacheListener;
|
||||
import org.apache.geode.cache.CacheLoader;
|
||||
import org.apache.geode.cache.CacheWriter;
|
||||
import org.apache.geode.cache.DataPolicy;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.asyncqueue.AsyncEventListener;
|
||||
import org.apache.geode.cache.asyncqueue.AsyncEventQueue;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.gemfire.PartitionedRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.ReplicatedRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
|
||||
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
|
||||
import org.springframework.data.gemfire.wan.AsyncEventQueueFactoryBean;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
@CacheServerApplication(logLevel = "error")
|
||||
@EnableGemfireRepositories(basePackageClasses = CustomerRepository.class)
|
||||
public class EventServerConfig {
|
||||
|
||||
@Bean
|
||||
AsyncEventListener orderAsyncEventListener(@Qualifier("OrderProductSummary") Region<Long, OrderProductSummary> orderProductSummary) {
|
||||
return new OrderAsyncQueueListener(orderProductSummary);
|
||||
}
|
||||
|
||||
@Bean
|
||||
AsyncEventQueueFactoryBean orderAsyncEventQueue(GemFireCache gemFireCache, AsyncEventListener orderAsyncEventListener) {
|
||||
final AsyncEventQueueFactoryBean asyncEventQueueFactoryBean = new AsyncEventQueueFactoryBean((Cache) gemFireCache);
|
||||
asyncEventQueueFactoryBean.setBatchTimeInterval(1000);
|
||||
asyncEventQueueFactoryBean.setBatchSize(5);
|
||||
asyncEventQueueFactoryBean.setAsyncEventListener(orderAsyncEventListener);
|
||||
return asyncEventQueueFactoryBean;
|
||||
}
|
||||
|
||||
@Bean(name = "OrderProductSummary")
|
||||
PartitionedRegionFactoryBean<Long, Order> createOrderProductSummaryRegion(GemFireCache gemFireCache) {
|
||||
final PartitionedRegionFactoryBean<Long, Order> partitionedRegionFactoryBean = new PartitionedRegionFactoryBean<>();
|
||||
partitionedRegionFactoryBean.setCache(gemFireCache);
|
||||
partitionedRegionFactoryBean.setRegionName("OrderProductSummary");
|
||||
partitionedRegionFactoryBean.setDataPolicy(DataPolicy.PARTITION);
|
||||
return partitionedRegionFactoryBean;
|
||||
}
|
||||
|
||||
@Bean("Orders")
|
||||
PartitionedRegionFactoryBean<Long, Order> createOrderRegion(GemFireCache gemFireCache, AsyncEventQueue orderAsyncEventQueue) {
|
||||
final PartitionedRegionFactoryBean<Long, Order> partitionedRegionFactoryBean = new PartitionedRegionFactoryBean<>();
|
||||
partitionedRegionFactoryBean.setCache(gemFireCache);
|
||||
partitionedRegionFactoryBean.setRegionName("Orders");
|
||||
partitionedRegionFactoryBean.setDataPolicy(DataPolicy.PARTITION);
|
||||
partitionedRegionFactoryBean.setAsyncEventQueues(new AsyncEventQueue[]{orderAsyncEventQueue});
|
||||
return partitionedRegionFactoryBean;
|
||||
}
|
||||
|
||||
@Bean("Products")
|
||||
ReplicatedRegionFactoryBean<Long, Product> createProductRegion(GemFireCache gemFireCache, CacheListener<Long, Product> loggingCacheListener,
|
||||
CacheLoader<Long, Product> productCacheLoader) {
|
||||
final ReplicatedRegionFactoryBean<Long, Product> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
|
||||
replicatedRegionFactoryBean.setCache(gemFireCache);
|
||||
replicatedRegionFactoryBean.setRegionName("Products");
|
||||
replicatedRegionFactoryBean.setDataPolicy(DataPolicy.REPLICATE);
|
||||
replicatedRegionFactoryBean.setCacheLoader(productCacheLoader);
|
||||
replicatedRegionFactoryBean.setCacheListeners(new CacheListener[]{loggingCacheListener});
|
||||
return replicatedRegionFactoryBean;
|
||||
}
|
||||
|
||||
@Bean("Customers")
|
||||
ReplicatedRegionFactoryBean<Long, Customer> createCustomerRegion(GemFireCache gemFireCache,
|
||||
CacheWriter<Long, Customer> customerCacheWriter,
|
||||
CacheListener<Long, Customer> loggingCacheListener) {
|
||||
final ReplicatedRegionFactoryBean<Long, Customer> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
|
||||
replicatedRegionFactoryBean.setCache(gemFireCache);
|
||||
replicatedRegionFactoryBean.setRegionName("Customers");
|
||||
replicatedRegionFactoryBean.setDataPolicy(DataPolicy.REPLICATE);
|
||||
replicatedRegionFactoryBean.setCacheListeners(new CacheListener[]{loggingCacheListener});
|
||||
replicatedRegionFactoryBean.setCacheWriter(customerCacheWriter);
|
||||
return replicatedRegionFactoryBean;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* A LineItem used in the examples
|
||||
*
|
||||
* @author Udo Kohlmeyer
|
||||
* @author Patrick Johnson
|
||||
*/
|
||||
@Data
|
||||
public class LineItem implements Serializable {
|
||||
|
||||
private Product product;
|
||||
private Integer amount;
|
||||
|
||||
public LineItem(Product product, Integer amount) {
|
||||
this.product = product;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public BigDecimal calcTotal() {
|
||||
return product.getPrice().multiply(BigDecimal.valueOf(amount));
|
||||
}
|
||||
|
||||
public Long getProductId() {
|
||||
return product.getId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
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;
|
||||
|
||||
@Component
|
||||
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() + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterDestroy(EntryEvent<K, V> event) {
|
||||
logger.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() + "]");
|
||||
}
|
||||
}
|
||||
72
geode/events/src/main/java/example/springdata/geode/server/events/Order.java
Executable file
72
geode/events/src/main/java/example/springdata/geode/server/events/Order.java
Executable file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Orders object used in the examples
|
||||
*
|
||||
* @author Udo Kohlmeyer
|
||||
* @author Patrick Johnson
|
||||
*/
|
||||
@Data
|
||||
@Region("Orders")
|
||||
public class Order implements Serializable {
|
||||
@Id
|
||||
private Long id;
|
||||
private Long customerId;
|
||||
private Address billingAddress;
|
||||
private Address shippingAddress;
|
||||
private List<LineItem> lineItems = new ArrayList<>();
|
||||
|
||||
public Order(Long orderId, Long customerId, Address address) {
|
||||
this.id = orderId;
|
||||
this.customerId = customerId;
|
||||
this.billingAddress = address;
|
||||
this.shippingAddress = address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total of the [Order].
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public BigDecimal calcTotal() {
|
||||
if (lineItems.size() == 0) {
|
||||
return BigDecimal.ZERO;
|
||||
} else {
|
||||
return lineItems.stream().map(LineItem::calcTotal).reduce(BigDecimal::add).get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given [LineItem] to the [Order].
|
||||
*
|
||||
* @param lineItem
|
||||
*/
|
||||
public void add(LineItem lineItem) {
|
||||
lineItems.add(lineItem);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
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;
|
||||
|
||||
public class OrderAsyncQueueListener implements AsyncEventListener {
|
||||
|
||||
private Region<Long, OrderProductSummary> summaryRegion;
|
||||
|
||||
public OrderAsyncQueueListener(Region<Long, OrderProductSummary> summaryRegion) {
|
||||
this.summaryRegion = summaryRegion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processEvents(List<AsyncEvent> list) {
|
||||
HashMap<Long, OrderProductSummary> summaryMap = new HashMap<>();
|
||||
list.forEach(asyncEvent -> {
|
||||
final Order order = (Order) asyncEvent.getDeserializedValue();
|
||||
if (order != null) {
|
||||
order.getLineItems().forEach(lineItem -> {
|
||||
OrderProductSummary orderProductSummary = summaryMap.get(lineItem.getProductId());
|
||||
if (orderProductSummary == null) {
|
||||
orderProductSummary = new OrderProductSummary(lineItem.getProductId(), new BigDecimal("0.00"));
|
||||
}
|
||||
orderProductSummary.setSummaryAmount(orderProductSummary.getSummaryAmount().add(lineItem.calcTotal()));
|
||||
summaryMap.put(lineItem.getProductId(), orderProductSummary);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
summaryMap.forEach((orderProductSummaryKey, orderProductSummary) -> {
|
||||
final OrderProductSummary productSummary = summaryRegion.get(orderProductSummaryKey);
|
||||
if (productSummary != null) {
|
||||
final BigDecimal newSummaryAmount = productSummary.getSummaryAmount().add(orderProductSummary.getSummaryAmount());
|
||||
summaryRegion.put(orderProductSummaryKey, new OrderProductSummary(orderProductSummaryKey, newSummaryAmount));
|
||||
} else {
|
||||
summaryRegion.put(orderProductSummaryKey, orderProductSummary);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* OrderProductSummary is an object used in the examples to show a summary of all Orders on a per product basis, on a per
|
||||
* timeframe shard (every 10s, or every 1hr)
|
||||
*
|
||||
* @author Udo Kohlmeyer
|
||||
* @author Patrick Johnson
|
||||
*/
|
||||
@Data
|
||||
@Region("OrderProductSummary")
|
||||
public class OrderProductSummary implements Serializable {
|
||||
|
||||
@Id
|
||||
private Long summaryKey;
|
||||
|
||||
private BigDecimal summaryAmount;
|
||||
|
||||
public OrderProductSummary(Long summaryKey, BigDecimal summaryAmount) {
|
||||
this.summaryKey = summaryKey;
|
||||
this.summaryAmount = summaryAmount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
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;
|
||||
|
||||
@Region("OrderProductSummary")
|
||||
public interface OrderProductSummaryRepository extends CrudRepository<OrderProductSummary, Long> {
|
||||
@Hint("emailAddressIndex")
|
||||
@Query("select orderSummary.value from /OrderProductSummary.entrySet orderSummary where orderSummary.key = $1")
|
||||
List<OrderProductSummary> findAllForProductID(long l);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
public interface OrderRepository extends CrudRepository<Order, Long> {
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.annotation.Transient;
|
||||
import org.springframework.data.gemfire.mapping.annotation.Region;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A product used in the examples.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author David Turanski
|
||||
* @author Udo Kohlmeyer
|
||||
* @author Patrick Johnson
|
||||
*/
|
||||
@Data
|
||||
@Region("Products")
|
||||
public class Product implements Serializable {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
private String name;
|
||||
private BigDecimal price;
|
||||
private String description;
|
||||
|
||||
@Transient
|
||||
private Map<String, String> attributes = new HashMap<>();
|
||||
|
||||
@PersistenceConstructor
|
||||
public Product(Long id, String name, BigDecimal price, String description) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.price = price;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the attribute with the given name to the given value.
|
||||
*
|
||||
* @param name must not be null or empty.
|
||||
* @param value
|
||||
*/
|
||||
public void addAttribute(String name, String value) {
|
||||
this.attributes.put(name, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
import com.github.javafaker.Faker;
|
||||
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;
|
||||
|
||||
@Component
|
||||
public class ProductCacheLoader implements CacheLoader<Long, Product> {
|
||||
private Faker faker = new Faker();
|
||||
|
||||
@Override
|
||||
public Product load(LoaderHelper loaderHelper) throws CacheLoaderException {
|
||||
return new Product((long) loaderHelper.getKey(), randomStringName(), randomPrice(), "");
|
||||
}
|
||||
|
||||
private BigDecimal randomPrice() {
|
||||
return new BigDecimal(faker.commerce().price());
|
||||
}
|
||||
|
||||
private String randomStringName() {
|
||||
return faker.commerce().productName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
public interface ProductRepository extends CrudRepository<Product, Long> {
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* https://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.server.events;
|
||||
|
||||
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;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = EventServer.class)
|
||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
|
||||
public class EventServerTests {
|
||||
|
||||
@Autowired
|
||||
Cache cache;
|
||||
|
||||
@Autowired
|
||||
private ProductRepository productRepository;
|
||||
|
||||
@Autowired
|
||||
private OrderProductSummaryRepository orderProductSummaryRepository;
|
||||
|
||||
@Test
|
||||
public void asyncEventQueueEasConfiguredCorrectly() {
|
||||
assertThat(this.orderProductSummaryRepository.count()).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void productCacheLoaderWorks() {
|
||||
long size = productRepository.count();
|
||||
assertThat(this.productRepository.findById(777L)).isNotNull();
|
||||
assertThat(productRepository.count()).isEqualTo(size + 1);
|
||||
productRepository.deleteById(777L);
|
||||
}
|
||||
}
|
||||
11
geode/events/src/test/resources/logback.xml
Normal file
11
geode/events/src/test/resources/logback.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<root level="error">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
<statusListener class="ch.qos.logback.core.status.NopStatusListener"/>
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user