Skip to content
Joan Zapata edited this page May 17, 2015 · 14 revisions

There's a lot to say about caching, many existing patterns which might fit your situation or not. That's why AsyncService doesn't do anything by default, and provides you with some methods to implement your own caching strategy, as you've seen before: cache(key, value) and getCached(key).

For common patterns, Kiss provides annotation to make things easier.

Pattern 1: Cache-Then-Call

This pattern is actually the one that pushed me to write this lib. I described it in an article right before I started working on AsyncService. The need here is to display something to the user as soon as possible.

Let's say we want to retrieve the user contacts.

@AsyncService
public class DemoService {
   public Contacts getContacts(){
      return // …network operation
   }
}

Network operations can be very slow. Let's not waste the user's time! For that, we'll display cache data as soon as possible, then update it with real data when it comes in.

Reminder: As you learned with Rule #1, by default in a AsyncService, all methods run one after the other. This "flow" is referred to as a "serial". So, all methods run by default with the same serial. To make sure the cache is retrieved as fast as possible, we'll create a new serial to run all cache-related methods.

Cache Then Call principle

Here's the code.

// 1: The user call getContacts()
@Serial("CACHE") public void getContacts() {

    // 2: Check the cache, and send it if not empty
    Contacts cache = getCached("CONTACTS", Contacts.class);
    if (cache != null) send(cache);

    // 3: Make the actual network call
    getContactsAsync();
}

// Implicit serial "DEFAULT"
protected Contacts getContactsAsync() {
    // 3bis: Make the network call
    Contacts contacts = // …network operation

    // 4: Update the cache
    cache("CONTACTS", contacts);

    // 5: Send the result back to the caller
    return contacts;
}

That's way too much!

AsyncService has a dedicated annotation for it, so all of this become a one-liner.

@CacheThenCall
public Contacts getContacts(){
   return // …network operation
}

You're free to use the key you want for the cache. You can include parameter values using brackets.

@CacheThenCall(key="CONTACTS:{group}")
public Contacts getContacts(int group){
   return // …network operation
}

By default, the generated cache key includes the class name, method name, and parameter values. For example, if your method is getUser(String username), the default cache key could be for example "DemoService.getUser(joan)".

Next step: [handle exceptions](Handle Exceptions)

Learn

  1. Learn the basics.
  2. How to [enhance your service](Enhance Service).
  3. Take advantage of [caching](Caching Patterns).
  4. How to [handle exceptions](Handle Exceptions).
  5. Want more? See what's [behind the scenes](Behind The Scenes).
Clone this wiki locally