środa, 29 grudnia 2010

Type safe Observer/Observable

Using generic design pattern in statically typed languages can lead to some problems related to type safety. For instance let's take a look at the implementation of Observer design pattern in Java which has been created in the pre generics era.
It consists of two classes namely Observer and Observable and in simplified form looks like this:

public interface Observer {
    void update(Observable observable);
}

public class Observable {
    public void addObserver(Observer observer) { }
    public void notifyObservers() { }
}

Let's assume that we want to have two distinct subclasses of Observer and Observable. ObserverA can observe instances of ObservableA only and ObserverB can observe instances of ObservableB only.


How should we define all those classes to enforce correct behaviour? As simple as this question seems to be the solution might not be as obvious for people who don't know generics too much.
The solution is to parametrize both Observer and Observable with two type parameters one for Observer subclass and the other one for Observable subclass.

public interface Observer<T extends Observer<T,O>, 
    O extends Observable<O,T>> {
    void update(O observable);
}

public class Observable<T extends Observable<T,O>, 
    O extends Observer<O,T>> {
    public void addObserver(O observer) { }
    public void notifyObservers() { }
}

public interface ObserverA extends 
    Observable<ObserverA, ObservableA> {
}

public class ObservableA extends 
    <ObservableA, ObserverA > {
}

Thanks to this ObserverA.update() will accept subclasses of ObservableA only and ObservableA.addObserver() will accept subclasses of ObserverA.
The same solution can be applied to any set of classes which depend on each other. In this context simply parametrize each of them with one type parameter for each of the classes.

wtorek, 28 września 2010

Lazy one-to-one inverse relationships in Hibernate

Many people are surprised when lazy loading of inverse (not owning) optional one-to-one relationships using Hibernate does not work for them out of the box.

Let's start with a short example:

@Entity
public class Person {
 private Animal animal;

 @OneToOne(optional = false)
 public Animal getAnimal() {
  return animal;
 }

 public void setAnimals(Animal animal) {
  this.animal = animal;
 }
}

@Entity
public class Animal {
 private Person owner;

 @OneToOne(fetch = FetchType.LAZY, optional = true, mappedBy = "animal")
 public Person getOwner() {
  return owner;
 }

 public void setOwner(Person owner) {
  this.owner = owner;
 }
}

Many developers expect that owner property of the Animal entity will not be loaded until it is accessed for the first time. This is true but only for relationships where the proxy object for the other end of the relationship can be used. In our example it won't work.

There are at least three well known solutions for this problem:
  1. The simplest one is to fake one-to-many relationship. This will work because lazy loading of collection is much easier then lazy loading of single nullable property but generally this solution is very inconvenient if you use complex JPQL/HQL queries.
  2. The other one is to use build time bytecode instrumentation. For more details please read Hibernate documentation: 19.1.7. Using lazy property fetching. Remember that in this case you have to add @LazyToOne(LazyToOneOption.NO_PROXY) annotation to one-to-one relationship to make it lazy. Setting fetch to LAZY is not enough.
  3. The last solution is to use runtime bytecode instrumentation but it will work only for those who use Hibernate as JPA provider in full-blown JEE environment (in such case setting "hibernate.ejb.use_class_enhancer" to true should do the trick: Entity Manager Configuration) or use Hibernate with Spring configured to do runtime weaving (this might be hard to achieve on some older application servers). In this case @LazyToOne(LazyToOneOption.NO_PROXY) annotation is also required.

But what if you don't want to modify the structure of your entities and don't want or cannot use bytecode instumentalization (there are some issues related to this).

There is one more undocumented solution. It requires some modifications in the entities code but thanks to this building and deployment process can remain untouched.

The idea is to fool Hibernate that the entity class which we want to use has been already instrumented. To do this your entity class has to implement FieldHandled or InterceptFieldEnabled interface.

@Entity
public class Animal implements FieldHandled {
 private Person owner;
 private FieldHandler fieldHandler;

 @OneToOne(fetch = FetchType.LAZY, optional = true, mappedBy = "animal")
 @LazyToOne(LazyToOneOption.NO_PROXY)
 public Person getOwner() {
  if (fieldHandler != null) {
   return (Person) fieldHandler.readObject(this, "owner", owner);
  }
  return owner;
 }

 public void setOwner(Person owner) {
  if (fieldHandler != null) {
   this.owner = fieldHandler.writeObject(this, "owner", this.owner, owner);
   return;
  }
  this.owner = owner;
 }

 public FieldHandler getFieldHandler() {
  return fieldHandler;
 }

 public void setFieldHandler(FieldHandler fieldHandler) {
  this.fieldHandler = fieldHandler;
 }
}

If you are using javassist as bytecode provider (default from Hibernate version 3.3.0.CR2) implement org.hibernate.bytecode.javassist.FieldHandled and if you are using CGLib implement net.sf.cglib.transform.impl.InterceptFieldEnabled.

Getters and setters for non-lazy properties requires no changes.

The last thing worth mentioning here is that Hibernate does not support one by one lazy properties loading. This means that if your entity class has more then one lazy properties all of them are going to be loaded during the first access to any of them (I know that this is stupid but this is how it is currently implemented).

czwartek, 16 września 2010

Mapping cyclic object references to XML using JAXB

With JAXB being de facto standard for XML to Java data binding it is hard not to use it in enterprise application. Because of this as a java developer sooner or later you will notice some serious limitations of it. One of the most painful is a lack of support for object cycles and repetitions.

Lets start with a simple java class which we want to serialize to XML using JAXB.

@XmlRootElement
public class Node {
 private List<Node> nodes;
 @XmlAttribute
 private String name;

 public Node() {
 }

 public Node(String name) {
  this.name = name;
 }

 @XmlElementRef 
 public List<Node> getNodes() {
  return nodes;
 }

 public void setNodes(List<Node> nodes) {
  this.nodes = nodes;
 }

 public void addNode(Node node) {
  if (nodes == null) {
   nodes = new ArrayList<Node>();
  }
  nodes.add(node);
 }
}

If we run following test code we will get self explanatory error.

public class Test {
 public static void main(String[] args) throws Exception {
  Node node1 = new Node("node1");
  Node node2 = new Node("node2");
  Node node3 = new Node("node3");
  node1.addNode(node2);
  node1.addNode(node3);
  node2.addNode(node1);
  node2.addNode(node3);
  node3.addNode(node1);
  node3.addNode(node2);
  
  JAXBContext context = JAXBContext.newInstance(Node.class);
  Marshaller marshaller = context.createMarshaller();
  marshaller.marshal(node1, System.out);
 }
}

Exception in thread "main" javax.xml.bind.MarshalException
 - with linked exception:
[com.sun.istack.internal.SAXException2: 
A cycle is detected in the object graph.
This will cause infinitely deep XML: 
node.Node@1e9cb75 -> node.Node@c5c3ac -> node.Node@1e9cb75]

After spending a few hours on searching web for solution for this problem I haven't found any but I was able to came up with my own idea how to fix it.

First of all we need simple dummy XML adapter.

public class AnyTypeAdapter extends XmlAdapter<Object, Object> {
 public Object marshal(Object value) {
  return value;
 }

 public Object unmarshal(Object value) {
  return value;
 }
}

We need also to create wrapper class which will enable us to break cycles.

@XmlRootElement
public class ObjectWrapper {
 private static AtomicInteger nextId = new AtomicInteger(0);
 
 @XmlAttribute
 @XmlID
 private String id = String.valueOf(nextId.addAndGet(1));

 @XmlAttribute
 @XmlIDREF
 private ObjectWrapper ref;

 @XmlJavaTypeAdapter(AnyTypeAdapter.class)
 @XmlAnyElement(lax = true)
 private Object value;

 public ObjectWrapper() {
 }

 public ObjectWrapper(Object value) {
  this.value = value;
 }

 public Object getValue() {
  return value;
 }
 
 public void update(ObjectWrapper ref) {
  this.ref = ref;
  this.id = null;
  this.value = null;
 }

 public Object resolve() {
  return value == null ? 
    (ref == null ? null : ref.value) : 
    value;
 }
}

In order to make its usage easier we need to create another XML adapter.

public class ObjectWrapperAdapter extends 
  XmlAdapter<ObjectWrapper, Object> {
 public ObjectWrapper marshal(Object value) {
  return value == null ? 
    null : new ObjectWrapper(value);
 }

 public Object unmarshal(ObjectWrapper wrapper) {
  return wrapper == null ? 
    null : wrapper.resolve();
 }
}

Last part of the solution is a marshaller listener which will find repetitions in the object graph and transform them to XML id references (I'm using IdentityHashMap here but in some cases HashMap does make sense as well).

public class CycleListener extends Marshaller.Listener {
 private Map<Object, ObjectWrapper> objectMap = 
   new IdentityHashMap<Object, ObjectWrapper>();
 
 public void beforeMarshal(Object source) {
  if (source instanceof ObjectWrapper) {
   ObjectWrapper wrapper = (ObjectWrapper) source;
   if (objectMap.containsKey(wrapper.getValue())) {
    if (wrapper != objectMap.get(wrapper.getValue())) {
     wrapper.update(objectMap.get(wrapper.getValue()));
    }
   } else {
    objectMap.put(wrapper.getValue(), wrapper);
   }
  }
 }
}

With those four classes we need to change the Node class a little bit by applying ObjectWrapperAdapter to it. No other changes to the serialized class are needed.

@XmlJavaTypeAdapter(ObjectWrapperAdapter.class)
@XmlRootElement
public class Node {
 private List<Node> nodes;
 @XmlAttribute
 private String name;

 public Node() {
 }

 public Node(String name) {
  this.name = name;
 }

 @XmlElementRef 
 public List<Node> getNodes() {
  return nodes;
 }

 public void setNodes(List<Node> nodes) {
  this.nodes = nodes;
 }

 public void addNode(Node node) {
  if (nodes == null) {
   nodes = new ArrayList<Node>();
  }
  nodes.add(node);
 }
}

Finally we can rerun our test code. The only change we have to make is to register marshaller listener and wrap Node instance with ObjectWrapper (this is not needed if we know that the root object does not occur in any cycle).

public class Test {
 public static void main(String[] args) throws Exception {
  Node node1 = new Node("node1");
  Node node2 = new Node("node2");
  Node node3 = new Node("node3");
  node1.addNode(node2);
  node1.addNode(node3);
  node2.addNode(node1);
  node2.addNode(node3);
  node3.addNode(node1);
  node3.addNode(node2);

  JAXBContext context = JAXBContext.newInstance(
    Node.class, ObjectWrapper.class);
  Marshaller marshaller = context.createMarshaller();
  marshaller.setListener(new CycleListener());
  marshaller.marshal(new ObjectWrapper(node1), System.out);
 }
}

As a result we will get following XML.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<objectWrapper id="1">
 <node name="node1">
  <objectWrapper id="2">
   <node name="node2">
    <objectWrapper ref="1" />
    <objectWrapper id="4">
     <node name="node3">
      <objectWrapper ref="1" />
      <objectWrapper ref="2" />
     </node>
    </objectWrapper>
   </node>
  </objectWrapper>
  <objectWrapper ref="4" />
 </node>
</objectWrapper>

As we can see each node element is wrapped with objectWrapper element which has an id and a node or a reference to other objectWrapper's id.

This approach works also with more complex object structures. Simply add @XmlJavaTypeAdapter(ObjectWrapperAdapter.class) annotation to all classes which can cause cycles or you want to remain unique after deserialization.