#539 - Add spring-data-geode-examples module.
This commit is contained in:
committed by
Mark Paluch
parent
08dce4f0f3
commit
fa0021cffb
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
11
geode/queries/src/test/resources/logback.xml
Normal file
11
geode/queries/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