Showing posts with label Cache. Show all posts
Showing posts with label Cache. Show all posts

Simple Coherence observer

Once you have put some elements in a Oracle Coherence named cache, you are often interested in checking out if someone else is doing anything in there, inserting, updating, or even deleting from it.

What you could want is observing what happens to your cache, probably something like using the observer pattern.

Doing that with Coherence is pretty easy, we need to define a class extending AbstractMapListener, to specify what we want actually do in case of insertion, editing or deletion on the cache; than we call addMapListener() on our cache passing an instance of such class, and basically we are done.

A very simple example of a map listener could be:
public class MyCacheListener extends AbstractMapListener {
    @Override
    public void entryInserted(MapEvent event) {
        System.out.println("*** Inserted: " + event);
    }

    @Override
    public void entryUpdated(MapEvent event) {
        System.out.println("*** Updated: " + event);
    }

    @Override
    public void entryDeleted(MapEvent event) {
        System.out.println("*** Deleted: " + event);
    }
}
It is not a fancy implementation, it just dumps to standard output the event signaling the item affected in the cache, but starting from this we can create a more useful functionality.

The class that works with the cache would probably implement a method like this:
public void observe() {
    cache.addMapListener(new MyCacheListener());
}
And this is a piece of code that would start observing on a Coherence cache:
CacheObserver cohCli = new CacheObserver(); // 1
cohCli.observe();

cohCli.checkPut("key", "value"); // 2
cohCli.getCheck("key", "value");
cohCli.checkPut("key", "change");
cohCli.checkRemove("key");

// ...
1. In my test code, CacheObserver extends the SimpleCache class seen in the previous post adding the observe() method seen here above.
2. Any time a change is done in the cache, the observer would dump the event generated to the screen.

Go to the full post

Basic Coherence functionality

Once you have setup Oracle Coherence in your development environment, and you have tested a simple Hello World application, you are ready to write something moderately more interesting.

In the following example I am using just a pair of Coherence classes. They still have in their package name a "Tangosol" reference, from the company that now, like many other ones, is part of Oracle:
import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;

public class SimpleCache {
    protected NamedCache cache;
    protected static final String CACHE_NAME = "MyCache";

    public SimpleCache() { // 1
        CacheFactory.ensureCluster();
        cache = CacheFactory.getCache(CACHE_NAME);
    }

    public void dtor() { // 2
        CacheFactory.shutdown();
    }

    public void checkRemove(String key) {  // 3
        System.out.println("+++ removing " + key);
        if(cache.containsKey(key)) {
            cache.remove(key);
        }
        else {
            System.out.println("+++ " + key + " is not in cache");
        }
    }

    public void checkPut(String key, String value) { // 4
        System.out.println("+++ putting " + key);
        if(cache.containsKey(key)) {
            System.out.println("+++ " + key + " already in cache");
        }
        cache.put(key, value);
    }

    public void getCheck(String key, String expValue) { // 5
        System.out.println("+++ getting " + key);
        String output = (String)cache.get(key);
        if(output == null)
            System.out.println("+++ " + key + " is not in the cache");
        else if(output.compareTo(expValue) != 0)
            System.out.println("+++ Unexpected: " + expValue + " != " + output);
    }

    public void full(String key, String value) { // 6
        checkPut(key, value);
        getCheck(key, value);
        checkRemove(key);
    }

    public static void main(String[] args) {
        SimpleCache cohCli = new SimpleCache();

        if(args.length == 0)
            cohCli.full("key", "value"); // 7
        else {
            if(args[0].matches(".*[Pp].*")) // 8
                cohCli.checkPut("key", "value");
            if(args[0].matches(".*[Gg].*"))
                cohCli.getCheck("key", "value");
            if(args[0].matches(".*[Rr].*"))
                cohCli.checkRemove("key");
        }
        cohCli.dtor();
    }
}
1. In the class constructor we get the cache from the factory.
2. From the name of this method you could correctly guess I am more a C++ that a Java guy. If you wonder, dtor is a common short name for destructor, there is not such a beast in Java, but the name should be thought as an hint to the user programmer - call it when you are done with an instance of this class.
3. Before removing an element in the cache, ensure it actually is in it.
4. If an element with the specified key is already in the cache, issue a warning before storing the new value.
5. Get an element, and check that its value matches the expectation.
6. Utility method, combines (3), (4), and (5) in an unique call.
7. If no parameter is passed to the Java application, a full test is performed, putting, getting, and finally removing a key-value in the cache.
8. The passed parameter is expected to be a string stating what we want to do. A "pgr" is a synonim for a full test; if I want just put I should specify just "p" (or "P") and so on.

Go to the full post

Hello Oracle Coherence

We can run Coherence just as we extract it from its distribution package, relying on its default configuration, but it is usually a smarter idea to provide at least some minimal custom setup for our instance.

We could pass parameters from the command line, or provide XML files with a format and name as expected by coherence.

Here is my tangosol-coherence-override.xml that I used to configure both my coherence server and client applications:
<?xml version='1.0'?>

<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
    xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-
config coherence-operational-config.xsd">
    <cluster-config>
        <member-identity>
            <cluster-name>myc</cluster-name>
        </member-identity>

        <multicast-listener>
            <address>224.3.6.0</address>
            <port>9485</port>
            <time-to-live>0</time-to-live>
        </multicast-listener>
    </cluster-config>
</coherence>
All the specified fields should be immediate, maybe with the exception of time-to-live, that is the default surviving time for an object in the cache. As you could expect, zero does not mean "immediate death", but quite the opposite.

Using those configuration, we could finally start writing some Java code. You see that the resulting code is very clean and easy. From the programmer point of you, the cache is nothing more than a Map:
// ...
import com.tangosol.net.*;

// ...

    // setup
    CacheFactory.ensureCluster();
    NamedCache cache = CacheFactory.getCache("hello-example"); // 1

    // input
    String key = "k1";
    String input = "Hello World!";

    // put an item in the cache
    cache.put(key, input); // 2

    // get an item from the cache 
    String output = (String)cache.get(key); // 3
    if(output.compareTo(input) == 0)
        System.out.println("OK");

    // removing an item from the cache
    cache.remove(key);

    // terminate
    CacheFactory.shutdown();
    
// ...
1. There could be many different caches in out Coherence instance, we get the cache that the client want through a dedicated factory.
2. Just like a standard Map, we simply put key and value, and let Coherence to take care of the details. With a variant, we can pass a third parameter, the time to live in the cache for this element, in milliseconds.
3. As the standard Map, we should downcast to the actual type - beware of exceptions! And, if the key is not found, the result would be a null. I didn't check nor for unexpected type nor for null, real code should be more careful.

Go to the full post

Oracle Coherence setup

The current version of Oracle (previously Tangosol) Coherence, 3.7.1, is available for Java, .NET, and C++.

Starting up using the Java version is pretty easy. Go to the official Oracle Coherence download page, get the distribution file, unzip it on your file system and you are ready to start using it.

Server

Assuming you have a JVM 1.6.23 or newer, to run the Coherence server, you open a window shell, go to bin directory in coherence, and run the cache-server.cmd (for Windows) or cache-server.sh (for UNIX) script. The server, with a default configuration gets up.

I am currently running it on Windows, and it works fine. I tested it also on a UNIX box, and I had to slightly modify the script - I think I remember the issue was I had to use a bash shell (first line: #!/bin/bash)

Client

Once the server is up, you open another shell, go to the same coherence/bin directory, and you run coherence.cmd (or .sh for UNIX).

If you see that both server and client go up, you can proudly say you have Coherence working on your machine. Next step will be to create a simple hello application.

I guess you know it, but just in case, you can download also the official Oracle Coherence documentation.

Go to the full post