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