Monday, December 22, 2008

On Iterator composition in Java

In my last blog post I mentioned that I would like to see library support for manipulating iterators included in the JDK. I for one, and I know that more people than me, have a set of iterator manipulation classes that I bring along from project to project, usually by copy/paste. This post is an elaboration on what the things are that I think should be included in the JDK, all communicated through code (The actual implementation is not as interesting as the API, and thus left as an exercise for the reader):

package java.util;

import java.util.iter.*;

public final class Iterators {
public <E> Iterable<E> empty() { ... }
public <S,T> Iterable<T> convert(Iterable<S> iterable, Converter<S,T> converter) { ... }
public <T> Iterable<T> upCast(Iterable<? extends T> iterable) { ... }
public <T> Iterable<T> downCast(Class<T> target, Iterable<?> iterable) { ... }
public <T> Iterable<T> append(Iterable<T>... iterables) { ... }
}

// These classes should preferably be reused from somewhere.
package java.util.iter;

public interface Converter<S,T> {
T convert(S source);
}

public interface Filter<E> {
boolean accept(E element);
}

And some sample uses:

package org.thobe.example;

import java.util.Iterators;
import java.util.iter.*;

class UsesIteratorComposition {
private class Something {}
private class Source extends Something {}
private class Target { Target(Source s) {} }

Iterable<Source> source = Iterators.empty();

void conversions() {
Iterable<Target> target = Iterators.convert(source, new Converter<Source,Target>() {
Target convert(Source source) {
return new Target(source);
}
});
}

void casts() {
Iterable<Something> something = Iterators.upCast(source);
Iterable<Source> back = Iterators.downCast(Source.class, something);
}

void append() {
Iterable<Source> source = Iterators.append(source, new ArrayList<Source>(){
{
add(new Source());
add(new Source());
}
});
}
}

Wednesday, December 17, 2008

On Double Checked Locking in Java

You have probably all heard/seen the “Double-Checked Locking is Broken” declaration. And if you haven't I'll just tell you that before the improved memory model of Java 5, double checked locking didn't work as expected. Even in Java 5 and later there are things you need to consider to get it to work properly, and even more things to consider if you want it to perform well.

Joshua Bloch suggests in his book Effective Java, and keeps repeating in several presentations that there is one way to implement double checked locking and that this code snippet should be copied to every place where it's needed. I disagree. Not with the part about there only being one way of doing it, but with the copying part. In my eyes this is perfect use case for an abstract class:

package java.util.concurrent;

public abstract class LazyLoaded<T> {
private volatile T value;
// Get the value, guard the loading by double checked locking
public final T getValue() {
T result = value;
if (result == null) { // First check
synchronized (this) { // Lock
result = value;
if (result == null) { // Second check
result = loadValue();
value = result;
}
}
}
return result;
}
protected abstract T loadValue();
}

This class would then be used like this:

package org.thobe.example;

import java.util.concurrent.LazyLoaded;

class UsesDoubleCheckedLocking {
// The generics even makes it read well:
private final LazyLoaded<Something>() {
@Override protected Something loadValue() {
return new Something();
}
};
// ... your code will probably do something useful here ...
}

Just expressing my opinion. I hope someone important reads this and makes sure that it gets included in Java7. And while you're at it, make sure we get some standardized ways of composing Iterable/Iterators as well...

Friday, December 05, 2008

About types in Neo4j

When I first started using Neo4j I wondered "Why is there a RelationshipType and no NodeType?", and as more people are introduced to Neo4j I find that this is a quite common question. And of course an obvious question in the strongly typed single inheritance world of Java. This post was inspired by a discussion on the Neo4j mailing list.

The answer to the question is to be found in the name RelationshipType, it means no more than than the name implies. In particular it does not mean data type. What you are wishing for when you ask for a node type is a way of specifying what properties a node or relationship has, based on its type. Neo4j does not provied any mechanism for this at the core layer. There is a meta model component available that gives you data types for nodes and relationships with verification and all of that if you would like it, but you need to explicitly turn it on.

So what are RelationshipTypes then? A relationship type is a navigational feature of Neo4j. It is used to implement what is known in graph theory as edge-labeled multigraphs. This feature makes it a whole lot easier to navigate through a graph that represents application data. Adding similar labels to nodes would not provide any navigational benefit, which is why Neo4j does not implement such a feature.

It is well worth noticing the RelationshipType can be used to implement data types for both relationships and nodes. In a way that allows nodes to have multiple (union) data types.
The way that you implement this in Neo4j is that the data type of a node is determined by the RelationshipType of the relationship is was reached through. A n1 has reached through a relationship r1 with the RelationshipType Ta is said to have the node data type Da, while the same node n1 reached through another relationship r2 with the RelationshipType Tb is said to have the node data type Db. Although it is the same node the application logic will treat it completely different, accessing different properties (with or without overlap). This is a very powerful feature, and not as easy to implement using a label for the nodes to determine the data type of the node.

The design guide for Neo4j recommends that domain model objects are implemented by wrapping nodes and relationships, and that the wrapper class is determined by the type of the traversed relationship as mentioned above. To make this even more simple the Neo4j community have developed a few components that automate this process. Most notably there is neo-weaver that automatically implements an interface or abstract class by the means of getting and setting properties on a node/relationship or by traversing relationships.

Happy Hacking!