Can anybody here direct me in the right direction to develop a caching application? Any links to the example are appreciated.
Its pretty straight forward with Spring-boot.
Provide the couchbase-cluster configuration.
Define a bucket where every cache related data will be read/written into.
Spring expects a CacheManager bean. So define it something like this:
#Bean
public CacheManager cacheManager() {
CacheBuilder cacheBuilder =
CacheBuilder.newInstance(bucket()).withExpiration(TTL);
return new CouchbaseCacheManager(cacheBuilder, CACHE_NAME);
}
Add annotation #Configuration and #EnableCaching
Now for the usage you can use annotations #Cacheable, #CacheEvict, #CachePut etc.
Simple usage:
#Cacheable(CACHE_NAME)
public String getCompanyName(String companyId){}
Hope it helps.
Related
I have the following cache implementation in a Spring Boot app and it is working without any problem. However, I want to define expiration for this approach. Is it possible to set expiration for #Cacheable?
I look at Expiry time #Cacheable spring boot and there is not seem to be a direct way for #Cacheable. Is it possible via a smart approach?
#Configuration
#EnableCaching
public class CachingConfig {
#Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
}
}
#Component
public class SimpleCacheCustomizer
implements CacheManagerCustomizer<ConcurrentMapCacheManager> {
#Override
public void customize(ConcurrentMapCacheManager cacheManager) {
cacheManager.setCacheNames(asList("users"));
}
}
#Cacheable("users")
public List<User> getUsers(UUID id) {...}
As said in the Spring documentation, there is no TTL for the default cache system of Spring.
8.7. How can I Set the TTL/TTI/Eviction policy/XXX feature?
Directly through your cache provider. The cache abstraction is an
abstraction, not a cache implementation. The solution you use might
support various data policies and different topologies that other
solutions do not support (for example, the JDK
ConcurrentHashMap — exposing that in the cache abstraction would be
useless because there would no backing support). Such functionality
should be controlled directly through the backing cache (when
configuring it) or through its native API
You'll have to use an other cache provider like Redis or Gemfire if you want a TTL configuration.
An example of how to use TTL with Redis is available here.
I'm new in Spring applications, and see the big difference between configurations in springBoot and spring. So my questin is: apart from spring-boot, is there a way to setup a proper spring application(with web mvc, security, aop, ...), without any xml config file (ie : config relying only on annotations).
Yes, there is a way to do this in Spring. Spring Boot is after all an enhanced, autoconfigured Spring (with other cool features). That means that everything there is in Spring Boot should be achievable in Spring as well, but you would have do a bit/a lot of Your own extra work.
Moving straight to the point, in order to achieve what you want, you would need to undertake the following steps:
Create a class, which will store all the configuration (basically the properties you would store in the xml file) - let's call it AppConfig.class
Annotate the AppConfig.class with #Configuration - this will inform Spring that this class is the source of configuration;
Annotate the AppConfig.class with #ComponentScan("com.app") - here, You need to provide a package, from which Spring has to start component scanning in order to find Beans to be registered in Spring Container. Important note is, that it will scan the package and it's subpackages, so you would mostly want to provide here the top level package;
If you need some data to be injected into your beans, you would want to use the #PropertySource("classpath:application.properties") - I have provided here the default value, which Spring Boot uses internally in case you want to inject some data into your beans at runtime. For this to work, you need to inject into AppConfig.class an Environment.class
To show it on the example:
#Configuration
#ComponentScan("com.app")
#PropertySource("classpath:application.properties")
public class AppConfig {
// it will help to pull the properties incorporated in the file you have provided in the #PropertySource annotation
private Environment environment;
//inject it
public AppConfig(Environment environment) {
this.environment = environment;
}
// build your beans - the getProperty method accepts the key from application.properties
// file and return a value as a String. You can provide additional arguments to convert
//the value and a default value if the property is not found
#Bean
public Product product() {
return new Product(
environment.getProperty("product.name", "XXX"),
environment.getProperty("product.price", BigDecimal.class, BigDecimal.ZERO),
environment.getProperty("product.quantity", Integer.class, 10)
);
}
}
I hope that it helps
I have following declaration:
#Cacheable("books")
public Book findBook(ISBN isbn) {...}
But I want to update the cache every 30 minutes. I understand that I can create #Scheduled job to invoke method annotated #CacheEvict("books")
Also, I suppose that in this case all books will be cleared but it is more desirable to update only stale data(which were put in cache > 30 minutes ago)
Is there anything in spring that can facilitate implementation?
Cache implementations provide a feature named expire after write or time to life for this task. The different cache implementations have a lot variances. In Spring no effort was made to try to abstract or generalize the configuration part as well. Here is an example of programmatic configuration for your cache in Spring, if you like to use cache2k:
#Configuration
#EnableCaching
public class CachingConfig extends CachingConfigurerSupport {
#Bean
public CacheManager cacheManager() {
return new SpringCache2kCacheManager()
.addCaches(
b->b.name("books").keyType(ISBN.class).valueType(Book.class)
.expireAfterWrite(30, TimeUnit.MINUTES)
.entryCapacity(5000);
}
}
More information about this is in cache2k User Guide - Spring Framework Support. Other cache implementations like, EHCache or Caffeine support expiry as well, but the configuration is different.
If you like to configure the cache expiry in a "vendor neutral" way, you can use a cache implementation that support the JCache/JSR107 standard. The standard includes setting an expiry. A way to do it, looks like this:
#Configuration
#EnableCaching
public class CacheConfiguration {
#Bean
public JCacheCacheManager cacheManager() {
return new JCacheCacheManager() {
#Override
protected Collection<Cache> loadCaches() {
Collection<Cache> caches = new ArrayList<>();
caches.add(new JCacheCache(
getCacheManager().createCache("books",
new MutableConfiguration<ISBN,Book>()
.setExpiryPolicyFactory(ModifiedExpiryPolicy.factoryOf(new Duration(TimeUnit.MINUTES, 30)))),
false));
return caches;
}
};
}
}
The in JCache is, that there are configuration options, that you need, which are not part of the standard. One example is limiting the cache size. For this, you always need to add a vendor specific configuration. In case of cache2k (I am the author of cache2k), which supports JCache, the configurations are merged, which is described in detail at cache2k User Guide - JCache. This means on a programmatic level you do the "logic" part of the configuration, where as, the "operational" part like the cache size is configurable in an external configuration file.
Unfortunately, its not part of the standard how a vendor configuration and a programmatic configuration via the JCache API needs to interoperate. So, even a 100% JCache compatible cache might refuse operation, and require that you only use one way of configuration.
I have a scenario configuring Spring Security on embedded Jetty which seems to be somewhat solved if I make use of JavaConfig to configure the Jetty server.
As a result, it's looking like JavaConfig rather than XML might be the better option for large chunks of the project. However, there are some niceties in the XML namespaces, like <context:component-scan /> which aren't readily available in a #Configuration setting.
I have discovered that ApplicationContextAware is honored for #Configuration classes, so the following is possible
#Configuration
public class FooConfig implements ApplicationContextAware {
#Override
public void setApplicationContext(ApplicationContext applicationContext) {
((AnnotationConfigApplicationContext) applicationContext).scan("org.example");
}
}
The alternative, which is documented, is to have the #Configuration class use an #ImportResource annotation and pull in an existing XML file:
#Configuration
#ImportResource("applicationContext-withComponentScan.xml")
public class BarConfig {}
I guess the question is "Is it bad form to abuse ApplicationContextAware in this way, or is it really not abuse"? Something just feels oddly dirty about the approach so I'd not be surprised if the Spring guys had covered this in some way or another that I've not spotted.
For the interested, the problem relates to scanning a Jersey setup with #Resource and #Provider classes that I'd rather not have to manually manage entries in a class/XML configuration.
Now that Spring 3.1 is ready and out, you can safely use #ComponentScan if you are on Spring 3.1. It's not only for Spring MVC as one of the outdated answers mentions. You can use it as follows:
#Configuration
#ComponentScan({"com.foo.bar", "org.foo.bar"})
public class AppConfig{ /** config code */ }
Here is the documentation http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/ComponentScan.html
Is it bad form to abuse ApplicationContextAware in this way, or is it really not abuse
Yes, this is bad form. If you're going to fetch things out of the context manually, you may as well not bother with dependency injection in the first place.
However, your second option (#ImportResource("applicationContext-withComponentScan.xml")) is a good one - this is current best practice when you want to use these XML macros in combination with annotation-style config.
A third option is to use the current milestone build of Spring 3.1, which adds a way of doing these things all in Java, using #Feature. This is not yet production-ready, though.
Check this link out as well. It is a bit more specific (for a web application) but it has a very nice code example for the scanning, specifically: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html
from that link:
#ComponentScan(basePackages = { "org.example"} )
So in the latest version of Spring we are able to use the #Configuration annotation to setup our configurations for Spring. Now in JavaConfig it is possible to use the #AnnotationDrivenTx (#AnnotationDrivenTx Reference Link) annotation to setup transactions in our Config class. But since JavaConfig has been decommissioned I was wondering if anyone knew how to setup something similar without JavaConfig and without needing to add anything to the application-context.xml. Here is what I basically have for my Config class
#Configuration
#ImportResource("config/application-context.xml")
public class Config {
public #Bean DataSource dataSource() {
//get and return datasource
}
public #Bean Service1 getService1() {
//return service1Impl
}
}
And I'd like to make Service1 transactional. If anyone has any ideas on how to do this or if this is just not possible please let me know.
Thanks!
You can now use #EnableTransactionManagement.
See this post for more details: http://blog.springsource.com/2011/06/10/spring-3-1-m2-configuration-enhancements/
It seems like it isn't possible according to this forum post:
there may be a more first-class
mechanism for enabling
annotation-driven TX in #Configuration
classes in Spring 3.1, but in the
meantime, the recommended approach is
to use #ImportResource to include a
snippet of XML that declares
<tx:annotation-driven/>
Wait: but you seem to have an XML context anyway. Why not add <tx:annotation-driven/> to it and use #Transactional?
Take a look at http://blog.springsource.com/2011/02/17/spring-3-1-m1-featurespec. Spring 3.1's FeatureSpecification classes such as TxAnnotationDriven are designed to solve exactly the problem described above.