cache eviction in spring using regex key - spring

I am using spring cache where my cache should be updated and deleted for a particular key.
below is my code for inserting value in cache
#Cacheable(value = CACHE_NAME, key = "")
public InputStream getFiles(String fileName, String id) {
clearCache(fileName, id);
return restTemplate.getForObject(configurationFileUrl, InputStream.class, id);
}
for deleting
#CacheEvict(value = CACHE_NAME, key = " ")
public void clearCache(String fileName, String id) {
}
Here I am trying to pass the key as SpEL with regular expression which will delete the key starting with same file name but different than latest updated key. e.g if the cache had below entry
krishna1 -> obj1
now obj got modified in some other projects DB and now it is maintaining record
Krishna2 for reference to modified Obj1
So once call come to my service I need to check for combination name+key in cache, if it is not there I should insert new entry(Krishna2), but now my old entry with key name Krishna1 will never be used, so How do I delete it.
I can not create Key with filename otherwise it will not able to identify if file got modified or not.
Problem Statement:
suppose that I have one micro service which is maintaining the DB access and is deployed inside my domain name it Service1. The DB is containing 3 java class class1 -> for drawing rectancle, class2-> drawing circle and class3 -> for triangle. Now think you have micro service deployed outside somewhere and it is getting request to draw shape. Take the scenario that it got request to draw circle and it got config saying class2 and V1(version info) is responsible to draw circle. so it will make a rest call to service1 download class2 and compile it and cache it .class, so that next request it can serve directly if there is no change in draw circle logic(class2). The change in class2 may occur in future but rarely. Now coming to the problem next time once it got the request it will first check if it already has the class with same version if yes then draw the circle otherwise it will make rest call to get the update java file and will compile and cache it in memory. This is the reason I appended Version(id) appended to key so that it can differentiate if file is already there and changed.

Yeah, I am with #Hanno Binder on this one; seems you may have a design problem, specifically in the way you are trying to version objects in the Cache using the key to distinguish versions.
(Disclaimer) I am not fully understanding your requirements here, but it seems you could just simplify things a bit by keeping the latest (updated) version of an object in the cache using the same key. Why do the users of the cached object care what version is in use as long as they get the latest when it is available.
In this case, it is real simple to make sure the latest version is the one cached (and returned from #Cacheable methods) without having to resort to "special" eviction criteria by using the Spring #CachePut annotation. Then, you only need to make sure that all updates are routed though the method annotated with #CachePut. Subsequently, all #Cacheable methods called will get the latest "version".
Again, I apologize if I missed the mark on your requirements.

Related

Will Spring Data's save() method update an entity in the database if there are no changes in the entity?

When editing a form, the user may sometimes not change the form and still click the submit button. In one of the controller methods below, will the save() method perform a query to the database and update the fields even if the user didn't change anything?
PostMapping("/edit_entry/{entryId}")
public String update_entry(
#PathVariable("entryId") Long entryId,
#RequestParam String title,
#RequestParam String text
) {
Entry entry = this.entryRepo.findById(entryId).get();
if (!entry.getTitle().equals(title))
entry.setTitle(title);
if (!entry.getText().equals(text))
entry.setText(text);
this.entryRepo.save(entry);
return "redirect:/entries";
}
And also, are the "if" statements necessary in this case?
What exactly happens during a call to save(…) depends on the underling persistence technology. Fundamentally there a re two categories of implementations:
Implementations that actively manage entities. Examples of this are JPA and Neo4j. Those implementations keep track of the entities returned from the store and thus are able to detect changes in the first place. You pay for this with additional complexity as the entities are usually instrumented in some way and the change detection of course also takes time even if it ends up not detecting any changes. On the upside though the only trigger updates if needed.
Implementations that do not actively manage entities. Examples are JDBC and MongoDB. Those implementations do not keep track of entities loaded from the data store and thus do not instrument them. That also means that there is no way of detecting changes as all the implementation sees is an entity instance without any further context.
In your concrete example, a MongoDB implementation would still issue an update while JPA will not issue an update at all if the request params do not contain differing values.

#Cacheable() not returning proper cache

I am well aware that there are multiple questions on this topic, but I just can't get the sense of it. The problem seems to be that #CachePut does not add the new value to the #Cacheable list.
After debugging the problem I found out that the problem seems to be in the key.
Here is the code snippet
#CacheConfig(cacheNames = "documents")
interface DocumentRepository {
#CachePut(key = "#a0.id")
Document save(Document document);
#Cacheable()
List<Document> findAll();
}
So when I invoke the save method, the key being used for caching is incrementing integer, or 1,2,3...
But when I try to get all documents, the cache uses SimpleKey[] as key. If I try to use the same key for #Cacheable, I get SpelEvaluationException, property 'id' cannot be found on null.
So what I am left with at the end is functional cache (the data is saved in the cache), but somehow I am not able to retrieve it.
The underlying cache implementation is EhCache.
I really don't understand what you are expecting here.
It looks like you expect your findAll method to return the full content of the cache named documents. I don't think there is anything in the documentation that can let you conclude that this feature exists (it does not). It is also very fragile. If we were implementing that, findAll would return different results based on the state of the cache. If someone would configure this cache to have a max size of 100 for instance. Or If the cache isn't warm-up on startup.
You can't expect a cache abstraction (or even a cache library) to maintain a synchronized view of "a list of objects". What findAll does is returning the entry that corresponds to a key with no argument (new SimpleKey by default).

Entity Framework in detached mode with MVC application

I have started working out with Entity Framework (EF) for an MVC n-tier application. It would seem that very obvious that this being a web application (which is stateless), I would have to use detached object models. There is no ambiguity with doing an Add operation. However when doing an edit there are here are two ways
Fetch the original object in context, attach the updated object and
then save to database. Something like mentioned in answer to this
question
EF4 Context.ApplyCurrentValues does not update current values
Set individual modified properties explicitly using the IsModified property of individual fields of the object like
mentioned in this article
http://msdn.microsoft.com/en-us/data/jj592677.aspx
Method 1 has disadvantage of having to load object into memory from database each time an update needs to be performed.
Method 2 would require having to manually pass which fields to be set as IsModified to true from wherever the object an be updated. So for e.g. for each object, I may need to create a boolean collection object for each field of the object.
e.g.
SaveEntity(EntityClass e, EntityStateClass ec)
{
context.Entry(e).Property("Name").IsModified = ec.NameState;
context.SaveChanges();
}
class EntityStateClass{ public bool NameState;}
I would prefer method 2 simply for the sake of performance but I am hindered by the n-tier architecture and repository pattern I am using. My Repository interface restricts save method for any object to be
SaveEntity(EntityClass e);
So I cannot pass the "state" object. Context class is not available and should not be available outside DAL. So I cannot set property outside. Is there any "proper" way to achieve this ?
Note: Self-Tracking Entity is also out of question since I cannot send entities with state to client (the browser) since I am intent on keeping the html lightweight.
EDIT: After a lot of thinking, I am trying to use following mechanism to keep track of modified state for each field in my domain class
Declare a partial class for entity class.
For each field that is updateable, declare a boolean property like "IsModified_FieldName"
Set the "IsModified_FieldName" property when the field is set.
However for this I need Entity Framework to generate explicit properties for me instead of implicit properties that it auto-generates. Does EF provide an handle to do this ?
Here is sample code of what I am trying to achieve
//Save Method for class EntityClass.
SaveEntity(EntityClass e)
{
context.Entry(e).Property("Name").IsModified = e.IsModified_Name;
context.SaveChanges();
}
//EntityClass is class autogenerated by EF
public partial class EntityClass
{
//This is auto-generated property by EF
public string Name {get; set;}
/* This is what I would like EF to do
private string name;
public string Name
{
get {return Name;}
set {
name = value;
//this is what I would like to do
this.IsModified_Name = true;
};
}
*/
}
//This is another partial definition for EntityClass that I will provide
public partial class EntityClass
{
//This property will be set to true if "Name" is set
public bool IsModified_Name {get; set;}
}
PS: It seems the information I have provided is not sufficient and therefore there are no responses.
I am using DbContext (Database first model)
EF auto-generates the class files for me. So each time I update my database, the class files are regenerated.
To your concrete question: The entities are generated by a T4 template and it should be possible to modify this template (which is in text format) to generate the entities in a way you want to shape them.
But I have a few remarks about your concept:
In a web application data are usually changed by a user in a browser. To have a definite knowledge what really has been changed you need to track the changes in the browser (probably by some Javascript that sets flags in the data (a ViewModel for example) when a user edits a text box for instance).
If you don't track the changes in the browser what happens? The data get posted back to the server and you don't know at the server side (with MVC in a controller) which property has been changed. So, your only chance is to map all properties that has been posted back to your EntityClass and every property will be marked as Modified, no matter if the user really did a change or not. When you later call SaveChanges EF will write an UPDATE statement that involves all those properties and you have an unnecessary overhead that you you want to avoid.
So, what did you win by setting individual properties instead of setting the whole entity's state to Modified? In both cases you have marked all properties as Modified. Exceptions are partial changes of an entity, for example: You have a Customer entity that has a Name and City property and a view that only allows to edit the Name but not the City and a corresponding ViewModel that only contains a Name property. In this case your procedure would only mark the Name property of the Customer entity as Modified but not the City. You might save here a little bit because you don't save the City property value to the database. But you still save the Name even if it didn't change.
If you use solution 1 (ApplyCurrentValues) you have to load the entity first from the database, yes, but it would only mark the properties as Modified that really changed compared to their values in the database. If the user didn't change anything no UPDATE would be written at all.
Keep in mind that you are only at the beginning to implement your concept. There are other changes to the data that can happen in the browser than only scalar property changes, namely relationship changes. For example a user changes the relationship from an Order to a Customer or you have a view that has an Order and a collection of OrderItems and the user cannot only edit the Order header but also edit the OrderItems and remove and add new OrderItems. How do you want to recognize when the data come back from the browser to the server which collection item has been added and which has been removed - unless you track all those changes in the browser and send tracking information back to the server in addition to the actual data or unless you reload the Order and OrderItems from the database and merge the changes into the original entities from the database?
Personally I would vote for option 1 for these reasons:
You can use real POCOs that don't carry additional tracking information. (BTW: I have some doubt if you aren't reinventing the wheel by implementing your own tracking that EF change tracking proxies provide out of the box.)
You don't need to track changes in the browser which can become quite complex and will require Javascript in every Edit view to write change flags into hidden form fields or something.
You can use standard features of EF without having to implement your own tracking.
You are required to load entities from the database when you want to update an entity, that's true. But is this the real performance bottleneck in a web application where data have to run through the wire back and forth (and reflection (which isn't really known as to be fast) is involved by the model binder)? I have nothing said if your database is remote from the web server and connected by a 9600 baud modem. But otherwise, your plan is not only premature optimization, it is kind of premature architecture. You are starting to build a potentially complex architecture based on "it could be slow" to solve a performance problem that you actually don't know of whether it really exists.

Is Context.SaveChanges called automatically when an entity that is being tracked changes?

If an entities properties have changed in a controller action and Update/SaveChanges is not called, will that entity be updated automatically?
I am using EF 4.1 with a repository pattern. I handle all CRUD operations in my EfRepository class like this:
public void Update(T entity)
{
try{_context.SaveChanges();}
catch{//do stuff}
}
//etc.
In my application I have an ajax/ActionResult call that gets an entity from the db, performs some basic calculations, and returns a JSON object. To make a long story short I discovered a bug in a static helper I was using in my ActionResult that was changing a property value on my entity and not the JSON-model I was returning.
My action method has no Update methods yet my entity was being updated every time I called this action. Using Sql Profiler I confirmed an update statement that was tailored to update my entity and the one(1) property my buggy static method was changing.
I placed a break point at my Update method in my repository class and even though my entity was being updated by EF, MY Update method was never called. The summary for the interface method 'Find' (which is what I use) in IDbSet says,
Finds an entity with the given primary key values. If an entity with
the given primary key values exists in the context, then it is
returned immediately without making a request to the store. Otherwise,
a request is made to the store for an entity with the given primary
key values and this entity, if found, is attached to the context and
returned. If no entity is found in the context or the store, then null
is returned.
There are some real good example here as well.
I think given my entity was attached, the short answer to my question is 'YES'. But being somewhat new to EF I found this to be a very difficult bug to figure out as it still appears there some things going on under the covers that I could not track down. I hesitated in posting this as a question but thought someone more knowledgeable could expand on my assumed answer of YES and at the bare minimum help someone else who runs across this.
If an entities properties have changed in a controller action and
Update/SaveChanges is not called, will that entity be updated
automatically?
No, ef will only propagate your changes to the database on a SaveChanges call. Save only happens manually (IE you have to explicitly call SaveChanges).
What is really important to understand though is that SaveChanges saves all current modifications to the context. This means if you are sharing a context your changes will be saved when anyone (not just you) calls SaveChanges.

Static? Repositories MVC3, EF4.2 (Code First)

I'm new to MVC, EF and the like so I followed the MVC3 tutorial at http://www.asp.net/mvc and set up an application (not yet finished with everything though).
Here's the "architecture" of my application so far
GenericRepository
PropertyRepository inherits GenericRepository for "Property" Entity
HomeController which has the PropertyRepository as Member.
Example:
public class HomeController
{
private readonly PropertyRepository _propertyRepository
= new PropertyRepository(new ConfigurationDbContext());
}
Now let's consider the following:
I have a Method in my GenericRepository that takes quite some time, invoking 6 queries which need to be in one transaction in order to maintain integrity. My google results yeldet that SaveChanges() is considered as one transaction - so if I make multiple changes to my context and then call SaveChanges() I can be "sure" that these changes are "atomic" on the SQL Server. Right? Wrong?
Furthermore, there's is an action method that calls _propertyRepository.InvokeLongAndComplex() Method.
I just found out: MVC creates a new controller for each request. So I end up with multiple PropertyRepositories which mess up my Database Integrity. (I have to maintain a linked list of my properties in the database, and if a user moves a property it needs 6 steps to change the list accordingly but that way I avoid looping through all entities when having thousands...)
I thougth about making my GenericRepository and my PropertyRepository static, so every HomeController is using the same Repository and synchronize the InvokeLongAndComplex Method to make sure there's only one Thread making changes to the DB at a time.
I have the suspicion that this idea is not a good solution but I fail to find a suitable solution for this problem - some guys say that's okay to have static repositories (what happens with the context though?). Some other guys say use IOC/DI (?), which sounds like a lot of work to set up (not even sure if that solves my problem...) but it seems that I could "tell" the container to always "inject" the same context object, the same Repository and then it would be enough to synchronize the InvokeLongAndComplex() method to not let multiple threads mess up the integrity.
Why aren't data repositories static?
Answer 2:
2) You often want to have 1 repository instance per-request to make it easier to ensure that uncommited changes from one user don't mess things up for another user.
why have a repository instance per-request doesn't it mess up my linked list again?
Can anyone give me an advice or share a best practice which I can follow?
No! You must have a new context for each request so even if you make your repositories static you will have to pass current context instance to each its method instead of maintaining single context inside repository.
What you mean by integrity in the first place? Are you dealing with transactions, concurrency issues or referential constraints? Handling all of these issues is your responsibility. EF will provide some basic infrastructure for that but the final solution is still up to your implementation.

Resources