com.j_spaces.javax.cache
Interface CacheLoader

All Known Subinterfaces:
BasicCacheLoader<K,V>, CacheStore, MapDataSource<K,V>
All Known Implementing Classes:
AbstractCacheLoader, HibernateCacheLoaderImpl, HibernateCacheStoreImpl, HibernateMapDataSource

public interface CacheLoader

The CacheLoader implementation is provided to ensure read-through behavior of the space. 
Whenever an object is not in space, CacheLoader is used to load the object from secondary storage transparently to the user. 

The load(Object key) method is invoked whenever a cache miss occurs during calls to any of the following methods: JavaSpace API: JavaSpace.take(Object entry, Transaction transaction, long timeout) JavaSpace.takeIfExists(Object entry, Transaction transaction, long timeout) JavaSpace.read(Object entry, Transaction transaction, long timeout) JavaSpace.readIfExists(Object entry, Transaction transaction, long timeout)
Map API: IMap.get(Object key) IMap.containsKey(Object key)
The key is IGSEntry object, so you should cast it into IGSEntry to retrieve the original object data. By extending your CacheLoader implementation from AbstractCacheLoader you will be able to convert the IGSEntry to your original object using: AbstractCashLoader.getConvertor().toObject(IGSEntry entry) - this will return your original Entry Object (the template when using the JavaSpace API) AbstractCashLoader.getConvertor().toIGSEntry(Object obj) - This will transfer your original Object to IGSEntry. This is required for the CacheLoader.load() return value method.
JavaSpace API: Object myObject = getConvertor().toObject((IGSEntry) key);
Map API: IGSEntry.MapEntry mEntry = ((IGSEntry) key).getMapEntry(); keyValue = ((Integer) mEntry.getKey()).intValue();

The loadAll(Collection keys) method is called whenever one or more cache misses occur during calls to any of the following methods: Map API: IMap.getAll(Collection keys) IMap.keySet() IMap.values() JavaSpace API: JavaSpace.read(Object entry, Transaction transaction, long timeout) IMap.readMultiple(Entry template, Transaction txn, int maxEntries) IMap.readMultiple(Object template, Transaction txn, int maxEntries) IMap.takeMultiple(Entry template, Transaction txn, int maxEntries) IMap.takeMultiple(Object template, Transaction txn, int maxEntries) In some cases getAll and readMultiple are not delegated to loadAll() but to the load(). This limitation will be resolved in future versions. Note: The loadAll is not called when the CacheIteratorFactory is implemented! Instead the CacheIteratorFactory.iterator( CacheQuery query ) is called allowing you to load data into the cache via iterator.
When the space is started the loadAll/CacheIteratorFactory.iterator() is called with IGSEntry that its class name is java.lang.Object. This allows you to load your data into the space before is it available for clients.
Configuration CacheLoader is configured in space schema XML configuration file as a persistent adapter.

The space schema should include the following:

<space-config> <persistent> <enabled>true</enabled> <!-- name of the storage adapter class to be used by the space --> <StorageAdapterClass>com.j_spaces.sadapter.cache.CacheAdapter</StorageAdapterClass> <!-- CacheLoader or CacheStore implementation class name that will be used by space --> <CacheLoaderClass>com.j_spaces.examples.jdbccachestore.spaceapi.CacheLoaderImpl</CacheLoaderClass> <DataBaseName>jdbc:hsqldb:testDB</DataBaseName> <userName>sa</userName> <password></password> </persistent> <engine> <cache_policy>0</cache_policy> </engine> </space-config>


You may also use the following space properties: space-config.persistent.enabled=true space-config.persistent.StorageAdapterClass=com.j_spaces.sadapter.cache.CacheAdapter space-config.persistent.CacheLoaderClass=com.j_spaces.examples.jdbccachestore.spaceapi.CacheLoaderImpl space-config.persistent.DataBaseName=jdbc:hsqldb:hsql://localhost:9003 space-config.persistent.userName=sa space-config.persistent.password= space-config.engine.cache_policy=0
You must use space-config.engine.cache_policy=0 (LRU policy) to activate the CacheStore and CacheLoader implementation.
It is recommended to configure also the following to control the space memory usage and the eviction behavior: space-config.engine.memory_usage.enabled=true space-config.engine.memory_usage.high_watermark_percentage=95 space-config.engine.memory_usage.write_only_block_percentage=85 space-config.engine.memory_usage.write_only_check_percentage=76 space-config.engine.memory_usage.low_watermark_percentage=75 space-config.engine.memory_usage.eviction_batch_size=500
The space-config.persistent.DataBaseName , space-config.persistent.userName and space-config.persistent.password will be passed into the CacheLifeCycleManager constructor to be used by the CacheStore implementation. Note that only one, CacheLoader or CacheStore, but not both, is allowed to be used since CacheStore extends CacheLoader interface.


Method Summary
 Object load(Object key)
          Loads value from secondary data storage in case if it's not in space cache.
 Map loadAll(Collection keys)
          Loads multiple values from secondary data storage in case they are not in cache.
 

Method Detail

load

Object load(Object key)
Loads value from secondary data storage in case if it's not in space cache.

Parameters:
key - Key (an IGSEntry) of the object to load.
Returns:
Object returned by load; can be null
Space API Implementation Example:

        public Object load(Object key) {

                Object values[] = null;
                Object loaded_object = null;

                try {
                        Object myObject = getObject((IGSEntry) key);
                        int keyValue = 0;
                        if (myObject instanceof Person) {
                                Person person = null;
                                // This is the template we got - must have ID
                                person = (Person) myObject;
                                // getting primary key value - another option could be via
                                // ((IGSEntry) key).getPrimaryKeyName()
                                keyValue = person.getId().intValue();
                                // Constructing the query
                                Connection con = getConnection();

                                PreparedStatement stP = con.prepareStatement(
                                                "select * from  "
                                                                + tableNames.get(((IGSEntry) key)
                                                                                .getClassName()) + " where ID = ? ");
                                stP.setInt(1, keyValue);

                                ResultSet rs = stP.executeQuery();
                                int sz = rs.getMetaData().getColumnCount();

                                values = new Object[sz];
                                while (rs.next()) {
                                        for (int i = 0; i < sz; i++) {
                                                values[i] = rs.getObject(i + 1);

                                        }
                                        // here we construct the loaded Person object
                                        loaded_object = new Person(String.valueOf(values[0]),
                                                        String.valueOf(values[1]), Integer.valueOf(String
                                                                        .valueOf(values[2])));
                                        break;
                                }
                                rs.close();
                                rs.close();
                                con.close();
                        }
                } catch (Exception e) {
                        e.printStackTrace();
                        throw new RuntimeException(e);
                }
                return getConvertor().toIGSEntry(loaded_object);
        }


Map API Implementation Example:
          
        public Object load(Object key) {

                Object values[] = null;
                Person loaded_person = null;
                Connection con = null;
                try {
                        con = getConnection();
                        int keyValue = 0;
                        Map.Entry mEntry = ((IGSEntry) key).getMapEntry();

                        if (mEntry != null) {
                                keyValue = ((Integer) mEntry.getKey()).intValue();
                        } else {
                                keyValue = ((Integer) getId((IGSEntry) key)).intValue();
                        }

                        PreparedStatement stP = con.prepareStatement("select * from  " + tableNames.get(Person.class.getName())
                                                        + " where ID = ? ");
                        stP.setInt(1, keyValue);

                        ResultSet rs = stP.executeQuery();
                        int sz = rs.getMetaData().getColumnCount();

                        values = new Object[sz];
                        while (rs.next()) {
                                for (int i = 0; i < sz; i++) {
                                        values[i] = rs.getObject(i + 1);
                                }
                                // HERE WE MAP table row to Person object
                                loaded_person = new Person(String.valueOf(values[0]), String
                                                .valueOf(values[1]), Integer.valueOf(String
                                                .valueOf(values[2])));
                                break;
                        }
                        rs.close();
                        con.close();

                } catch (Exception e) {
                        try {
                                con.close();
                        } catch (SQLException e1) {
                                e1.printStackTrace();
                        }
                        e.printStackTrace();
                }
                return getConvertor().toIGSEntry(loaded_person);
        }

                

loadAll

Map loadAll(Collection keys)
Loads multiple values from secondary data storage in case they are not in cache.

Parameters:
keys - Collection of (CacheQuery) Keys to load by.
Returns:
Map of key-value pairs loaded from data storage.
Space API Implementation Example

        public Map loadAll(Collection keys) {
                HashMap map = new HashMap();
                Iterator keyIter = keys.iterator();
                while (keyIter.hasNext()) {
                        CacheQuery exprationEntry = (CacheQuery) keyIter.next();
                        Object query = exprationEntry.getQuery();
                        String querystr = null;
                        // null template
                        if (query instanceof IGSEntry) {
                                IGSEntry igsentry = (IGSEntry) query;
                                if (!tableNames.containsKey(igsentry.getClassName())) {
                                        System.out.println("Do not have mapping for class "
                                                        + igsentry.getClassName());

                                        if (igsentry.getClassName().equals("java.lang.Object")) {
                                                System.out.println("HERE YOU CAN LOAD DATA INTO THE SPACE WHEN IT IS STARTED!");
                                        }
                                        // return empty map - indicates no objects loaded from database
                                        return map;
                                }
                                querystr = "select * from "
                                                + tableNames.get(igsentry.getClassName());
                        }
                        // non null template or SQLQuery used
                        if (query instanceof SQLQuery) {
                                SQLQuery sqlquery = (SQLQuery) query;
                                if (!tableNames.containsKey(sqlquery.getClassName())) {
                                        System.out.println("Do not have mapping for class "
                                                        + sqlquery.getClassName());
                                        // return empty map - indicates no objects loaded from database
                                        return map;
                                }
                                querystr = "select * from "
                                                + tableNames.get(sqlquery.getClassName());
                                querystr += " where " + sqlquery.getQuery();
                        }
                        try {
                                Connection con = getConnection();
                                PreparedStatement stP = con.prepareStatement(
                                                querystr);

                                ResultSet rs = stP.executeQuery();
                                IGSEntry value = null;
                                while (rs.next()) {
                                        Integer id = new Integer(rs.getInt(3));
                                        Person person = new Person(rs.getString(1),
                                                        rs.getString(2), id);

                                        value = getConvertor().toIGSEntry(person);
                                        map.put(value, value);
                                }
                                rs.close();
                                con.close();
                        } catch (Exception e) {
                                e.printStackTrace();
                                throw new RuntimeException(e);
                        }
                }

                return map;
        }


Map API Implementation Example

        public Map loadAll(Collection keys) {
                HashMap map = new HashMap();

                Iterator keyIter = keys.iterator();
                while (keyIter.hasNext()) {
                        CacheQuery cacheQuery = (CacheQuery) keyIter.next();
                        Object query = cacheQuery.getQuery();
                        String sqlstr = null;
                        sqlstr = "select * from Person";
                        Map.Entry mapentry = null;
                        if (query instanceof Map.Entry)
                        {
                                mapentry  = (Map.Entry)query;
                                sqlstr += " where id = " + Integer.valueOf(mapentry.getKey().toString()).intValue();
                        }
                        else if (query instanceof IGSEntry)
                        {
                                // All entries - for example IMap.values() call 
                                IGSEntry igsentry = (IGSEntry)query;
                                if (igsentry.getClassName().equals("java.lang.Object"))
                                {
                                        return map;
                                }
                        }
                        else if (query instanceof SQLQuery)
                        {
                                SQLQuery sqlquery = (SQLQuery)query;
                                if (sqlquery.getClassName().equals("java.lang.Object"))
                                {
                                        return map;
                                }
                                sqlstr += " where " + sqlquery.getQuery();
                        }
                        PreparedStatement stP =null; 
                        ResultSet rs = null;
                        Connection con = null;
                        try {
                                con = getConnection();
                                stP = con.prepareStatement(sqlstr);
                                rs = stP.executeQuery();
                                while (rs.next()) {
                                        Integer id = new Integer(rs.getInt(3));
                                        Person person = new Person(rs.getString(1),
                                                        rs.getString(2), id);
                                        IGSEntry  igsEntry = getConvertor().toIGSEntry(person);
                                        map.put( igsEntry ,  igsEntry );
                                }
                                rs.close();
                                con.close();
                        } catch (Exception e) {
                                try {
                                        rs.close();
                                } catch (SQLException e1) {
                                        e1.printStackTrace();
                                }
                                try {
                                        con.close();
                                } catch (SQLException e1) {
                                        e1.printStackTrace();
                                }
                                e.printStackTrace();
                                throw new RuntimeException(e);
                        }
                }
                return map;
        }