Miscellaneous Components

Home‎ > ‎

CacheStore for your Space

Oracle Coherence has a component called CacheStore that can be used to integrate "any" external data source with the Coherence Grid. Typically this external data source is a relational database, but it can be a Directory Server and in fact other Coherence data grid. CacheStore is also used to implement multi-cluster data replication strategies using Coherence. To demonstrate this very fact I wrote the following implementation to integrate JavaSpace as my external data source for the Coherence Grid.

Challenges:

  • JavaSpace works on a Collection, Coherence NamedCache is a Map
  • Data Access in NamedCache is by Key (Or a Extractor Query), In Java Space its a template Query

So how would I do it?

Create a Coherence Cache Config

<!DOCTYPE cache-config SYSTEM "cache-config.dtd">
<cache-config>
    <caching-scheme-mapping>
        <cache-mapping>
            <cache-name>SpaceCache</cache-name>
            <scheme-name>distributed-scheme</scheme-name>
        </cache-mapping>       
    </caching-scheme-mapping>
    <caching-schemes>
        <distributed-scheme>
            <scheme-name>distributed-scheme</scheme-name>
            <service-name>DistributedCache</service-name>
            <backing-map-scheme>
                <read-write-backing-map-scheme>
                    <scheme-ref>rw-bm</scheme-ref>
                </read-write-backing-map-scheme>
            </backing-map-scheme>
            <autostart>true</autostart>           
        </distributed-scheme>
       
        <read-write-backing-map-scheme>
            <scheme-name>rw-bm</scheme-name>
            <internal-cache-scheme>
                <local-scheme></local-scheme>
            </internal-cache-scheme>
            <cachestore-scheme>
                <class-scheme>
                    <class-name>SpaceCacheStore</class-name>
                </class-scheme>               
            </cachestore-scheme>

        </read-write-backing-map-scheme>       
    </caching-schemes>
</cache-config>

Create a Jini Entry Object:

public class MessageEntry implements Entry {

    public Binary oKey;
    public Binary oValue;
   
    public MessageEntry() {
    }
   
    public MessageEntry (Binary oKey, Binary oValue) {
        this.oKey = oKey;
        this.oValue = oValue;
    }
   
    public String toString () {
        return "oKey: " + ExternalizableHelper.fromBinary(oKey) +
               ": oValue: " + ExternalizableHelper.fromBinary (oValue);
    }
}

Create a Coherence Cache Store:

public class SpaceCacheStore implements CacheStore {

    private boolean isInitialized;
    private JavaSpace space;

    private void init() {
        synchronized (this) {
            System.out.println("Looking up JavaSpace.class");
            Lookup finder = new Lookup(JavaSpace.class);
            System.out.println("Lookup initialized");
            space = (JavaSpace) finder.getService();
            isInitialized = true;
        }
        Base.log("Space has been found");
    }

    private void checkInit() {
        if (!isInitialized) {
            System.out.println("Initializing");
            init();
        }
    }

    public SpaceCacheStore() {
    }

    public void store(Object oKey, Object oValue) {

        checkInit();

        if (!(oKey instanceof Binary)) {
            oKey = ExternalizableHelper.toBinary(oKey);
        }
        if (!(oValue instanceof Binary)) {
            oValue = ExternalizableHelper.toBinary(oValue);
        }

        MessageEntry entry = new MessageEntry ();
        entry.oKey = (Binary)oKey;
        entry.oValue = (Binary)oValue;
       
       try {
            space.write(entry, null, Long.MAX_VALUE);
        } catch (TransactionException e) {
            e.printStackTrace(System.err);
        } catch (RemoteException e) {
            e.printStackTrace(System.err);
        }       
    }

    public Object load(Object oKey) {
        checkInit();
        if (!(oKey instanceof Binary)) {
            oKey = ExternalizableHelper.toBinary(oKey);
        }
        MessageEntry template = new MessageEntry ();
        template.oKey = (Binary)oKey;
        try {
            MessageEntry result =
            (MessageEntry) space.read (template, null, Long.MAX_VALUE);
            return ExternalizableHelper.fromBinary (result.oValue);
        } catch (InterruptedException e) {
            e.printStackTrace(System.err);
        } catch (UnusableEntryException e) {
            e.printStackTrace(System.err);
        } catch (TransactionException e) {
            e.printStackTrace(System.err);
        } catch (RemoteException e) {
            e.printStackTrace(System.err);
        }
        return null;
    }

}

How to Test it?

  • Download the Jini2_1
  • Go to JINI_HOME/installverify and launch the Jini processes (Registry et al)
  • Download the attached project and run a DefaultCacheServer
  • Start a CacheFactory
  • Initialize the cache { cache SpaceCache}
  • put key1 value1 and put key2 value2
  • Run clear command to remove all Cache Entries, so that next time get () will invoke load () on the cache store.
  • get key1 will return value1 and get key2 will return value2, but these values come from the Space

Attachments (1)