#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,52 @@
/*
* 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.queries;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.annotation.LuceneIndexed;
import org.springframework.data.gemfire.mapping.annotation.PartitionRegion;
import java.io.Serializable;
/**
* A customer used for Lucene examples.
*
* @author Udo Kohlmeyer
* @author Patrick Johnson
*/
@Data
@PartitionRegion(name = "Customers")
public class Customer implements Serializable {
@Id
private Long id;
private EmailAddress emailAddress;
private String firstName;
@LuceneIndexed(name = "lastName_lucene")
private String lastName;
public Customer(long id, EmailAddress emailAddress, String firstName, String lastName) {
this.id = id;
this.emailAddress = emailAddress;
this.firstName = firstName;
this.lastName = lastName;
}
}

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.queries;
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,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.queries.client;
import example.springdata.geode.client.queries.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(name = "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,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.client.queries.client;
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.context.annotation.DependsOn;
import org.springframework.data.gemfire.GemfireTemplate;
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
import org.springframework.data.gemfire.config.annotation.EnableClusterDefinedRegions;
import org.springframework.data.gemfire.config.annotation.EnableContinuousQueries;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
import org.springframework.data.gemfire.search.lucene.LuceneTemplate;
@Configuration
@EnableGemfireRepositories(basePackageClasses = CustomerRepository.class)
@ClientCacheApplication(name = "CQClientCache", logLevel = "error", pingInterval = 5000L, readTimeout = 15000, subscriptionEnabled = true, readyForEvents = true)
@EnableContinuousQueries
@EnableClusterDefinedRegions(clientRegionShortcut = ClientRegionShortcut.PROXY)
public class QueryClientConfig {
@Bean("customerTemplate")
@DependsOn("Customers")
protected GemfireTemplate configureCustomerTemplate(GemFireCache gemfireCache) {
return new GemfireTemplate(gemfireCache.getRegion("Customers"));
}
@Bean
LuceneTemplate createCustomerLuceneTemplate() {
return new LuceneTemplate("lastName_lucene", "/Customers");
}
}

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.queries.server;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication(scanBasePackageClasses = QueryServerConfig.class)
public class QueryServer {
public static void main(String[] args) {
new SpringApplicationBuilder(QueryServer.class).web(WebApplicationType.NONE).build().run(args);
}
}

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.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;
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
import org.springframework.data.gemfire.config.annotation.EnableIndexing;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
import org.springframework.data.gemfire.search.lucene.LuceneTemplate;
@Configuration
@CacheServerApplication(logLevel = "error")
@EnableGemfireRepositories(basePackageClasses = CustomerRepository.class)
@EnableEntityDefinedRegions(basePackageClasses = Customer.class)
@EnableIndexing
public class QueryServerConfig {
@Bean
@DependsOn("lastName_lucene")
LuceneTemplate createCustomerLuceneTemplate() {
return new LuceneTemplate("lastName_lucene", "/Customers");
}
}

View File

@@ -0,0 +1,158 @@
/*
* 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.queries;
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 org.apache.geode.cache.Region;
import org.apache.geode.cache.lucene.LuceneResultStruct;
import org.apache.geode.cache.query.CqEvent;
import org.awaitility.Awaitility;
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;
import org.springframework.data.gemfire.listener.ContinuousQueryListenerContainer;
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;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = QueryClientConfig.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class QueryTests extends ForkingClientServerIntegrationTestsSupport {
@Autowired
private ContinuousQueryListenerContainer container;
@Autowired
private CustomerRepository customerRepository;
@Autowired
private GemfireTemplate customerTemplate;
@Resource(name = "Customers")
private Region<Long, Customer> customers;
@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);
}
@Test
public void luceneIsConfiguredCorrectly() {
customerRepository.save(new Customer(1L, new EmailAddress("name@internet.com"), "Stephanie", "Demarco"));
customerRepository.save(new Customer(2L, new EmailAddress("cool_Guy57@mail.com"), "Patrick", "Dunham"));
customerRepository.save(new Customer(3L, new EmailAddress("scientist@mail.com"), "Jasmine", "Oliander"));
customerRepository.save(new Customer(4L, new EmailAddress("catlover42@mail.com"), "Erica", "Shu"));
customerRepository.save(new Customer(5L, new EmailAddress("zolander@mail.com"), "Tom", "Darude"));
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()));
}
@Test
public void oqlQueriesConfiguredCorrectly() {
logger.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);
Customer customer = customerRepository.findById(2L).get();
assertThat(customer).isEqualTo(frank);
logger.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);
customer = new Customer(1L, new EmailAddress("3@3.com"), "Jude", "Smith");
customerRepository.save(customer);
assertThat(customers.keySetOnServer().size()).isEqualTo(3);
customerList = customerRepository.findByEmailAddressUsingIndex("3@3.com");
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);
customerList = customerRepository.findByFirstNameUsingIndex("Frank");
assertThat(customerList.get(0)).isEqualTo(frank);
logger.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);
}
@Test
public void continuousQueryWorkingCorrectly() {
assertThat(this.customers).isEmpty();
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);
Awaitility.await().atMost(30, TimeUnit.SECONDS).until(() -> this.counter.get() == 3);
}
@ContinuousQuery(name = "CustomerCQ", query = "SELECT * FROM /Customers")
public void handleEvent(CqEvent event) {
logger.info("Received message for CQ 'CustomerCQ'" + event);
counter.incrementAndGet();
}
@After
public void cleanup() {
customerRepository.deleteAll(customerRepository.findAll());
container.getQueryService().closeCqs();
}
}

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>