Wednesday, March 18, 2009

Oracle Coherence learnings, so far...Part 2

1 . If you want to listen to events like when a new object is inserted in the coherence cache(CC) or when an object is deleted from CC or when an object in CC is updated do it like this folks:
NamedCache cache = CacheFactory.getCache("person");
cache.addMapListener(new MapListener() {

public void entryInserted(MapEvent mapEvent) {
//Code when some new object is inserted into cache
}

public void entryUpdated(MapEvent mapEvent) {
Object key = mapEvent.getKey();
Object oldVal = mapEvent.getOldValue();
Object val = mapEvent.getNewValue();
System.out.println("Old value:"+oldVal+", New value being added:"+val);
}

public void entryDeleted(MapEvent mapEvent) {
//Code when some an object is deleted into cache
}
});


2. Up until now we have just done put and get of data into the cache. I am sure, by now, someone is craving to ask what about concurrency. If we want to control concurrency to the data we have the option to lock and unlock keys. But there is a better way to do this: Entry Processes are agents that perform processing against entries, and will carry this out directly where the data is being held. The sort of processing you can carry out may change the data, e.g. create, update or remove or may just perform calculations on the data. Entry processors that work against the same key will be logically queued. This means that you can achieve lock-free (high performance) processing. This is called in-line processing of data. Custom entry processes may be written in the following way:
Class RaiseSalary extents AbstractProcessor {
...
public Object process (Entry entry) {
Employee emp = (Employee)entry.getValue();
emp.setSalary(emp.getSalary() * 1.10);
entry.setValue(emp);
return null;
}

To invoke this you then do the following:
empCache.invokeAll(AlwaysFilter.INSTANCE, new RaiseSalary());

3. Up until now, we've seen simple keys. What if when we want to have a composite key like the id and the version number. Then it is a good idea to wrap all the member elements that form a composite key into an inner class and call it "public static class Key implements ExternalizableLite". A sample key implementation may look like this:
public static class Key implements ExternalizableLite {

// lets define a key of id and version
private int id;
private int version;

public Key() {
//for serializble
}

public Key(int id, int version) {
this.id = id;
this.version = version;
}

public Key(Person p) {
this.id = p.getId();
this.version = 1; // default to version 1
}

public void writeExternal(DataOutput dataOutput) throws IOException {
ExternalizableHelper.writeInt(dataOutput, this.id);
ExternalizableHelper.writeInt(dataOutput, this.version);
}

public void readExternal(DataInput dataInput) throws IOException {
this.id = ExternalizableHelper.readInt(dataInput);
this.version = ExternalizableHelper.readInt(dataInput);
}

@Override
public boolean equals(Object object) {
...
}

@Override
public int hashCode() {
final int PRIME = 37;
int result = 1;
return result;
}
}

As a next step, we can target for efficiencies of partitioning. That is, in the cluster of caches, we can target for similar objects to be in the same cache instance. For this the inner class can implement KeyAssociation and override the method getAssociatedKey(). With this, for instance, if this method returns the same surname then those persons are placed in the same cache instance.

No comments: