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

Google App Engine Setup

You can develop a web application for Google App Engine in Java, Python, and Go. I did it in Java, and here is a report of what I have done, from nothing till having a very simple web app running on appspot.com.

If you don't have any strong argument against Eclipse, it should a good idea to pick that IDE to develop for App Engine, and the reason is that Google makes available a plugin that would simplify a bit your job.

Currently are available plugins for Eclipse Europa, Ganymede, Galileo, Helios, and Indigo. You can install it directly from Eclipse, by the Software Update feature. If this does not work, firewall issues are a common reason for that, you can download the zipped plugin, and install it in Eclipse as a "New software".

Once the plugin is installed, we can run a testing version of the Google App Server locally. From the shell we go in a bit obscure directory, under eclipse\plugins, should be named something like:
com.google.appengine.eclipse.sdkbundle_1.6.1.v201112160242r37\appengine-java-sdk-1.6.1\
From there we can run the Application Server, in developing mode, passing to it as parameter the directory where it could find a .WAR file created for the Google App Engine.

For instance, to run the demo application Guestbook, we call:
> bin\dev_appserver.cmd demos\guestbook\war
You could have some error (again, a firewall issue could be the culprit), but if in the end you get the confirmation on the server going up and running on http://localhost:8080/, and:
The admin console is running at http://localhost:8080/_ah/admin
You are ready to open your favorite browser on localhost and see the test web application running locally.

Pay attention to the port number. If you run the server "by hand", as we have just seen, it is 8080, but when you run it from Eclipse the 8888 port number is used.

Go to the full post

SoftReference vs. WeakReference

At first sight SoftReference doesn't look much different from WeakReference. Actually, if you compare the example you can see here below, and the one I wrote for SoftReference, they will look almost identical.

What changes is all in the expected surviving time for an object that is not associated anymore to any strong reference. If it has at least one soft reference it should survive longer than if it had only weak references. We could say that the Java garbage collector turns a more gentle eye to soft references while it is stricter against weak references.

What it the point using soft references? Caching, maybe.

I loaded an object in memory, it has completed its job, and now it could be discarded. Still there is a chance someone will ask again for it soon, and loading it again is a bit expensive. We don't have a strong opinion on how long it should stay alive, and when it will be more worthy to get rid of it. We don't know how to take such a decision, so we let JVM deciding for us.
String strong = new String("A string");
SoftReference<String> soft = new SoftReference<String>(strong);

System.out.println("Setup: " + strong);
strong = null;

int[][] ia = new int[10][];
for(int i = 0; i < 10; ++i) {
    if(sa.get() == null) {
        System.out.println("Removed");
        return;
    }
    System.out.println(i + "] looping on " + sa.get());
    ia[i] = new int[150000];
}
System.out.println("Not removed!?");
If you run this code, and compare it with the same stuff but using WeakReference instead, you should find out a similar behavior, but a different number of loops performed before the garbage collector takes the decision to kill the object.

Go to the full post

WeakReference and WeakHashMap

As consequence of having a garbage collector that decides if and when an object is destroyed, there is no destructor in Java. Sometime this is a nuisance.

Think to this example. We need to keep references to some objects currently available in an application and associate to each of them some specific information. A map looks a natural container, but there is a problem: when we should remove a record from it?

When the object is not used anymore, one would say. But we are using Java, no destructor available.

We need a more creative solution, as for instance weak references. In this specific case we have even a better solution, WeakHashMap, a HashMap variation, seems exactly what we are looking for.

An example should make clear what a Java weak reference is, and how to use it:
String strong = new String("Weak"); // 1
WeakReference<String> wa = new WeakReference<String>(strong); // 2

System.out.println("Setup: " + strong);
strong = null; // 3

int[][] ia = new int[10][]; // 4
for(int i = 0; i < 10; ++i) {
    if(wa.get() == null) { // 5
        System.out.println("Removed");
        return;
    }
    System.out.println(i + "] looping on " + wa.get()); // 6
    ia[i] = new int[150000]; // 7
}
System.out.println("Not removed!?"); // 8
1. A "normal" reference to an object, is what in this context is usually called a "strong" reference. The garbage collector won't consider for destruction an object till it has at least one strong reference.
2. In this way we create a weak reference. It is not strong enough to save it from destruction by gc, but still provide a way to access the underlying object.
3. Setting a strong reference to null, we remove the connection between it and its original target. Now there is just a weak reference to our String object. Its life is in a serious danger, the garbage collector could decide to destroy it whenever it thinks it is the right moment.
4. The programmer can force the garbage collector the do its job, but I felt it was more interesting allocating some memory and let the JVM decide when to start to collect the garbage.
5. The WeakReference.get() method returns null when the referenced object has been deleted by gc.
6. Theoretically, gc could be called after (5) and before (6), so we could get and print "null" from our WeakReference. But do not expect to see this behavior.
7. The application claims for more memory, increasing the chance that the garbage collector would be called.
8. If you reach this line, the garbage collector has not be called when running the above for loop. Try to increase the quantity of memory claimed on (7).

Instead of using explicitly WeakReference, we could modify the above code and use WeakHashMap:
String key = new String("Key"); // 1
String val = new String("Weak hash map"); // 2

WeakHashMap<String, String> whm = new WeakHashMap<String, String>(); // 3
whm.put(key, val);

System.out.println("Setup: " + whm.get("Key"));
key = null; // 4

int[][] ia = new int[10][];
for(int i = 0; i < 10; ++i) {
    String stillThere = whm.get("Key"); // 5
    if(stillThere == null) {
        System.out.println("Removed");
        return;
    }
    System.out.println(i + "] looping on " + whm.get("Key"));
    ia[i] = new int[150000];
}
System.out.println("Not removed!?");
1. In a real case we usually have some more complex object instead a simple String, but for an example it would suffice.
2. Extra information related to the original object.
3. Our weak map where we store the original object as a key and the extra info as value.
4. The key variable does not refer anymore to the original String object. If we used an HashMap, we would still have there a strong reference to it, but we are using WeakHashMap that keeps just a weak reference to its keys.
5. If we used an HashMap, there wouldn't be much sense of looping in this way on get(), it would always return the same value. But here we are using a WeakHashMap, and this means that when the garbage collector is called, all the weak references to the removed object are marked as invalid (null).

Go to the full post

Logback filters

Filtering could be a complicated matter, the official Logback documentation would give you a detailed introduction to the subject, but I guess it can be useful having a more limited view on a few basic features.

We can specify the lower level accepted to log in a logger element (including the root element) setting its level attribute. For instance, if we want to log everything from trace up we specify "trace" as level for the root element:
<root level="trace">
A threshold filter could be used to skip from logging any message with a severity higher than the specified level. In this example a console appender is filtered to show only up to info messages:
<appender name="CApp" class="ch.qos.logback.core.ConsoleAppender">
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
        <level>info</level>
    </filter>
    ...
We can filter so that only messages with a specified severity are logged. This filter accepts only warning messages and discard all the others:
<filter class="ch.qos.logback.classic.filter.LevelFilter">
    <level>WARN</level>
    <onMatch>ACCEPT</onMatch>
    <onMismatch>DENY</onMismatch>
</filter>
For more complex filtering we can create a custom filter and refer to it in our configuration file.

If we want to log only INFO, but just the ones among them containing the "hello" text in it, we could define a MyFilter class like this:
package test;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;

public class MyFilter extends Filter<ILoggingEvent> {
    @Override
    public FilterReply decide(ILoggingEvent event) {
        if(event.getLevel() != Level.INFO)
            return FilterReply.DENY;

        if (event.getMessage().contains("hello"))
            return FilterReply.NEUTRAL;
        return FilterReply.DENY;
    }
}
In our configuration file we refer to it:
<filter class="test.MyFilter">
This approach keeps the XML configuration file simple, delegating the filtering logic to a custom Java class. On the other side, the configuration file gets a bit more obscure - at first sight it is not clear what the filtering is actually doing.

When the filtering rule is very simple, it won't probably make much sense using this approach, maybe a couple of filters in the XML configuration would be a better solution.

Go to the full post

Loggers and appenders

After performing some basic Logback configuration, we can see how to set appenders and loggers, so that Logback could send its output both to console and a file, specifying a different behavior in different classes.

We have already know how to use an appender to send output to the console, now we see how to create a file appender, and also how to create a configuration logger, to describe a relation between a SLF4J logger, as defined and used in our code, and an appender.

Here is an XML Logback configuration file:
<configuration debug="true">
  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
  <appender name="CApp" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}: %msg%n</pattern>
    </encoder>
  </appender>
  <appender name="FApp" class="ch.qos.logback.core.FileAppender">
    <file>TestLogback.log</file>
    <encoder>
      <pattern>%date %level [%thread] %logger{10} [%file:%line]: %msg%n</pattern>
    </encoder>
  </appender>
  <logger name="test.TestLogback" level="info">
    <appender-ref ref="FApp" />
  </logger>
  <root level="trace">
    <appender-ref ref="CApp" />
  </root>
</configuration>
You see that this configuration file is set to be in debug mode, and it has a status listener element set to output its feedback to the standard console. More on Logback configuration debug in the previous post.
Same for the CApp appender, console appender already seen in the previous post.
The FApp appender is a FileAppender. We specify its name and the format internally used.
The logger element works like a root element, the biggest difference is due that root does not need a name, while a logger has to provide it, to be used by the SLF4J logger factory to retrieve the settings.
We can specify the additivity attribute in the logger, defaulted to true, if not explicitly set to false, it means that this logger uses the appenders specified by its ancestors (if any) and adds the one(s) specified in this element's belly. False means that all the existing appenders are discarded and only the one specified there are used.
The logger level is explicitly set to "info", this logger and all the ones on hierarchy below are affected by this.

We can get the same result by a groovy configuration file:
import static ch.qos.logback.classic.Level.DEBUG
import static ch.qos.logback.classic.Level.INFO
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
import ch.qos.logback.core.status.OnConsoleStatusListener
import ch.qos.logback.core.ConsoleAppender
import ch.qos.logback.core.FileAppender

statusListener(OnConsoleStatusListener)

appender("CApp", ConsoleAppender) {
  encoder(PatternLayoutEncoder) {
    pattern = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}: %msg%n"
  }
}

appender("FApp", FileAppender) {
  file = "TestLogback.log";
  encoder(PatternLayoutEncoder) {
    pattern = "%date %level [%thread] %logger{10} [%file:%line]: %msg%n"
  }
}

logger("test.TestLogback", INFO, ["FApp"])
root(DEBUG, ["CApp"])
The lack of semicolons at the end of lines is a perlish Groovy variation on Java syntax.

Go to the full post