Polish cache sample
Update single cache sample with all supported cache providers. Add README to shortly explain how to get started with them. See gh-2633pull/3077/head
parent
23a278451a
commit
eef027a4f0
@ -0,0 +1,72 @@
|
||||
= Spring Boot Cache Sample
|
||||
|
||||
This sample demonstrates the caching auto-configuration support. Spring's caching
|
||||
abstraction is supported by many caching libraries, including:
|
||||
|
||||
* Any compliant `JSR-107` (JCache) provider
|
||||
* `EhCache`
|
||||
* `Hazelcast`
|
||||
* `Infinispan`
|
||||
* `Redis`
|
||||
* `Guava`
|
||||
* Simple provider based on `ConcurrentHashMap`
|
||||
|
||||
The sample defines a simple `CountryService` that caches countries by ISO code. When
|
||||
the application starts a client invokes the service with a random code every 500ms. You
|
||||
can look at the `/metrics` endpoint to review the cache statistics if your chosen
|
||||
caching provider is supported.
|
||||
|
||||
== Using a different cache provider
|
||||
|
||||
Initially, the project does not define any caching library so the abstraction works
|
||||
on simple `ConcurrentHashMap`-based caches. You can try out your favorite caching library
|
||||
as explained below.
|
||||
|
||||
=== EhCache 2.x
|
||||
|
||||
Simply add the `net.sf.ehcache:ehcache` dependency to the project. Since there is a
|
||||
default `ehcache.xml` configuration file at the root of the classpath, it is automatically
|
||||
used to configure the underlying `CacheManager`.
|
||||
|
||||
=== Hazelcast
|
||||
|
||||
Both `com.hazelcast:hazelcast` and `com.hazelcast:hazelcast-spring` should be added to
|
||||
the project to enable support for Hazelcast. Since there is a default `hazelcast.xml`
|
||||
configuration file at the root of the classpath, it is used to automatically configure
|
||||
the underlying `HazelcastInstance`.
|
||||
|
||||
=== Infinispan
|
||||
|
||||
Simply add the `org.infinispan:infinispan-spring4` dependency to enable support for
|
||||
Infinispan. There is no default location that Infinispan uses to look for a config
|
||||
file so if you don't specify anything it will bootstrap on a hardcoded default. You
|
||||
can set the `spring.cache.infinispan.config` property to use the provided
|
||||
`infinispan.xml` configuration instead.
|
||||
|
||||
=== JCache (JSR-107)
|
||||
|
||||
You do not need to use a JSR-107 compliant `CacheManager` to use the standard
|
||||
annotations. As a matter of a fact, this sample uses by default the standard annotations
|
||||
with a simple map-based `CacheManager` by default. If you want to configure your cache
|
||||
infrastructure via the standard, you need a compliant implementation. You could try
|
||||
the following:
|
||||
|
||||
* `Hazelcast`: add `com.hazelcast:hazelcast`
|
||||
* `Infinispan`: add `org.infinispan:infinispan-jcache`
|
||||
|
||||
|
||||
Since Spring Boot supports the native cache library and the JCache wrapper, you
|
||||
should set the `spring.cache.type` property to `jcache` to specify that you want the
|
||||
cache manager to be auto-configured that way.
|
||||
|
||||
=== Redis
|
||||
|
||||
Add the `spring-boot-starter-redis` and make sure it is configured properly (by default,
|
||||
a redis instance with the default settings is expected on your local box).
|
||||
|
||||
=== Guava
|
||||
|
||||
Spring Boot does not provide any dependency management for _Guava_ so you'll have to add
|
||||
the `com.google.guava:guava` dependency with a version. You can customize how caches are
|
||||
created in different ways, see `application.properties` for an example and the
|
||||
documentation for more details.
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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
|
||||
*
|
||||
* http://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 sample;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@EnableCaching
|
||||
@EnableScheduling
|
||||
@SpringBootApplication
|
||||
public class SampleCacheApplication {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SampleCacheApplication.class);
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder()
|
||||
.sources(SampleCacheApplication.class)
|
||||
.profiles("app")
|
||||
.run(args);
|
||||
}
|
||||
|
||||
@Component
|
||||
static class CacheManagerCheck implements CommandLineRunner {
|
||||
|
||||
private final CacheManager cacheManager;
|
||||
|
||||
@Autowired
|
||||
CacheManagerCheck(CacheManager cacheManager) {
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String... strings) throws Exception {
|
||||
logger.info("\n\n" + "=========================================================\n"
|
||||
+ "Using cache manager: " + this.cacheManager.getClass().getName() + "\n"
|
||||
+ "=========================================================\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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
|
||||
*
|
||||
* http://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 sample;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Profile("app")
|
||||
class SampleClient {
|
||||
|
||||
private static final List<String> SAMPLE_COUNTRY_CODES = Arrays.asList("AF", "AX", "AL", "DZ", "AS",
|
||||
"AD", "AO", "AI", "AQ", "AG", "AR", "AM", "AW", "AU", "AT", "AZ", "BS", "BH", "BD", "BB", "BY",
|
||||
"BE", "BZ", "BJ", "BM", "BT", "BO", "BQ", "BA", "BW", "BV", "BR", "IO", "BN", "BG", "BF", "BI",
|
||||
"KH", "CM", "CA", "CV", "KY", "CF", "TD", "CL", "CN", "CX", "CC", "CO", "KM", "CG", "CD", "CK",
|
||||
"CR", "CI", "HR", "CU", "CW", "CY", "CZ", "DK", "DJ", "DM", "DO", "EC", "EG", "SV", "GQ", "ER",
|
||||
"EE", "ET", "FK", "FO", "FJ", "FI", "FR", "GF", "PF", "TF", "GA", "GM", "GE", "DE", "GH", "GI",
|
||||
"GR", "GL", "GD", "GP", "GU", "GT", "GG", "GN", "GW", "GY", "HT", "HM", "VA", "HN", "HK", "HU",
|
||||
"IS", "IN", "ID", "IR", "IQ", "IE", "IM", "IL", "IT", "JM", "JP", "JE", "JO", "KZ", "KE", "KI",
|
||||
"KP", "KR", "KW", "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LI", "LT", "LU", "MO", "MK", "MG",
|
||||
"MW", "MY", "MV", "ML", "MT", "MH", "MQ", "MR", "MU", "YT", "MX", "FM", "MD", "MC", "MN", "ME",
|
||||
"MS", "MA", "MZ", "MM", "NA", "NR", "NP", "NL", "NC", "NZ", "NI", "NE", "NG", "NU", "NF", "MP",
|
||||
"NO", "OM", "PK", "PW", "PS", "PA", "PG", "PY", "PE", "PH", "PN", "PL", "PT", "PR", "QA", "RE",
|
||||
"RO", "RU", "RW", "BL", "SH", "KN", "LC", "MF", "PM", "VC", "WS", "SM", "ST", "SA", "SN", "RS",
|
||||
"SC", "SL", "SG", "SX", "SK", "SI", "SB", "SO", "ZA", "GS", "SS", "ES", "LK", "SD", "SR", "SJ",
|
||||
"SZ", "SE", "CH", "SY", "TW", "TJ", "TZ", "TH", "TL", "TG", "TK", "TO", "TT", "TN", "TR", "TM",
|
||||
"TC", "TV", "UG", "UA", "AE", "GB", "US", "UM", "UY", "UZ", "VU", "VE", "VN", "VG", "VI", "WF",
|
||||
"EH", "YE", "ZM", "ZW");
|
||||
|
||||
private final CountryRepository countryService;
|
||||
|
||||
private final Random random;
|
||||
|
||||
@Autowired
|
||||
public SampleClient(CountryRepository countryService) {
|
||||
this.countryService = countryService;
|
||||
this.random = new Random();
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 500)
|
||||
public void retrieveCountry() {
|
||||
String randomCode = SAMPLE_COUNTRY_CODES.get(random.nextInt(SAMPLE_COUNTRY_CODES.size()));
|
||||
System.out.println("Looking for country with code '" + randomCode + "'");
|
||||
this.countryService.findByCode(randomCode);
|
||||
}
|
||||
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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
|
||||
*
|
||||
* http://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 sample;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Eddú Meléndez
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Component
|
||||
public class Startup implements CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
private CountryService countryService;
|
||||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
System.out.println("---- calling country service");
|
||||
System.out.println(countryService.countries());
|
||||
System.out.println("---- calling country service again from cache.");
|
||||
System.out.println(countryService.countries());
|
||||
}
|
||||
|
||||
}
|
@ -1 +0,0 @@
|
||||
spring.cache.config=/cache/ehcache-override.xml
|
@ -0,0 +1,19 @@
|
||||
|
||||
|
||||
#
|
||||
# Infinispan configuration file location.
|
||||
#
|
||||
#spring.cache.infinispan.config=infinispan.xml
|
||||
|
||||
|
||||
#
|
||||
# JCache configuration (example with hazelcast).
|
||||
#
|
||||
#spring.cache.type=jcache
|
||||
#spring.cache.jcache.config=hazelcast.xml
|
||||
|
||||
|
||||
#
|
||||
# Guava configuration
|
||||
#
|
||||
#spring.cache.guava.spec=maximumSize=200,expireAfterAccess=600s
|
@ -1,8 +0,0 @@
|
||||
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect"
|
||||
dynamicConfig="true">
|
||||
<cache name="countries"
|
||||
maxBytesLocalHeap="50m"
|
||||
timeToLiveSeconds="100">
|
||||
</cache>
|
||||
</ehcache>
|
@ -1,8 +1,7 @@
|
||||
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect"
|
||||
dynamicConfig="true">
|
||||
xsi:noNamespaceSchemaLocation="ehcache.xsd">
|
||||
<cache name="countries"
|
||||
maxBytesLocalHeap="50m"
|
||||
timeToLiveSeconds="100">
|
||||
maxEntriesLocalHeap="200"
|
||||
timeToLiveSeconds="600">
|
||||
</cache>
|
||||
</ehcache>
|
||||
|
@ -0,0 +1,17 @@
|
||||
<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-3.4.xsd"
|
||||
xmlns="http://www.hazelcast.com/schema/config"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<map name="countries">
|
||||
<time-to-live-seconds>600</time-to-live-seconds>
|
||||
<max-size>200</max-size>
|
||||
</map>
|
||||
|
||||
<cache name="countries">
|
||||
<eviction size="200"/>
|
||||
|
||||
<statistics-enabled>true</statistics-enabled>
|
||||
<management-enabled>true</management-enabled>
|
||||
</cache>
|
||||
|
||||
</hazelcast>
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<infinispan xmlns="urn:infinispan:config:7.2">
|
||||
|
||||
<cache-container default-cache="default">
|
||||
<local-cache name="countries">
|
||||
<eviction max-entries="200"/>
|
||||
<expiration lifespan="600000"/>
|
||||
</local-cache>
|
||||
</cache-container>
|
||||
|
||||
</infinispan>
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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
|
||||
*
|
||||
* http://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 sample;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Eddú Meléndez
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = {SampleEhCacheCacheApplication.class})
|
||||
@ActiveProfiles("override")
|
||||
public class SampleEhCacheCacheApplicationOverrideTests extends AbstractEhCacheCacheTests {
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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
|
||||
*
|
||||
* http://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 sample;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Eddú Meléndez
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = {SampleEhCacheCacheApplication.class})
|
||||
public class SampleEhCacheCacheApplicationTests extends AbstractEhCacheCacheTests {
|
||||
|
||||
}
|
Loading…
Reference in New Issue