is it posible to add new value to ehcache in spring? - java

I am trying to use ehcache in my java project, it's new for me.
now i am using ehcache for retrieving area list, and my project adding new area , that time i am using #TriggersRemove functionality for once clear the cache and then reload it.
ex: i have retrive 10 areas and using ehcache , and i adding one more area that time i clear the cache and reload it.
is any other options for avoiding the data reload in cache.
my code:
#Cacheable(cacheName="retrieveAreas")
public List<AreaBO> retrieveAreas(){
//some code here
}
#TriggersRemove(cacheName="retrieveAreas", removeAll=true)
public long addArea(AreaBO areaBO) throws UserServiceException{
// some codes here
}

It seems that you are using the annotation from EhCache. If you where to switch to the caching annotations provided by Spring since version 3.1 your code would be:
#Cacheable(value="retrieveAreas")
public List<AreaBO> retrieveAreas(){
//some code here
}
#CachePut(value="retrieveAreas")
public long addArea(AreaBO areaBO) throws UserServiceException{
// some codes here
}
The difference as you can see is in the #CachePut annotation that adds the return value of the method to the cache specified.
I am not aware of a corresponding annotation in EHCache

Related

LazyInitializationException in unit tests under Spring-Data/Spring-Boot

My unit tests are seeing org.hibernate.LazyInitializationException: could not initialize proxy [org.openapitools.entity.MenuItem#5] - no Session. I'm not sure why they expect a session in a unit test. I'm trying to write to an in-memory h2 database for the unit tests of my Controller classes that implement the RESTful APIs. I'm not using any mock objects for the test, because I want to test the actual database transactions. This worked fine when I was using Spring-Boot version 1.x, but broke when I moved to version 2. (I'm not sure if that's what caused the tests to break, since I made lots of other changes. My point is that my code has passed these tests already.)
My Repositories extend JPARepository, so I'm using a standard Hibernate interface.
There are many answers to this question on StackOverflow, but very few describe a solution that I could use with Spring-Data.
Addendum: Here's a look at the unit test:
#Test
public void testDeleteOption() throws ResponseException {
MenuItemDto menuItemDto = createPizzaMenuItem();
ResponseEntity<CreatedResponse> responseEntity
= adminApiController.addMenuItem(menuItemDto);
final CreatedResponse body = responseEntity.getBody();
assertNotNull(body);
Integer id = body.getId();
MenuItem item = menuItemApiController.getMenuItemTestOnly(id);
// Hibernate.initialize(item); // attempted fix blows up
List<String> nameList = new LinkedList<>();
for (MenuItemOption option : item.getAllowedOptions()) { // blows up here
nameList.add(option.getName());
}
assertThat(nameList, hasItems("pepperoni", "olives", "onions"));
// ... (more code)
}
My test application.properties has these settings
spring.datasource.url=jdbc:h2:mem:pizzaChallenge;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=pizza
spring.datasource.password=pizza
spring.jpa.show-sql=true
This is not standard Hibernate, but spring data. You have to understand that Hibernate uses lazy loading to avoid loading the whole object graph from the database. If you close the session or connection to the database e.g. by ending a transaction, Hibernate can't lazy load anymore and apparently, your code tries to access state that needs lazy loading.
You can use #EntityGraph on your repository to specify that an association should be fetched or you avoid accessing the state that isn't initialized outside of a transaction. Maybe you just need to enlarge the transaction scope by putting #Transactional on the method that calls the repository and accesses the state, so that lazy loading works.
I found a way around this. I'm not sure if this is the best approach, so if anyone has any better ideas, I'd appreciate hearing from them.
Here's what I did. First of all, before reading a value from the lazy-loaded entity, I call Hibernate.initialize(item);
This throws the same exception. But now I can add a property to the test version of application.properties that says
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
Now the initialize method will work.
P.S. I haven't been able to find a good reference for Spring properties like this one. If anyone knows where I can see the available properties, I'd love to hear about it. The folks at Spring don't do a very good job of documenting these properties. Even when they mention a specific property, they don't provide a link that might explain it more thoroughly.

is there a Cacheable in C# similar to Java?

In Java Spring Boot, I can easily enable caching using the annotation #EnableCaching and make methods cache the result using #Cacheable, this way, any input to my method with the exact same parameters will NOT call the method, but return immediately using the cached result.
Is there something similar in C#?
What I did in the past was i had to implement my own caching class, my own data structures, its a big hassle. I just want an easy way for the program to cache the result and return the exact result if the input parameters are the same.
EDIT: I dont want to use any third party stuff, so no MemCached, no Redis, no RabbitMQ, etc... Just looking for a very simple and elegant solution like Java's #Cacheable.
Caches
A cache is the most valuable feature that Microsoft provides. It is a type of memory that is relatively small but can be accessed very quickly. It essentially stores information that is likely to be used again. For example, web browsers typically use a cache to make web pages load faster by storing a copy of the webpage files locally, such as on your local computer.
Caching
Caching is the process of storing data into cache. Caching with the C# language is very easy. System.Runtime.Caching.dll provides the feature for working with caching in C#. In this illustration I am using the following classes:
ObjectCache
MomoryCache
CacheItemPolicy
ObjectCache
: The CacheItem class provides a logical representation of a cache entry, that can include regions using the RegionName property. It exists in the System.Runtime.Caching.
MomoryCache
: This class also comes under System.Runtime.Caching and it represents the type that implements an in-cache memory.
CacheItemPolicy
: Represents a set of eviction and expiration details for a specific cache entry.
.NET provides
System.Web.Caching.Cache - default caching mechanizm in ASP.NET. You can get instance of this class via property Controller.HttpContext.Cache also you can get it via singleton HttpContext.Current.Cache. This class is not expected to be created explicitly because under the hood it uses another caching engine that is assigned internally. To make your code work the simplest way is to do the following:
public class DataController : System.Web.Mvc.Controller{
public System.Web.Mvc.ActionResult Index(){
List<object> list = new List<Object>();
HttpContext.Cache["ObjectList"] = list; // add
list = (List<object>)HttpContext.Cache["ObjectList"]; // retrieve
HttpContext.Cache.Remove("ObjectList"); // remove
return new System.Web.Mvc.EmptyResult();
}
}
System.Runtime.Caching.MemoryCache - this class can be constructed in user code. It has the different interface and more features like update\remove callbacks, regions, monitors etc. To use it you need to import library System.Runtime.Caching. It can be also used in ASP.net application, but you will have to manage its lifetime by yourself.
var cache = new System.Runtime.Caching.MemoryCache("MyTestCache");
cache["ObjectList"] = list; // add
list = (List<object>)cache["ObjectList"]; // retrieve
cache.Remove("ObjectList"); // remove
You can write a decorator with a get-or-create functionality. First, try to get value from cache, if it doesn't exist, calculate it and store in cache:
public static class CacheExtensions
{
public static async Task<T> GetOrSetValueAsync<T>(this ICacheClient cache, string key, Func<Task<T>> function)
where T : class
{
// try to get value from cache
var result = await cache.JsonGet<T>(key);
if (result != null)
{
return result;
}
// cache miss, run function and store result in cache
result = await function();
await cache.JsonSet(key, result);
return result;
}
}
ICacheClient is the interface you're extending. Now you can use:
await _cacheClient.GetOrSetValueAsync(key, () => Task.FromResult(value));

Unable to get good example of using memcached from Java boot

I am using java boot for my development. For now I have used 'EhCache' for caching , it is directly supported from Java boot. This is "in-process" cache, i.e., becomes part of your process. It is okay for now. But my server will run on multiple nodes in near future. Hence want to switch to 'Memcached' as common caching layer.
After spending good amount of time, I could not get good sample of using Memcached from java boot. I have looked at 'Simple Spring Memcached' which comes close to my requirement. But still it gives example using XML configuration in Spring way. Java boot does not use such XML configuration as far as possible. At least I could not map the example quickly to java boot world.
I want to use Memcahed ( directly or via cache-abstraction-layer) from java boot. If anybody points me to a relevant java boot example, it will save a lot of time for me.
You could also check Memcached Spring Boot library. It uses Memcached implementation for Spring Cache Abstraction.
In other words you use the same configuration and same annotations as you would use with any other Spring Cache implementation. You can check out here the usage of the library.
There are also example projects in Kotlin and Java.
I have already accepted answer given by #ragnor. But I think I should post a complete example here which has worked for me.
Make sure you have cache-enabled for your application by adding #EnableCaching
POM.xml should have following dependency:
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>spring-cache</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>spymemcached-provider</artifactId>
<version>3.6.1</version>
</dependency>
Add a config file to configure your memcached cache configuration, say MySSMConfig.java
#Configuration
#EnableAspectJAutoProxy
#ImportResource("simplesm-context.xml") // This line may or may not be needed,
// not sure
public class SSMConfig
{
private String _memcachedHost; //Machine where memcached is running
private int _memcachedPort; //Port on which memcached is running
#Bean
public CacheManager cacheManager()
{
//Extended manager used as it will give custom-expiry value facility in future if needed
ExtendedSSMCacheManager ssmCacheManager = new ExtendedSSMCacheManager();
//We can create more than one cache, hence list
List<SSMCache>cacheList = new ArrayList<SSMCache>();
//First cache: Testcache
SSMCache testCache = createNewCache(_memcachedHost, _memcachedPort,
"testcache", 5);
//One more dummy cache
SSMCache dummyCache = createNewCache(_memcachedHost,_memcachedPort,
"dummycache", 300);
cacheList.add(testCache);
cacheList.add(dummyCache);
//Adding cache list to cache manager
ssmCacheManager.setCaches(cacheList);
return ssmCacheManager;
}
//expiryTimeInSeconds: time(in seconds) after which a given element will expire
//
private SSMCache createNewCache(String memcachedServer, int port,
String cacheName, int expiryTimeInSeconds)
{
//Basic client factory to be used. This is SpyMemcached for now.
MemcacheClientFactoryImpl cacheClientFactory = new MemcacheClientFactoryImpl();
//Memcached server address parameters
//"127.0.0.1:11211"
String serverAddressStr = memcachedServer + ":" + String.valueOf(port);
AddressProvider addressProvider = new DefaultAddressProvider(serverAddressStr);
//Basic configuration object
CacheConfiguration cacheConfigToUse = getNewCacheConfiguration();
//Create cache factory
CacheFactory cacheFactory = new CacheFactory();
cacheFactory.setCacheName(cacheName);
cacheFactory.setCacheClientFactory(cacheClientFactory);
cacheFactory.setAddressProvider(addressProvider);
cacheFactory.setConfiguration(cacheConfigToUse);
//Get Cache object
Cache object = null;
try {
object = cacheFactory.getObject();
} catch (Exception e) {
}
//allow/disallow remove all entries from this cache!!
boolean allowClearFlag = false;
SSMCache ssmCache = new SSMCache(object, expiryTimeInSeconds, allowClearFlag);
return ssmCache;
}
private CacheConfiguration getNewCacheConfiguration()
{
CacheConfiguration ssmCacheConfiguration = new CacheConfiguration();
ssmCacheConfiguration.setConsistentHashing(true);
//ssmCacheConfiguration.setUseBinaryProtocol(true);
return ssmCacheConfiguration;
}
}
OK, we are ready to use our configured cache.
Sample methods in some other class to read from cache and to remove from cache
#Cacheable(value="dummycache, key="#givenId.concat('-dmy')", unless="#result == null")
public String getDummyDataFromMemCached(String givenId)
{
logger.warn("getDummyDataFromMemCached: Inside DUMMY method to actually get data");
return "Sample-" + String.valueOf(givenId);
}
#CacheEvict(value="dummycache",key="#givenId.concat('-dmy')")
public void removeDummyDataFromMemCached(String givenId)
{
//Do nothing
return;
}
Note that we have added suffix to the kache-keys. As Memcached does not support cache-zones, "dummycache" and "testcache" ultimately does not remain separate on a single server. (They may remain separate with some other cache implementation). Hence to avoid conflict, we append unique suffix to the cache-key.
If you want to cache objects of your own class, then make sure that they are serializable. Just change your class definition to 'XYZ implements Serializable'.
You can find some materials how to configure SSM using Java configuration instead of XML files here and here.
Basically you have to move definitions of all beans from XML to Java.

Dynamic argument for #CacheEvict

I am implementing EHcache in my project and i have written a method that will remove all entries from the cache. The method works fine, here's the code snippet:
public void removeEntriesFromCache(String cacheName){
CacheManager.getInstance.getCache(cacheName).removeAll();
}
I am eventually going to expose this method as a rest service so that user could call the service along with cache name that needs to be invalidated. However, i would want to be able to do the same using #CacheEvict. I know i can do this:
#CacheEvict(name ="myCache" , allEntries=true)
public void removeEntriesFromCache(){
}
But, this method will remove entries from just one cache , in this case it will remove all cache entries from "myCache". I want to be able to resolve the cache name dynamically at runtime as specified by the user.
Is it possible to achieve something like this:
#CacheEvict(name ="${cacheName}" , allEntries=true)
public void removeEntriesFromCache(String cacheName){
}
OR
#CacheEvict(name ="#cacheName" , allEntries=true)
public void removeEntriesFromCache(String cacheName){
}
Your suggestions would be welcome.
Thanks
#CacheEvict documentation clearly states where you can use SpEl. You can't use SpEl in the name attribute, but you can inject CacheManager to the bean you are annotating now, get the Cache by name and clear it.
cacheManager.getCache(cacheName).clear()

How to wrap Wicket page rendering in a Spring / Hibernate transaction?

My application loads entities from a Hibernate DAO, with OpenSessionInViewFilter to allow rendering.
In some cases I want to make a minor change to a field -
Long orderId ...
link = new Link("cancel") {
#Override public void onClick() {
Order order = orderDAO.load(orderId);
order.setCancelledTime(timeSource.getCurrentTime());
};
but such a change is not persisted, as the OSIV doesn't flush.
It seems a real shame to have to call orderDOA.save(order) in these cases, but I don't want to go as far as changing the FlushMode on the OSIV.
Has anyone found any way of declaring a 'request handling' (such as onClick) as requiring a transaction?
Ideally I suppose the transaction would be started early in the request cycle, and committed by the OSIV, so that all logic and rendering would take place in same transaction.
I generally prefer to use additional 'service' layer of code that wraps basic DAO
logic and provides transactions via #Transactional. That gives me better separation of presentation vs business logic and is
easier to test.
But since you already use OSIV may be you can just put some AOP interceptor around your code
and have it do flush()?
Disclaimer : I've never actually tried this, but I think it would work. This also may be a little bit more code than you want to write. Finally, I'm assuming that your WebApplication subclasses SpringWebApplication. Are you with me so far?
The plan is to tell Spring that we want to run the statements of you onClick method in a transaction. In order to do that, we have to do three things.
Step 1 : inject the PlatformTransactionManager into your WebPage:
#SpringBean
private PlatformTransactionManager platformTransactionManager;
Step 2 : create a static TransactionDefinition in your WebPage that we will later reference:
protected static final TransactionDefinition TRANSACTION_DEFINITION;
static {
TRANSACTION_DEFINITION = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
((DefaultTransactionDefinition) TRANSACTION_DEFINITION).setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE);
}
Feel free to change the TransactionDefinition settings and/or move the definition to a shared location as appropriate. This particular definition instructs Spring to start a new transaction even if there's already one started and to use the maximum transaction isolation level.
Step 3 : add transaction management to the onClick method:
link = new Link("cancel") {
#Override
public void onClick() {
new TransactionTemplate(platformTransactionManager, TRANSACTION_DEFINITION).execute(new TransactionCallback() {
#Override
public Object doInTransaction(TransactionStatus status) {
Order order = orderDAO.load(orderId);
order.setCancelledTime(timeSource.getCurrentTime());
}
}
}
};
And that should do the trick!

Categories

Resources