Version 19

    Shotoku Cache

    The standard cache is quite simple: through static methods of the ShotokuCache class, you can place an object in the cache, binding it to a key, retrieve it or delete it. What is important in application server mode, is that this cache is global (so one web application can access data placed in the cache by another web application).

     

    Be sure to check out the javadoc for org.jboss.shotoku.cache.

     

    Shotoku Cache Items

    However, apart from standard cache functions, you can do more. The general use case is that the objects placed in the cache should be updated regularly. To achieve this, first extend the ShotokuCacheItem class.

     

    Then, you must implement the T init(K key) method and void update(K key, T currentValue) method. The first one will be called whenever a key is accessed for a first time - using the T get(K key) method, and it should return the initial value that should be placed in the cache. The update method will be called on specified intervals of time - as specified in shotoku.properties, property shotoku.service.interval. If you decide that the value in the cache should be updated, you just need to call, from the update method, the void put(K key, T newValue) method.

     

    You can access items with the shotokuCacheItem.get(K key) method. Note: when accessing objects that are "handled" by a ShotokuCacheItem implementation, do not use ShotokuCache.get(key), as it will not work. Of course, you must create it first;

     

    If you are using Shotoku in application server mode, and have annotations enabled, using a ShotokuCacheItem is even simpler: just write: @CacheItem MyShotokuCacheItem msci; in the field declaration. You can then access it in the same manner as before (no initialization is required).

     

    You can also easily bind with each key a unique ContentManager instance. To do this, first implement the ShotokuCacheItem.initContentManager(K key) method, which will be called to get a ContentManager when the ShotokuCacheItem.getContentManager(K key) method is called for the first time. Later, just call ShotokuCacheItem.getContentManager(K key) to get the created instance (no more instances will be created).

     

    If you want to specify at what the intervals the update should be fired, use the constructor with the long interval parameter (the interval should be given in milliseconds). The effective interval will be the given one, rounded to be the smallest multiplicity of the Shotoku cache interval, as set in shotoku.properties.

     

    Shotoku Resource Watchers

    Updating objects every shotoku.cache.interval miliseconds can be undesirable. A second option that Shotoku gives you is to have the update method called only when ceratain resources change - are deleted, added or modified in the repository. To do this, extend the ShotokuResourceWatcher class. The methods that you have to implement are quite similar as before.

     

    There is also a second class, ShotokuResourceWatcherSplitDescriptor, which is a slight modification to ShotokuResourceWatcher: the update method has three sets as parameters (modified, deleted, added resources), instead of a map which tells what change happened to which resource.

     

    You should also probably implement the initContentManager(key) method, as monitored resources for each key will be read (and checked) from the content manager that this method returns.

     

    The T init(K key) stays the same, as well as its meaning. The void update(K key, T currentObject, Map<String, ChangeType> changes) method gains one parameter - changes, and is called only when some of the watched resources change. This is a map from watched (monitored) paths, to the change, that occured on that type (it can be ChangeType.ADDED/DELETED/MODIFIED. Of course, the changes map cannot be empty, because if it were, the update method wouldn't be called.

     

    To watch resources, you have three methods:

    • addWatchedPath(String key, String path)

    • deleteWatchedPath(String key, String path)

    • resetWatchedPaths(String key) - removes all watched paths.

    You can call them from the init or update methods (from other methods of course too ).

     

    The usage of resource watchers is the same as that of cache items. You can also use the @CacheItem annotation, or a variant: @CacheItem(interval=123) when you want the update to be fired at specified intervals

     

    Note:

    If you are using the @CacheItem annotation, be sure that:

    • the class representing the item is either public ("stand-alone"), or if it is inside another classe, it must be static public (for reflection to work)

    • the class must have a () constructor, or a (long) constructor, when using the interval parameter.

     

    For multi-valued keys, there are org.jboss.shotoku.tools.Pair and org.jboss.shotoku.tools.Triple helper classes, for easily storing tuples of objects.

     

    A small example

    public class ResWatcherTest {
       public static class MyResWatcher extends ShotokuResourceWatcher<String, String> {
          public String init(String key) {
             addWatchedPath(key, "/some/path");
             return "notChanged";
          }
    
          protected void update(String key, String currentObject, Map<String, ChangeType> chagnes) {
             put(key, "changed");
          }
    
          protected ContentManager initContentManager(String key) {
             return ContentManager.getContentManager("prefix", "svn-cm");
          }
       }
    
       @ResourceWatcher
       MyResWatcher myResWatcher;
    
       public String get() {
          return myResWatcher.get("a key");
       }
    }
    

     

    First call to the get() method will always return "notChanged". Only after the resource corresponding to the path "/some/path" will get changed, the method will start returning "changed".