Topic
  • 2 replies
  • Latest Post - ‏2013-01-25T13:29:51Z by jhanders
SystemAdmin
SystemAdmin
1485 Posts

Pinned topic ObjectMap.getAll() - possible to get data for some keys in the key list?

‏2012-12-26T10:15:41Z |
Hello,

I am writing an application which has data cached in ObjectGrid. I also have a Loader to query data from a backend system, in case of cache miss. I would like to get data from the Grid using a list of key, so I decide to use ObjectMap.getAll(), as I don’t want to have a loop calling get() for each key. I found that the getAll() is a lot faster than get(), and my application is performance concerned.

The situation is, I have key1, key2, key3 cached in ObjectGrid. I call getAll() for list of “key1, key2, key3, key4”. The Loader will be trigged for key4. At the time of request, assume that the backend is temporary down, so there will be a LoaderException for key4.

From my testing, such a situation will result in Exception. I don’t get any data back, even though the key1, key2, key3 are in cached. Is it possible to get data back for key1, key2, key3 and an Exception for key4? Or if there is any alternative way to do please suggest.

P.S. I use WXS6.1 (and will migrate to WXS7.1 next year)

Thanks,
Jirassaya
Updated on 2013-01-25T13:29:51Z at 2013-01-25T13:29:51Z by jhanders
  • Art_Jolin
    Art_Jolin
    26 Posts

    Re: ObjectMap.getAll() - possible to get data for some keys in the key list?

    ‏2013-01-14T17:17:23Z  
    I am assuming here you wrote the Loader yourself and you are not using one of the built-in JPA loaders that come with WXS. Your own loader code, in the "get(...)" method, throws the exception to WXS. Therefore, you can choose to not throw an exception but instead return a special value object when the backend is down. Naturally, ALL your client code must check for this special value object but it does allow you to do what you want to do in a well-designed way. There is no special value built-into WXS for this purpose (like the special KEY_NOT_FOUND value object WXS has). You will need to define one yourself. Since WXS does not enforce strict types in a BackingMap for keys or values (even tho it is nearly always far more sensible and less error-prone to always put one key type and one value type in any given map), you can do the following:

    public class MyValueClass {

    public static final String GRID_DOWN = "GRID IS DOWN";

    private int someInteger;
    private Float someFloat;
    ...
    }

    The real data in your BackingMap (named MyValueClassMap, for example) will be of type MyValueClass, but if you do a getAll(keylist) and the fourth key results in a Loader call while your backend is down, your Loader would not throw an exception but instead return the GRID_DOWN constant for each key in the Loader.get(...) call (because you don't know the order of the cache hit keys vs the cache miss keys). In your example, the return from getAll(keylist) will be:

    {myValueClass1, myValueClass2, myValueClass3, GRID_DOWN}

    When you iterate, you need to test each value in the returned List to see if it is GRID_DOWN before you use the object. This will of course slightly slow down things but hopefully not much in your particular case. Note that you can't do

    if (!value == MyValueClass.GRID_DOWN)...

    because the constant instance of GRID_DOWN is coming from the container JVM and won't have the same memory address as the constant instance of GRID_DOWN in your client JVM. You should do this or similar

    if (!GRID_DOWN.equals(value))...

    or, more efficient still if your value class is not itself a String,

    if (!(value instanceof String)) ...

    "instanceof" in Java is far more efficient in Java 1.6 and later than it was in earlier versions.
  • jhanders
    jhanders
    260 Posts

    Re: ObjectMap.getAll() - possible to get data for some keys in the key list?

    ‏2013-01-25T13:29:51Z  
    • Art_Jolin
    • ‏2013-01-14T17:17:23Z
    I am assuming here you wrote the Loader yourself and you are not using one of the built-in JPA loaders that come with WXS. Your own loader code, in the "get(...)" method, throws the exception to WXS. Therefore, you can choose to not throw an exception but instead return a special value object when the backend is down. Naturally, ALL your client code must check for this special value object but it does allow you to do what you want to do in a well-designed way. There is no special value built-into WXS for this purpose (like the special KEY_NOT_FOUND value object WXS has). You will need to define one yourself. Since WXS does not enforce strict types in a BackingMap for keys or values (even tho it is nearly always far more sensible and less error-prone to always put one key type and one value type in any given map), you can do the following:

    public class MyValueClass {

    public static final String GRID_DOWN = "GRID IS DOWN";

    private int someInteger;
    private Float someFloat;
    ...
    }

    The real data in your BackingMap (named MyValueClassMap, for example) will be of type MyValueClass, but if you do a getAll(keylist) and the fourth key results in a Loader call while your backend is down, your Loader would not throw an exception but instead return the GRID_DOWN constant for each key in the Loader.get(...) call (because you don't know the order of the cache hit keys vs the cache miss keys). In your example, the return from getAll(keylist) will be:

    {myValueClass1, myValueClass2, myValueClass3, GRID_DOWN}

    When you iterate, you need to test each value in the returned List to see if it is GRID_DOWN before you use the object. This will of course slightly slow down things but hopefully not much in your particular case. Note that you can't do

    if (!value == MyValueClass.GRID_DOWN)...

    because the constant instance of GRID_DOWN is coming from the container JVM and won't have the same memory address as the constant instance of GRID_DOWN in your client JVM. You should do this or similar

    if (!GRID_DOWN.equals(value))...

    or, more efficient still if your value class is not itself a String,

    if (!(value instanceof String)) ...

    "instanceof" in Java is far more efficient in Java 1.6 and later than it was in earlier versions.
    I worked with the customer off the forum. I am providing the solution below for the benefit of others.

    In the code example the Loader throws an exception for a negative Integer. As such for those keys an Exception was returned instead of the value that is expected. Instead of an Exception another type could be used to indicate that the entry is not available.

    
    List<Integer> keyList = 
    
    new ArrayList<Integer>(40); 
    
    for (
    
    int i = -20; i < 20; ++i) 
    { keyList.add(Integer.valueOf(i)); 
    }   Map<Integer, Object> getAllValues = agentManager.callMapAgent(
    
    new GetAllAgent(), keyList);   
    
    public 
    
    class GetAllAgent 
    
    implements MapGridAgent 
    {   
    
    private 
    
    static 
    
    final 
    
    long serialVersionUID = 1L;   
    
    public Object process(Session s, ObjectMap map, Object key) 
    { 
    
    try 
    { 
    
    return map.get(key); 
    } 
    
    catch (ObjectGridException e) 
    { 
    
    return e; 
    } 
    }   @SuppressWarnings(
    "rawtypes") 
    
    public Map processAllEntries(Session s, ObjectMap map) 
    { 
    
    return 
    
    null; 
    } 
    }