#539 - Add spring-data-geode-examples module.

This commit is contained in:
Patrick Johnson
2020-02-06 15:25:47 -08:00
committed by Mark Paluch
parent 08dce4f0f3
commit fa0021cffb
151 changed files with 6712 additions and 0 deletions

View File

@@ -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.client.function;
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;
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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.client.function;
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);
}
/**
* Adds the given [Address] to the [Customer].
*/
public void add(Address address) {
this.addresses.add(address);
}
}

View File

@@ -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.client.function;
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;
}
}

View File

@@ -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.client.function;
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));
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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.client.function;
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);
}
}

View File

@@ -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.client.function;
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);
}
}

View File

@@ -0,0 +1,30 @@
/*
* 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.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;
@OnRegion(region = "Customers")
public interface CustomerFunctionExecutions {
@FunctionId("listConsumersForEmailAddressesFnc")
List<List<Customer>> listAllCustomersForEmailAddress(String... emailAddresses);
}

View File

@@ -0,0 +1,42 @@
/*
* 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.client.function.client;
import example.springdata.geode.client.function.Customer;
import org.springframework.data.gemfire.mapping.annotation.ClientRegion;
import org.springframework.data.gemfire.repository.Query;
import org.springframework.data.gemfire.repository.query.annotation.Hint;
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;
@ClientRegion("Customers")
public interface CustomerRepository extends CrudRepository<Customer, Long> {
@Trace
@Limit(100)
@Hint("emailAddressIndex")
@Query("select * from /Customers customer where customer.emailAddress.value = $1")
List<Customer> findByEmailAddressUsingIndex(String emailAddress);
@Trace
@Limit(100)
@Query("select * from /Customers customer where customer.firstName = $1")
List<Customer> findByFirstNameUsingIndex(String firstName);
}

View 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.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;
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
import org.springframework.data.gemfire.function.config.EnableGemfireFunctionExecutions;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
import org.springframework.data.gemfire.transaction.config.EnableGemfireCacheTransactions;
/**
* Spring JavaConfig configuration class to setup a Spring container and infrastructure components.
*
* @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)
@EnableGemfireCacheTransactions
public class FunctionInvocationClientApplicationConfig {
@Bean("Customers")
protected ClientRegionFactoryBean<Long, Customer> configureProxyClientCustomerRegion(GemFireCache gemFireCache) {
ClientRegionFactoryBean<Long, Customer> clientRegionFactoryBean = new ClientRegionFactoryBean<>();
clientRegionFactoryBean.setCache(gemFireCache);
clientRegionFactoryBean.setName("Customers");
clientRegionFactoryBean.setShortcut(ClientRegionShortcut.PROXY);
return clientRegionFactoryBean;
}
@Bean("Products")
protected ClientRegionFactoryBean<Long, Product> configureProxyClientProductRegion(GemFireCache gemFireCache) {
ClientRegionFactoryBean<Long, Product> clientRegionFactoryBean = new ClientRegionFactoryBean<>();
clientRegionFactoryBean.setCache(gemFireCache);
clientRegionFactoryBean.setName("Products");
clientRegionFactoryBean.setShortcut(ClientRegionShortcut.PROXY);
return clientRegionFactoryBean;
}
@Bean("Orders")
protected ClientRegionFactoryBean<Long, Order> configureProxyClientOrderRegion(GemFireCache gemFireCache) {
ClientRegionFactoryBean<Long, Order> clientRegionFactoryBean = new ClientRegionFactoryBean<>();
clientRegionFactoryBean.setCache(gemFireCache);
clientRegionFactoryBean.setName("Orders");
clientRegionFactoryBean.setShortcut(ClientRegionShortcut.PROXY);
return clientRegionFactoryBean;
}
}

View File

@@ -0,0 +1,30 @@
/*
* 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.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;
@OnRegion(region = "Orders")
public interface OrderFunctionExecutions {
@FunctionId("sumPricesForAllProductsForOrderFnc")
List<BigDecimal> sumPricesForAllProductsForOrder(Long orderId);
}

View File

@@ -0,0 +1,26 @@
/*
* 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.client.function.client;
import example.springdata.geode.client.function.Order;
import org.springframework.data.gemfire.mapping.annotation.ClientRegion;
import org.springframework.data.repository.CrudRepository;
@ClientRegion("Orders")
public interface OrderRepository extends CrudRepository<Order, Long> {
}

View File

@@ -0,0 +1,30 @@
/*
* 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.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;
@OnRegion(region = "Products")
public interface ProductFunctionExecutions {
@FunctionId("sumPricesForAllProductsFnc")
List<BigDecimal> sumPricesForAllProducts();
}

View File

@@ -0,0 +1,26 @@
/*
* 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.client.function.client;
import example.springdata.geode.client.function.Product;
import org.springframework.data.gemfire.mapping.annotation.ClientRegion;
import org.springframework.data.repository.CrudRepository;
@ClientRegion("Products")
public interface ProductRepository extends CrudRepository<Product, Long> {
}

View File

@@ -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.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;
@Component
public class CustomerFunctions {
@GemfireFunction(id = "listConsumersForEmailAddressesFnc", HA = true, optimizeForWrite = true, batchSize = 3, hasResult = true)
public List<Customer> listAllCustomersForEmailAddress(@RegionData Map<Long, Customer> customerData,
String... emailAddresses) {
List<String> emailAddressesAsList = Arrays.asList(emailAddresses);
List<Customer> collect = customerData.values().parallelStream()
.filter((customer) -> emailAddressesAsList.contains(customer.getEmailAddress().getValue()))
.collect(Collectors.toList());
return collect;
}
}

View File

@@ -0,0 +1,29 @@
/*
* 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.client.function.server;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication(scanBasePackageClasses = FunctionServerApplicationConfig.class)
public class FunctionServer {
public static void main(String[] args) {
new SpringApplicationBuilder(FunctionServer.class).web(WebApplicationType.NONE).build().run(args);
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.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;
import org.springframework.data.gemfire.ReplicatedRegionFactoryBean;
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
import org.springframework.data.gemfire.config.annotation.EnableIndexing;
import org.springframework.data.gemfire.config.annotation.EnableLocator;
import org.springframework.data.gemfire.config.annotation.EnableManager;
import org.springframework.data.gemfire.function.config.EnableGemfireFunctions;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
@Configuration
@ComponentScan(basePackageClasses = CustomerFunctions.class)
@EnableGemfireFunctions
@EnableGemfireRepositories(basePackageClasses = CustomerRepository.class)
@EnableLocator
@EnableIndexing
@EnableManager
@CacheServerApplication(port = 0, logLevel = "error")
public class FunctionServerApplicationConfig {
@Bean("Customers")
ReplicatedRegionFactoryBean<Long, Customer> createCustomerRegion(GemFireCache gemfireCache) {
ReplicatedRegionFactoryBean<Long, Customer> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
replicatedRegionFactoryBean.setCache(gemfireCache);
replicatedRegionFactoryBean.setRegionName("Customers");
replicatedRegionFactoryBean.setDataPolicy(DataPolicy.REPLICATE);
replicatedRegionFactoryBean.setScope(Scope.DISTRIBUTED_ACK);
return replicatedRegionFactoryBean;
}
@Bean("Orders")
ReplicatedRegionFactoryBean<Long, Order> createOrderRegion(GemFireCache gemfireCache) {
ReplicatedRegionFactoryBean<Long, Order> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
replicatedRegionFactoryBean.setCache(gemfireCache);
replicatedRegionFactoryBean.setRegionName("Orders");
replicatedRegionFactoryBean.setDataPolicy(DataPolicy.REPLICATE);
return replicatedRegionFactoryBean;
}
@Bean("Products")
ReplicatedRegionFactoryBean<Long, Product> createProductRegion(GemFireCache gemfireCache) {
ReplicatedRegionFactoryBean<Long, Product> replicatedRegionFactoryBean = new ReplicatedRegionFactoryBean<>();
replicatedRegionFactoryBean.setCache(gemfireCache);
replicatedRegionFactoryBean.setRegionName("Products");
replicatedRegionFactoryBean.setDataPolicy(DataPolicy.REPLICATE);
return replicatedRegionFactoryBean;
}
}

View File

@@ -0,0 +1,34 @@
/*
* 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.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;
@Component
public class OrderFunctions {
@GemfireFunction(id = "sumPricesForAllProductsForOrderFnc", HA = true, optimizeForWrite = false, hasResult = true)
public BigDecimal sumPricesForAllProductsForOrderFnc(Long orderId, @RegionData Map<Long, Order> orderData) {
return orderData.get(orderId).calcTotal();
}
}

View File

@@ -0,0 +1,34 @@
/*
* 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.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;
@Component
public class ProductFunctions {
@GemfireFunction(id = "sumPricesForAllProductsFnc", HA = true, optimizeForWrite = false, hasResult = true)
public BigDecimal sumPricesForAllProductsFnc(@RegionData Map<Long, Product> productData) {
return productData.values().stream().map(Product::getPrice).reduce(BigDecimal::add).get();
}
}

View File

@@ -0,0 +1,145 @@
/*
* 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.client.function.client;
import example.springdata.geode.client.function.Address;
import example.springdata.geode.client.function.Customer;
import example.springdata.geode.client.function.EmailAddress;
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 javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = FunctionInvocationClientApplicationConfig.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class FunctionInvocationClientTests extends ForkingClientServerIntegrationTestsSupport {
@Autowired
private CustomerRepository customerRepository;
@Autowired
private OrderRepository orderRepository;
@Autowired
private ProductRepository productRepository;
@Autowired
private CustomerFunctionExecutions customerFunctionExecutions;
@Autowired
private OrderFunctionExecutions orderFunctionExecutions;
@Autowired
private ProductFunctionExecutions productFunctionExecutions;
@Resource(name = "Customers")
private Region<Long, Customer> customers;
@Resource(name = "Orders")
private Region<Long, Order> orders;
@Resource(name = "Products")
private Region<Long, Product> products;
private Logger logger = LoggerFactory.getLogger(this.getClass());
@BeforeClass
public static void setup() throws IOException {
startGemFireServer(FunctionServer.class);
}
@Test
public void functionsExecuteCorrectly() {
createCustomerData();
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);
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);
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);
Order order = orderRepository.findById(1L).get();
logger.info("For order: \n\t " + order);
}
public void createCustomerData() {
logger.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");
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);
}));
assertThat(orders.keySetOnServer().size()).isEqualTo(100);
}
}

View 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>