How to implement caching in Spring in non-component classes - java

I understand that for caching annotations like #Cacheable, #CachePut to work, they should be used in Spring Component class. But, I have a class that is not a Spring component or service, but I need to implement caching on one of the methods in that class.
#CachePut(cacheNames = {"NAME_OF_CACHE"})
public Object addToCache(String cacheKey) {
// Some computation here
return response;
}
I have a roadblock for converting this class to a component. Objects of this class will be initialized during runtime. Is there any way to implement this functionality?

You can manage the caching manually:
1- when you enter the function, check if the cache has the record you want and return it if yes.
2- in the end of the function insert to the cache before you return the result.
Note: you need to have an instance of your cache inside this class which is doable but not preferable.
On the other hand, if you have a problem in converting it to component because it needs to be instantiated in the runtime. Spring provides this capability, you just need to check the scope option.
You can choose the prototype scope for your purpose.

Related

Spring #Cacheable : need to know value return from cache or not

Our applications using Spring Cache and need to know if response was returned from cache OR it was actually calculated. We are looking to add a flag in result HashMap that will indicate it. However whatever is returned by method, it is cached so not sure if we can do it in calculate method implementation.
Is there any way to know if calculate method was executed OR return value coming from cache when calling calculate method?
Code we are using for calculate method -
#Cacheable(
cacheNames = "request",
key = "#cacheMapKey",
unless = "#result['ErrorMessage'] != null")
public Map<String, Object> calculate(Map<String, Object> cacheMapKey, Map<String, Object> message) {
//method implementation
return result;
}
With a little extra work, it is rather simple to add a bit of state to your #Cacheable component service methods.
I use this technique when I am answering SO questions like this to show that the value came from the cache vs. the service method by actually computing the value. For example.
You will notice this #Cacheable, #Service class extends an abstract base class (CacheableService) to help manage the "cacheable" state. That way, multiple #Cacheable, #Service classes can utilize this functionality if need be.
The CacheableService class contains methods to query the state of the cache operation, like isCacheMiss() and isCacheHit(). Inside the #Cacheable methods, when invoked due to a "cache miss", is where you would set this bit, by calling setCacheMiss(). Again, the setCacheMiss() method is called like so, inside your #Cacheable service method.
However, a few words of caution!
First, while the abstract CacheableService class manages the state of the cacheMiss bit with a Thread-safe class (i.e. AtomicBoolean), the CacheableService class itself is not Thread-safe when used in a highly concurrent environment when you have multiple #Cacheable service methods setting the cacheMiss bit.
That is, if you have a component class with multiple #Cacheable service methods all setting the cacheMiss bit using setCacheMiss() in a multi-Threaded environment (which is especially true in a Web application) then it is possible to read stale state of cacheMiss when querying the bit. Meaning, the cacheMiss bit could be true or false depending on the state of the cache, the operation called and the interleaving of Threads. Therefore, more work is needed in this case, so be careful if you are relying on the state of the cacheMiss bit for critical decisions.
Second, this approach, using an abstract CacheableService class, does not work for Spring Data (CRUD) Repositories based on an interface. As others have mentioned in the comments, you could encapsulate this caching logic in an AOP Advice and intercept the appropriate calls, in this case. Personally, I prefer that caching, security, transactions, etc, all be managed in the Service layer of the application rather than the Data Access layer.
Finally, there are undoubtedly other limitations you might run into, as the example code I have provided above was never meant for production, only demonstration purposes. I leave it to you as an exercise to figure out how to mold these bits for your needs.

Correct way of finding what was modified by a post in an spring-mvc controller?

It is a rather general question, but I will give a stripped down example. Say I have a Web CRUD application that manages simple entities stored in a database, nothing but classic : JSP view, RequestMapping annotated controller, transactional service layer and DAO.
On an update, I need to know the previous values of my fields, because a business rule asks a for a test involving the old and new values.
So I am searching for a best practice on that use case.
I thing that spring code is way more extensively tested and more robust than my own, and I would like to do it the spring way as much as possible.
Here is what I have tried :
1/ load an empty object in controller and manage the update in service :
Data.java:
class Data {
int id; // primary key
String name;
// ... other fields, getters, and setters omitted for brevity
}
DataController
...
#RequestMapping("/data/edit/{id}", method=RequestMethod.GET)
public String edit(#PathVariable("id") int id, Model model) {
model.setAttribute("data", service.getData(id);
return "/data/edit";
}
#RequestMapping("/data/edit/{id}", method=RequestMethod.POST)
public String update(#PathVariable("id") int id, #ModelAttribute Data data, BindingResult result) {
// binding result tests omitted ..
service.update(id, data)
return "redirect:/data/show";
}
DataService
#Transactional
public void update(int id, Data form) {
Data data = dataDao.find(id);
// ok I have old values in data and new values in form -> do tests stuff ...
// and MANUALLY copy fields from form to data
data.setName(form.getName);
...
}
It works fine, but in real case, if I have many domain objects and many fields in each, it is quite easy to forget one ... when spring WebDataBinder has done it including validation in the controller without I have to write any single thing other than #ModelAttribute !
2/ I tried to preload the Data from the database by declaring a Converter
DataConverter
public class DataConverter<String, Data> {
Data convert(String strid) {
return dataService.getId(Integer.valueOf(strid));
}
}
Absolutely magic ! The data if fully initialized from database and fields present in form are properly updated. But ... no way to get the previous values ...
So my question is : what could be the way to use spring DataBinder magic and to have access to previous values of my domain objects ?
You have already found the possible choices so i will just add some ideas here ;)
I will start with your option of using a empty bean and copying the values over to a loaded instance:
As you have shown in your example it's an easy approach. It's quite easily adaptable to create a generalized solution.
You do not need to copy the properties manually! Take a look at the 'BeanWrapperImpl' class. This spring object allows you to copy properties and is in fact the one used by Spring itself to achieve it's magic. It's used by the 'ParameterResolvers' for example.
So copying properties is the easy part. Clone the loaded object, fill the loaded object and compare them somehow.
If you have one service or just several this is the way to go.
In my case we needed this feature on each entity. Using Hibernate we have the issue that an entity might not only change inside a specific service call, but theoretically all over the place..
So I decided to create a 'MappedSuperClass' which all entities need to extend. This entity has a 'PostLoad' event listener which clones the entity in a transient field directly after loading. (This works if you don't have to load thousands of entities in a request.) Then you need also the 'PostPersist' and 'PostUpdate' listeners to clone the new state again as you probably don't reload the entity before another modification.
To facilitate the controller mapping I have implemented a 'StringToEntityConverter' doing exactly what you did, just generalized to support any entity type.
Finding the changes in a generalized approach will involve quite a bit of reflection. It's not that hard and I don't have the code available right now, but you can also use the 'BeanWrapper' for that:
Create a wrapper for both objects. Get all 'PropertyDescriptors' and compare the results. The hardest part is to find out when to stop. Compare only the first level or do you need deep comparison?
One other solution could also be to rely on Hibernate Envers. This would work if you do not need the changes during the same transaction. As Envers tracks the changes during a flush and creates a 'Revision' you can "simply" fetch twp revisions and compare them.
In all scenarios you will have to write a comparison code. I'm not aware of a library but probably there is something around in the java world :)
Hope that helps a bit.

Custom Constructor : Apache Cayenne 3.2M

I'm new to the API. It appears to me that you have to construct objects via the 'context' object like this:
ServerRuntime cayenneRuntime = new ServerRuntime("cayenne-project.xml");
context = cayenneRuntime.newContext()
...
MyEntity entity=context.newObject(MyEntity.class);
Rather than just creating Java Objects in the usual new() way:
MyEntity entity=new MyEntity();
But I want to create a constructor for my 'MyEntity' class that would do something like:
public MyEntity(String inputFile) {
...
do setters based on information derived from inputFile (size, time created etc).
...
How can I achieve this - ideally I want to keep the logic on the class MyEntity itself, rather than having a 'wrapper' class somewhere else to instantiate the object and perform the setting.... I guess I could have a 'helper' method which just the settings on a previously instantiated instance...but is there an idiom I'm missing here...?
You got it right about creating the object via 'context.newObject(..)' - this is the best way to do it and will keep you out of trouble. Still you can actually have your own constructor (provided you also maintain a default constructor for the framework to use):
public MyEntity(String inputFile) {
...
}
public MyEntity() {
}
Then you can create your object first, and add it to the context after that:
MyEntity e = new MyEntity(inputFile);
context.registerNewObject(e);
As far as idioms go, a very common one is to avoid business logic in persistent objects. ORM models are often reused in more than one application, and behavior you add to the entities doesn't uniformly apply everywhere. The other side of this argument is that anything but simplest methods depend on the knowledge of the surrounding environment - something you don't want your entities to be aware of.
Instead one would write a custom service layer that sits on top of the entities and contains all the business logic (often used with a dependency injection container). Services are not wrappers of entities (in fact services are often singletons). You can think of them as configurable strategy objects. In the Java world such layered design and this type of separation of concerns is very common and is probably the most flexible approach.
But if you want to hack something quickly, and don't envision it to grow into a complex multi-module system, then using a custom constructor or a static factory method in the entity is just fine of course.

Struts2 xwork Type Conversion with hibernate

What is the best way to convert types in a Struts2 application?
Right now I want to create a CRUD for a certain hibernate entity in my application. Say I wanted to change the Account that a User is associated with. I can just pass in the parameter user.account.id with a specific value, provided that I have all of the proper getters/setters.
This works perfectly fine when creating an object for the first time, where the account would be null. This makes ognl create a new account object, and set the id to what was passed in.
The problem happens when trying to change the encapsulated Account object. Using the same user.account.id parameter, ognl interprets this as getUser().getAccount().setId(param). Hibernate interprets this as an attempt to change the primary key.
I understand why it does this, I am just wondering if there is better way for handling this case. This is very common in our application, and I don't want to have to keep creating multiple objects and marshaling them over before I save them via hibernate.
Does anyone no a better way to solve this problem in struts2?
Type Converters for Persistence
Create a type converter for the entity and then just pass user.account, rather than user.account.id. This will invoke getUser().setAccount(account) and wont cause you the headaches.
When you update the record, just pass user.account as a hidden field in the form.
As for a widespread solution for your entities, you have a few options:
Multiple Converters
Create an abstract type converter that handles most of the logic so that you have a subclass-per-entity that is really lightweight. Register each converter in your xwork-conversion.properties.
Interface-Driven Converter
The approach that I use is that I have an interface called IdBasedJpaEntity which 99.9% of my entities implement. It defines a getId() method of type Integer. I then have a JpaDAORegistry singleton class that I create when my app starts. I register each of my entities with it and it constructs a single instance of each DAO (basically, a de-facto singleton). I have a map of entity class to DAO instance. This allows my type converter to look up the appropriate DAO instance for any given IdBasedJpaEntity, allowing me to have a single JpaEntityConverter class that works with any entity that implements the interface. This route is a little bit more work up front, but has proven highly reusable for me.

Seam outjections will be removed?

Jacob Orshalick (author of Seam Framework: Experience the Evolution of Java EE ) said:
Outjection allows you to make variables available from the current context for injection or access through EL. This can be beneficial if you want to loosely couple several components that inject the same context variable (like the current user, the hotel being booked, etc). If you want to avoid outjection, an alternative is to use an #Factory method or set the value directly into the context through: Contexts.getConversationContext().set("myVarName", myVar)
Another benefit is performance. By outjecting a value to the context, you can bypass having to pass through your component to get that value. This is especially applicable in the case of data tables with JSF (see this discussion). But, as you will see in the discussion you could also use #BypassInterceptors to achieve the same benefit.
Outjection is really a convenience, but the same benefits can definitely be achieved through other means. Do note that outjection was not included in Web Beans and will either be deprecated or completely removed in Seam 3, so this is further reason to avoid it when possible.
We have an application with a lot of outjections and we've started to get rid of them. He said:
but the same benefits can definitely be achieved through other means.
but which are these other means? How to remove the outjections? In ASP.NET for instance you have session variables. In Seam, you can outject var in session (a benefit in some situations).
Or page scope: (for instance in jsf cycle the backing bean is called multiple times (sometimes). You have an account which is loaded from an accountId page param. You can load the account, outject it with a page scope and you can use its properties greatly. OR (to avoid outjection) is to have a loadAccount() method where you take the account from the db whenever you need it...WORST!)
I do not think that:
Contexts.getConversationContext().set("myVarName", myVar)
is a method of how to avoid outjection.
This only calls the same context where the outjected variable is saved and modifies it in a profound way (i think it's exactly what #Out do in the background).
Question 1: What do you think guys about their intention? Do you have specific info about how they will replace it?
Question2: How do you avoid the use of outjection?
Thanks in advance.
I think the best way you can achieve "outjection" is by using #Factory. Its advantage:
It can be #In-jected into another component
It can create any value, not just component instance
It calculate the value once, and just once
It can be triggered by JSF page (I am not sure whether you must enable Seam Transaction Management in order to get this feature)
So if you have a JSF page that needs to access a #Factory more than one time, It is calculated just once. If a value needs to be calculated each time it is requested, so you need a #Unwrap method. For instance, #{currentDate} built-in component is implemented as follows
#Name("org.jboss.seam.faces.facesContext")
#Scope(ScopeType.STATELESS) // ScopeType.STATELESS is similar to Spring prototype scope
public class CurrentDate {
#Unwrap
public Date getCurrentDate() {
return new java.sql.Date(System.currentTimeMillis());
}
}
regards,
To avoid outjection just add a getter to your field in your backing bean, so instead of:
#Name("myBean")
public class MyBean{
#Out
private SomeBean someBean;
}
you will have:
#Name("myBean")
public class MyBean{
private SomeBean someBean;
public SomeBean getSomeBean(){
return someBean;
}
}
and in your xhtml/jsp file you will have to call the getter instead but this have some issues too because everytime you call the getter all the Seam Interceptors will be applied to that call so you probably will need to add #BypassInterceptors to prevent that from happening.
And yes I also think that
Contexts.getConversationContext().set("myVarName", myVar)
is just doing what outject does but manually.

Categories