Sam
Sam

Reputation: 564

caching best practice java

I have a Struts based B2B application. There can be 20-25 list boxes in a page and the data in the list box can vary from customer to customer. Say for example list boxes will be Eligible Country list, Product Brand list etc. There will be multiple users under one customer. In the current solution the customer object is been set in application scope (ServletContext) when the first user under a customer logs in. This approach was taken to avoid database call on page load.

We are looking to re-architecture the solution expecting a 50% growth in customer base. The new application is going to be on Spring framework with Hibernate-JPA, at the end the application will be deployed on JBoss cluster. Looking for expert opinion for best caching approach to handle the list box data.

Thank You.

Upvotes: 4

Views: 5699

Answers (1)

Stephane Nicoll
Stephane Nicoll

Reputation: 33091

If your application is using Spring, a good start is the Caching abstraction, see also this blog post for a good introduction

Designing your model

You need to design a model for the content of those lists that you could probably reuse directly in your struts application. You probably don't want to cache the Country itself but more the filtered list as this is probably where you'll get the best gain. As your application is using Hibernate, you can easily enable the 2nd level cache in Hibernate for the entities anyway.

Once you have designed that, you need to find a way to generate a key that is good enough to identify a user of your application. Probably the id of a customer is a good candidate.

Creating your repository

You can then create a repository that provides the content of those lists based on some arguments. Ideally the only argument would be the key that identifies the customer but you can tweak that to your needs. For instance:

public class YourRepositoryImpl implements YourRepository {

  @Cacheable("modelCache")
  public YourModel get(String customerId) {
    // compute the list for that customer. 
    // Only called if not in the cache
  }

  ...
}

This basically instruct Spring to update the modelCache cache with the result of the getmethod. In this particular case, the customerId is the key used to store the value in the cache. Typically, if you call this method again, your code will not even be called because Spring will find an entry in the cache for that key and will return the value directly.

If the key cannot be created easily or if you need a bit more context, you can define a custom KeyGenerator or specify the pattern to use as a SPeL expression in the annotation directly.

Enabling caching support

You can easily turn on the caching support either through the XML namespace of the @EnableCaching java configuration. The actual caching is delegated to a cache implementation with support for ehcache, guava, concurrent hash map and JSR-107 compliant caches out-of-the-box. You can configure all the cache-provider specific settings you want at this stage: it won't impact your code and you can even change from one provider to the other without changing your code

Updating the cache

If the data is read-only, that's just about it. If the content of those lists change, you need to handle the eviction so that your get method is called again to recompute/refresh the list (see @CacheEvict) or you can update the content of the cache yourself (see CachePut). You also need to configure your back-end cache so that the content of your cache is consistent on all nodes of your cluster.

The logic that mandates that a particular list has changed can be tricky to implement so you should probably focus on that part early when designing your model.

Upvotes: 4

Related Questions