Add Sample Code for Near Caching.
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
plugins {
|
||||
id "io.freefair.lombok" version "3.2.1"
|
||||
}
|
||||
|
||||
apply plugin: 'io.spring.convention.spring-sample-boot'
|
||||
|
||||
description = "Spring Geode Sample demonstrating Spring's Cache Abstraction using Apache Geode as the caching provider with Near Caching."
|
||||
|
||||
dependencies {
|
||||
|
||||
compile project(":spring-geode-starter")
|
||||
|
||||
compile project(":apache-geode-extensions")
|
||||
|
||||
compile ("org.springframework.boot:spring-boot-starter-web") {
|
||||
exclude group: "org.apache.logging.log4j", module: "log4j-to-slf4j"
|
||||
}
|
||||
|
||||
compile "org.assertj:assertj-core"
|
||||
compile "org.projectlombok:lombok"
|
||||
|
||||
runtime "javax.cache:cache-api"
|
||||
runtime "org.springframework.boot:spring-boot-starter-jetty"
|
||||
runtime "org.springframework.shell:spring-shell"
|
||||
|
||||
testCompile "org.springframework.boot:spring-boot-starter-test"
|
||||
|
||||
testCompile("org.springframework.data:spring-data-geode-test") {
|
||||
exclude group: "org.apache.logging.log4j", module: "log4j-core"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bootJar {
|
||||
mainClassName = 'example.app.caching.near.BootGeodeNearCachingClientCacheApplication'
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2019 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.app.near.caching.client;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.apache.geode.cache.DataPolicy;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.client.Pool;
|
||||
import org.apache.geode.cache.client.PoolManager;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* Spring Boot application demonstrating Spring's Cache Abstraction with Apache Geode as the caching provider
|
||||
* for {@literal Near Caching}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.boot.SpringApplication
|
||||
* @see org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
* @since 1.1.0
|
||||
*/
|
||||
// tag::class[]
|
||||
@SpringBootApplication
|
||||
public class BootGeodeNearCachingClientCacheApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BootGeodeNearCachingClientCacheApplication.class, args);
|
||||
}
|
||||
|
||||
// tag::application-runner[]
|
||||
@Bean
|
||||
public ApplicationRunner runner(@Qualifier("YellowPages") Region<?, ?> yellowPages) {
|
||||
|
||||
return args -> {
|
||||
|
||||
assertThat(yellowPages).isNotNull();
|
||||
assertThat(yellowPages.getName()).isEqualTo("YellowPages");
|
||||
assertThat(yellowPages.getInterestListRegex()).containsAnyOf(".*");
|
||||
assertThat(yellowPages.getAttributes()).isNotNull();
|
||||
assertThat(yellowPages.getAttributes().getDataPolicy()).isEqualTo(DataPolicy.NORMAL);
|
||||
assertThat(yellowPages.getAttributes().getPoolName()).isEqualTo("DEFAULT");
|
||||
|
||||
Pool defaultPool = PoolManager.find("DEFAULT");
|
||||
|
||||
assertThat(defaultPool).isNotNull();
|
||||
assertThat(defaultPool.getSubscriptionEnabled()).isTrue();
|
||||
|
||||
};
|
||||
}
|
||||
// end::application-runner[]
|
||||
}
|
||||
// end::class[]
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2019 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.app.near.caching.client.config;
|
||||
|
||||
import org.apache.geode.cache.CacheListener;
|
||||
import org.apache.geode.cache.EntryEvent;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.InterestResultPolicy;
|
||||
import org.apache.geode.cache.Region;
|
||||
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.client.Interest;
|
||||
import org.springframework.data.gemfire.client.RegexInterest;
|
||||
import org.springframework.data.gemfire.config.annotation.RegionConfigurer;
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.geode.cache.AbstractCommonEventProcessingCacheListener;
|
||||
|
||||
/**
|
||||
* Spring {@link Configuration} class to configure Apache Geode client {@link Region Regions}
|
||||
* with interest registration on all keys.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.springframework.context.annotation.Configuration
|
||||
* @see org.springframework.data.gemfire.client.ClientRegionFactoryBean
|
||||
* @see org.springframework.data.gemfire.client.Interest
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableCachingDefinedRegions
|
||||
* @see org.springframework.data.gemfire.config.annotation.RegionConfigurer
|
||||
* @since 1.1.0
|
||||
*/
|
||||
// tag::class[]
|
||||
@Configuration
|
||||
//@EnableCachingDefinedRegions(clientRegionShortcut = ClientRegionShortcut.CACHING_PROXY)
|
||||
public class GeodeConfiguration {
|
||||
|
||||
// TODO: Replace with the SDG `@EnableCachingDefineRegions annotation declared above (and currently commented out,
|
||||
// because...) once DATAGEODE-219 is resolved. :(
|
||||
// tag::region[]
|
||||
@Bean("YellowPages")
|
||||
public ClientRegionFactoryBean<Object, Object> yellowPagesRegion(GemFireCache gemfireCache) {
|
||||
|
||||
ClientRegionFactoryBean<Object, Object> clientRegion = new ClientRegionFactoryBean<>();
|
||||
|
||||
clientRegion.setCache(gemfireCache);
|
||||
clientRegion.setClose(false);
|
||||
clientRegion.setShortcut(ClientRegionShortcut.CACHING_PROXY);
|
||||
|
||||
clientRegion.setRegionConfigurers(
|
||||
interestRegisteringRegionConfigurer(),
|
||||
subscriptionCacheListenerRegionConfigurer()
|
||||
);
|
||||
|
||||
return clientRegion;
|
||||
}
|
||||
// end::region[]
|
||||
|
||||
// tag::interest-registration[]
|
||||
@Bean
|
||||
RegionConfigurer interestRegisteringRegionConfigurer() {
|
||||
|
||||
return new RegionConfigurer() {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void configure(String beanName, ClientRegionFactoryBean<?, ?> clientRegion) {
|
||||
|
||||
Interest interest = new RegexInterest(".*", InterestResultPolicy.NONE,
|
||||
false, true);
|
||||
|
||||
clientRegion.setInterests(ArrayUtils.asArray(interest));
|
||||
}
|
||||
};
|
||||
}
|
||||
// end::interest-registration[]
|
||||
|
||||
// tag::subscription-cache-listener[]
|
||||
@Bean
|
||||
RegionConfigurer subscriptionCacheListenerRegionConfigurer() {
|
||||
|
||||
return new RegionConfigurer() {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void configure(String beanName, ClientRegionFactoryBean<?, ?> clientRegion) {
|
||||
|
||||
CacheListener subscriptionCacheListener = new AbstractCommonEventProcessingCacheListener() {
|
||||
|
||||
@Override
|
||||
protected void processEntryEvent(EntryEvent event, EntryEventType eventType) {
|
||||
|
||||
if (event.isOriginRemote()) {
|
||||
System.err.printf("[%1$s] EntryEvent for [%2$s] with value [%3$s]%n",
|
||||
event.getKey(), event.getOperation(), event.getNewValue());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
clientRegion.setCacheListeners(ArrayUtils.asArray(subscriptionCacheListener));
|
||||
}
|
||||
};
|
||||
}
|
||||
// end::subscription-cache-listener[]
|
||||
}
|
||||
// end::class[]
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2019 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.app.near.caching.client.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import example.app.near.caching.client.model.Person;
|
||||
import example.app.near.caching.client.service.YellowPagesService;
|
||||
|
||||
/**
|
||||
* Spring {@link RestController} class for implementing the UI to the Yellow Pages application.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.web.bind.annotation.GetMapping
|
||||
* @see org.springframework.web.bind.annotation.RestController
|
||||
* @see example.app.near.caching.client.model.Person
|
||||
* @see example.app.near.caching.client.service.YellowPagesService
|
||||
* @since 1.1.0
|
||||
*/
|
||||
// tag::class[]
|
||||
@RestController
|
||||
public class YellowPagesController {
|
||||
|
||||
private static final String HTML =
|
||||
"<html><title>Yellow Pages</title><body bgcolor=\"#F5FC1D\" text=\"black\"><h1>%s</h1><body><html>";
|
||||
|
||||
@Autowired
|
||||
private YellowPagesService yellowPages;
|
||||
|
||||
@GetMapping("/")
|
||||
public String home() {
|
||||
return format("Near Caching Example");
|
||||
}
|
||||
|
||||
@GetMapping("/ping")
|
||||
public String ping() {
|
||||
return format("PONG");
|
||||
}
|
||||
|
||||
@GetMapping("/yellow-pages/{name}")
|
||||
public String find(@PathVariable("name") String name) {
|
||||
|
||||
long t0 = System.currentTimeMillis();
|
||||
|
||||
Person person = this.yellowPages.find(name);
|
||||
|
||||
return format(String.format("{ person: %s, cacheMiss: %s, latency: %d ms }",
|
||||
person, this.yellowPages.isCacheMiss(), (System.currentTimeMillis() - t0)));
|
||||
}
|
||||
|
||||
@GetMapping("/yellow-pages/{name}/update")
|
||||
public String update(@PathVariable("name") String name,
|
||||
@RequestParam(name = "email", required = false) String email,
|
||||
@RequestParam(name = "phoneNumber", required = false) String phoneNumber) {
|
||||
|
||||
Person person = this.yellowPages.save(this.yellowPages.find(name), email, phoneNumber);
|
||||
|
||||
return format(String.format("{ person: %s }", person));
|
||||
}
|
||||
|
||||
@GetMapping("/yellow-pages/{name}/evict")
|
||||
public String evict(@PathVariable("name") String name) {
|
||||
|
||||
this.yellowPages.evict(name);
|
||||
|
||||
return format(String.format("Evicted %s", name));
|
||||
}
|
||||
|
||||
private String format(String value) {
|
||||
return String.format(HTML, value);
|
||||
}
|
||||
}
|
||||
// end::class[]
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2019 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.app.near.caching.client.model;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* {@link Person} models a person (human being).
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
*/
|
||||
// tag::class[]
|
||||
@Getter
|
||||
@EqualsAndHashCode(of = "name")
|
||||
@ToString(of = { "name", "email", "phoneNumber" })
|
||||
@RequiredArgsConstructor(staticName = "newPerson")
|
||||
public class Person {
|
||||
|
||||
@NonNull
|
||||
private String name;
|
||||
|
||||
private String email;
|
||||
private String phoneNumber;
|
||||
|
||||
public Person withEmail(String email) {
|
||||
this.email = email;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Person withPhoneNumber(String phoneNumber) {
|
||||
this.phoneNumber = phoneNumber;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
// end::class[]
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2019 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.app.near.caching.client.service;
|
||||
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.CachePut;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import example.app.near.caching.client.model.Person;
|
||||
import example.app.near.caching.client.service.support.AbstractCacheableService;
|
||||
import example.app.near.caching.client.service.support.EmailGenerator;
|
||||
import example.app.near.caching.client.service.support.PhoneNumberGenerator;
|
||||
|
||||
/**
|
||||
* Spring {@link Service} class implementing the Yellow Pages.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.cache.annotation.Cacheable
|
||||
* @see org.springframework.stereotype.Service
|
||||
* @see example.app.near.caching.client.model.Person
|
||||
* @see example.app.near.caching.client.service.support.AbstractCacheableService
|
||||
* @see example.app.near.caching.client.service.support.EmailGenerator
|
||||
* @see example.app.near.caching.client.service.support.PhoneNumberGenerator
|
||||
* @since 1.1.0
|
||||
*/
|
||||
// tag::class[]
|
||||
@Service
|
||||
public class YellowPagesService extends AbstractCacheableService {
|
||||
|
||||
@Cacheable(cacheNames = "YellowPages", key = "#name")
|
||||
public Person find(String name) {
|
||||
|
||||
this.cacheMiss.set(true);
|
||||
|
||||
Person person = Person.newPerson(name)
|
||||
.withEmail(EmailGenerator.generate(name, null))
|
||||
.withPhoneNumber(PhoneNumberGenerator.generate(null));
|
||||
|
||||
simulateLatency();
|
||||
|
||||
return person;
|
||||
}
|
||||
|
||||
@CachePut(cacheNames = "YellowPages", key = "#person.name")
|
||||
public Person save(Person person, String email, String phoneNumber) {
|
||||
|
||||
if (StringUtils.hasText(email)) {
|
||||
person.withEmail(email);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(phoneNumber)) {
|
||||
person.withPhoneNumber(phoneNumber);
|
||||
}
|
||||
|
||||
return person;
|
||||
}
|
||||
|
||||
@CacheEvict(cacheNames = "YellowPages")
|
||||
public boolean evict(String name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// end::class[]
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2019 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.app.near.caching.client.service.support;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Abstract base class for implementing cacheable {@link Service services} along with additional functionality to
|
||||
* ascertain whether a cacheable operation led to a cache hit or a cache miss.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
// tag::class[]
|
||||
public abstract class AbstractCacheableService {
|
||||
|
||||
protected static final int BOUNDED_MULTIPLIER = 3;
|
||||
|
||||
protected static final long BASE_MILLISECONDS = 2000L;
|
||||
protected static final long ONE_SECOND_IN_MILLISECONDS = 1000L;
|
||||
|
||||
protected final AtomicBoolean cacheMiss = new AtomicBoolean(false);
|
||||
|
||||
protected final Random multiplier = new Random(System.currentTimeMillis());
|
||||
|
||||
public boolean isCacheHit() {
|
||||
return !isCacheMiss();
|
||||
}
|
||||
|
||||
public boolean isCacheMiss() {
|
||||
return this.cacheMiss.compareAndSet(true,false);
|
||||
}
|
||||
|
||||
protected long delayInMilliseconds() {
|
||||
return BASE_MILLISECONDS + (ONE_SECOND_IN_MILLISECONDS * this.multiplier.nextInt(BOUNDED_MULTIPLIER));
|
||||
}
|
||||
|
||||
protected boolean simulateLatency() {
|
||||
return simulateLatency(delayInMilliseconds());
|
||||
}
|
||||
|
||||
protected boolean simulateLatency(long milliseconds) {
|
||||
|
||||
try {
|
||||
Thread.sleep(milliseconds);
|
||||
return true;
|
||||
}
|
||||
catch (InterruptedException ignore) {
|
||||
Thread.currentThread().interrupt();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// end::class[]
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2019 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.app.near.caching.client.service.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Generates {@link String email addresses} given a person's {@link String name}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
*/
|
||||
// tag::class[]
|
||||
public class EmailGenerator {
|
||||
|
||||
private static final String AT_APPLE_COM = "@apple.com";
|
||||
private static final String AT_COMCAST_NET = "@comcast.net";
|
||||
private static final String AT_GMAIL_COM = "@gmail.com";
|
||||
private static final String AT_HOME_ORG = "@home.org";
|
||||
private static final String AT_MICROSOFT_COM = "@microsoft.com";
|
||||
private static final String AT_NASA_GOV = "@nasa.gov";
|
||||
private static final String AT_PIVOTAL_IO = "@pivotal.io";
|
||||
private static final String AT_YAHOO_COM = "@yahoo.com";
|
||||
|
||||
private static final List<String> AT_EMAIL_ADDRESSES = Arrays.asList(
|
||||
AT_APPLE_COM,
|
||||
AT_COMCAST_NET,
|
||||
AT_GMAIL_COM,
|
||||
AT_HOME_ORG,
|
||||
AT_MICROSOFT_COM,
|
||||
AT_NASA_GOV,
|
||||
AT_PIVOTAL_IO,
|
||||
AT_YAHOO_COM
|
||||
);
|
||||
|
||||
private static final Random index = new Random(System.currentTimeMillis());
|
||||
|
||||
public static String generate(String name, String email) {
|
||||
|
||||
Assert.hasText(name, "Name is required");
|
||||
|
||||
if (!StringUtils.hasText(email)) {
|
||||
|
||||
name = name.toLowerCase();
|
||||
name = StringUtils.trimAllWhitespace(name);
|
||||
email = String.format("%1$s%2$s", name,
|
||||
AT_EMAIL_ADDRESSES.get(index.nextInt(AT_EMAIL_ADDRESSES.size())));
|
||||
}
|
||||
|
||||
return email;
|
||||
}
|
||||
}
|
||||
// end::class[]
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2019 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.app.near.caching.client.service.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.shiro.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Generates random phone number using a few well-defined area codes.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.1.0
|
||||
*/
|
||||
// tag::class[]
|
||||
public class PhoneNumberGenerator {
|
||||
|
||||
private static int CALIFORNIA_AREA_CODE = 707;
|
||||
private static int IOWA_AREA_CODE = 319;
|
||||
private static int MONTANA_AREA_CODE = 406;
|
||||
private static int NEW_YORK_AREA_CODE = 914;
|
||||
private static int OREGON_AREA_CODE = 503;
|
||||
private static int WASHINGTON_AREA_CODE = 206;
|
||||
private static int WISCONSIN_AREA_CODE = 608;
|
||||
|
||||
private static final List<Integer> PHONE_NUMBER_AREA_CODES = Arrays.asList(
|
||||
CALIFORNIA_AREA_CODE,
|
||||
IOWA_AREA_CODE,
|
||||
MONTANA_AREA_CODE,
|
||||
NEW_YORK_AREA_CODE,
|
||||
OREGON_AREA_CODE,
|
||||
WASHINGTON_AREA_CODE,
|
||||
WISCONSIN_AREA_CODE
|
||||
);
|
||||
|
||||
private static final Random index = new Random(System.currentTimeMillis());
|
||||
|
||||
public static String generate(String phoneNumber) {
|
||||
|
||||
if (!StringUtils.hasText(phoneNumber)) {
|
||||
|
||||
phoneNumber = String.valueOf(PHONE_NUMBER_AREA_CODES.get(index.nextInt(PHONE_NUMBER_AREA_CODES.size())))
|
||||
.concat("-")
|
||||
.concat(String.valueOf(index.nextInt(9)))
|
||||
.concat(String.valueOf(index.nextInt(9)))
|
||||
.concat(String.valueOf(index.nextInt(9)))
|
||||
.concat("-")
|
||||
.concat(String.valueOf(index.nextInt(9)))
|
||||
.concat(String.valueOf(index.nextInt(9)))
|
||||
.concat(String.valueOf(index.nextInt(9)))
|
||||
.concat(String.valueOf(index.nextInt(9)));
|
||||
}
|
||||
|
||||
return phoneNumber;
|
||||
}
|
||||
}
|
||||
// end::class[]
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2019 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.app.near.caching.server;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.apache.geode.cache.DataPolicy;
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.RegionAttributes;
|
||||
import org.apache.geode.cache.server.CacheServer;
|
||||
|
||||
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 org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.gemfire.RegionAttributesFactoryBean;
|
||||
import org.springframework.data.gemfire.ReplicatedRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.CacheServerApplication;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableLocator;
|
||||
import org.springframework.data.gemfire.config.annotation.EnableManager;
|
||||
|
||||
import example.app.near.caching.client.model.Person;
|
||||
|
||||
/**
|
||||
* Spring Boot application that configures and bootstraps an Apache Geode {@link CacheServer} application.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.server.CacheServer
|
||||
* @see org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
* @see org.springframework.boot.builder.SpringApplicationBuilder
|
||||
* @see org.springframework.data.gemfire.config.annotation.CacheServerApplication
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableLocator
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableManager
|
||||
* @since 1.1.0
|
||||
*/
|
||||
// tag::class[]
|
||||
@SpringBootApplication
|
||||
@CacheServerApplication
|
||||
@SuppressWarnings("unused")
|
||||
public class BootGeodeNearCachingCacheServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
new SpringApplicationBuilder(BootGeodeNearCachingCacheServerApplication.class)
|
||||
.web(WebApplicationType.NONE)
|
||||
.build()
|
||||
.run(args);
|
||||
}
|
||||
|
||||
// tag::application-runner[]
|
||||
@Bean
|
||||
ApplicationRunner runner(@Qualifier("YellowPages") Region<String, Person> yellowPagesRegion) {
|
||||
|
||||
return args -> {
|
||||
|
||||
assertThat(yellowPagesRegion).isNotNull();
|
||||
assertThat(yellowPagesRegion.getName()).isEqualTo("YellowPages");
|
||||
assertThat(yellowPagesRegion.getAttributes()).isNotNull();
|
||||
assertThat(yellowPagesRegion.getAttributes().getDataPolicy()).isEqualTo(DataPolicy.REPLICATE);
|
||||
assertThat(yellowPagesRegion.getAttributes().getEnableSubscriptionConflation()).isTrue();
|
||||
|
||||
};
|
||||
}
|
||||
// end::application-runner[]
|
||||
|
||||
// tag::geode-configuration[]
|
||||
@Configuration
|
||||
static class GeodeConfiguration {
|
||||
|
||||
@Bean("YellowPages")
|
||||
public ReplicatedRegionFactoryBean<Object, Object> yellowPagesRegion(GemFireCache gemfireCache,
|
||||
@Qualifier("YellowPagesAttributes") RegionAttributes<Object, Object> exampleAttributes) {
|
||||
|
||||
ReplicatedRegionFactoryBean<Object, Object> yellowPagesRegion =
|
||||
new ReplicatedRegionFactoryBean<>();
|
||||
|
||||
yellowPagesRegion.setAttributes(exampleAttributes);
|
||||
yellowPagesRegion.setCache(gemfireCache);
|
||||
yellowPagesRegion.setClose(false);
|
||||
yellowPagesRegion.setPersistent(false);
|
||||
|
||||
return yellowPagesRegion;
|
||||
}
|
||||
|
||||
@Bean("YellowPagesAttributes")
|
||||
public RegionAttributesFactoryBean<Object, Object> exampleRegionAttributes() {
|
||||
|
||||
RegionAttributesFactoryBean<Object, Object> yellowPagesRegionAttributes =
|
||||
new RegionAttributesFactoryBean<>();
|
||||
|
||||
yellowPagesRegionAttributes.setEnableSubscriptionConflation(true);
|
||||
|
||||
return yellowPagesRegionAttributes;
|
||||
}
|
||||
}
|
||||
// end::geode-configuration[]
|
||||
|
||||
// tag::locator-manager[]
|
||||
@Configuration
|
||||
@EnableLocator
|
||||
@EnableManager(start = true)
|
||||
@Profile("locator-manager")
|
||||
static class LocatorManagerConfiguration { }
|
||||
// end::locator-manager[]
|
||||
|
||||
}
|
||||
// end::class[]
|
||||
@@ -0,0 +1,4 @@
|
||||
# Spring Boot application.properties for the Apache Geode ClientCache One application.
|
||||
|
||||
server.port=8181
|
||||
spring.application.name=ClientApplicationOne
|
||||
@@ -0,0 +1,4 @@
|
||||
# Spring Boot application.properties for the Apache Geode ClientCache Two application.
|
||||
|
||||
server.port=8282
|
||||
spring.application.name=ClientApplicationTwo
|
||||
@@ -0,0 +1,4 @@
|
||||
# Spring Boot application.properties for the Apache Geode ClientCache application
|
||||
|
||||
spring.application.name=ClientApplication
|
||||
spring.data.gemfire.pool.subscription-enabled=true
|
||||
@@ -0,0 +1,3 @@
|
||||
# Spring Boot application.properties for the Apache Geode CacheServer application.
|
||||
|
||||
spring.application.name=YellowPagesServer
|
||||
@@ -0,0 +1,3 @@
|
||||
# Spring Boot application.properties for both the Apache Geode ClientCache and CacheServer applications.
|
||||
|
||||
spring.data.gemfire.cache.log-level=config
|
||||
Reference in New Issue
Block a user