Difference between revisions of "EclipseLink/Release/2.4.0/JAXB RI Extensions/Cycle Recoverable"

From Eclipsepedia

Jump to: navigation, search
 
(18 intermediate revisions by one user not shown)
Line 1: Line 1:
 
<div style="margin:5px;float:right;border:1px solid #000000;padding:5px">__TOC__</div>
 
<div style="margin:5px;float:right;border:1px solid #000000;padding:5px">__TOC__</div>
  
= Design Documentation: CycleRecoverable =
+
= Cycle Recoverable =
  
[http://bugs.eclipse.org/372404 ER 372404]
+
In the current JAXB RI, developed by Sun, there is a series of "proprietary" JAXB extensions which provide advanced functionality outside of the JAXB specification (these extension classes and properties reside in the '''com.sun.xml.bind''' package).
  
In the current JAXB RI, developed by Sun, there are a series of "proprietary" JAXB extensions that are available to provide advanced JAXB functionality outside of the JAXB spec (these extension classes reside in the '''com.sun.xml.bind''' package).
+
The '''CycleRecoverable ''' interface allows the user to write their own logic to be used when object cycles are detected during marshal operations.  When a cycle is detected, MOXy will invoke the '''onCycleDetected''' method, which returns a "replacement" object for the one that caused the cycle.
 
+
The '''CycleRecoverable ''' interface allows the user to write their own logic to be used when object cycles are detected during marshal operations.  When a cycle is detected, MOXy will invoke the '''onCycleDetected''', which returns a "replacement" object for the one that caused the cycle.
+
 
+
This document will outline the design for an EclipseLink equivalent to this extension.
+
  
  
Line 18: Line 14:
 
<div style="width:800px">
 
<div style="width:800px">
 
<source lang="java">
 
<source lang="java">
 +
import java.util.*;
 
import javax.xml.bind.annotation.*;
 
import javax.xml.bind.annotation.*;
  
Line 23: Line 20:
 
public class Department {
 
public class Department {
  
 +
  @XmlAttribute
 +
  public int id;
 
   public String name;
 
   public String name;
   public List<Employee> employees;
+
   public List<Employee> employees = new ArrayList<Employee>();
  
 
}
 
}
Line 34: Line 33:
 
public class Employee {
 
public class Employee {
  
 +
  @XmlAttribute
 +
  public int id;
 
   public String name;
 
   public String name;
 
   public Department dept;
 
   public Department dept;
  
 
}
 
}
 +
</source>
 +
</div>
 +
 +
 +
An object cycle would be created if you constructed the following objects:
 +
 +
<div style="width:800px">
 +
<source lang="java">
 +
Employee emp1 = new Employee();
 +
emp1.name = "Fred Smith";
 +
 +
Department dept1 = new Department();
 +
dept1.name = "Accounting";
 +
 +
emp1.dept = dept1;
 +
dept1.employees.add(emp1);
 +
 +
JAXBContext ctx = JAXBContext.newInstance(new Class[] { Department.class });
 +
ctx.createMarshaller().marshal(dept1, System.out);
 +
</source>
 +
</div>
 +
 +
<span style="color:#FF0000">'''A cycle is detected in the object graph.  This will cause an infinite loop: Department@122cdb6 -> Employee@1ef9157 -> Department@122cdb6'''</span>
 +
 +
 +
By implementing the '''CycleRecoverable''' interface on the '''Department''' class, the user has the opportunity to provide a new Object for marshalling, replacing the duplicate '''Department'''.  In this example, we will return a '''DepartmentPointer''' object that holds the '''id''' of the real '''Department'''.
 +
 +
<div style="width:800px">
 +
<source lang="java">
 +
import java.util.*;
 +
import javax.xml.bind.annotation.*;
 +
import com.sun.xml.bind.CycleRecoverable;
 +
 +
@XmlRootElement
 +
public class Department implements CycleRecoverable {
 +
 +
  @XmlAttribute
 +
  public int id;
 +
  public String name;
 +
  public List<Employee> employees = new ArrayList<Employee>();
 +
 +
  public Object onCycleDetected(Context arg0) {
 +
      // Context provides access to the Marshaller being used:
 +
      System.out.println("JAXB Marshaller is: " + cycleRecoveryContext.getMarshaller());
 +
 +
      DepartmentPointer p = new DepartmentPointer();
 +
      p.id = this.id;
 +
      return p;
 +
  }
 +
 +
}
 +
</source>
 +
</div>
 +
 +
<div style="width:800px">
 +
<source lang="java">
 +
public class DepartmentPointer {
 +
 +
    public int id;
 +
   
 +
}
 +
</source>
 +
</div>
 +
 +
Note: In this case, '''DepartmentPointer''' must be explicitly specified in the list of classes when creating the '''JAXBContext''', as it is not reachable from the '''Department''' class:
 +
 +
<div style="width:850px">
 +
<source lang="xml">
 +
JAXBContext ctx = JAXBContext.newInstance(new Class[] { Department.class, DepartmentPointer.class });
 +
</source>
 +
</div>
 +
 +
 +
This time, marshalling '''dept1''' will succeed:
 +
 +
<div style="width:800px">
 +
<source lang="xml">
 +
JAXB Marshaller is: org.eclipse.persistence.jaxb.JAXBMarshaller@18fd984
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<department>
 +
  <id>123</id>
 +
  <name>Accounting</name>
 +
  <employees>
 +
      <id>111</id>
 +
      <name>Fred Smith</name>
 +
      <dept xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="departmentPointer">
 +
        <id>123</id>
 +
      </dept>
 +
  </employees>
 +
</department>
 
</source>
 
</source>
 
</div>
 
</div>

Latest revision as of 11:36, 18 June 2012

[edit] Cycle Recoverable

In the current JAXB RI, developed by Sun, there is a series of "proprietary" JAXB extensions which provide advanced functionality outside of the JAXB specification (these extension classes and properties reside in the com.sun.xml.bind package).

The CycleRecoverable interface allows the user to write their own logic to be used when object cycles are detected during marshal operations. When a cycle is detected, MOXy will invoke the onCycleDetected method, which returns a "replacement" object for the one that caused the cycle.


[edit] Example

Consider the following two classes:

import java.util.*;
import javax.xml.bind.annotation.*;
 
@XmlRootElement
public class Department {
 
   @XmlAttribute
   public int id;
   public String name;
   public List<Employee> employees = new ArrayList<Employee>();
 
}
public class Employee {
 
   @XmlAttribute
   public int id;
   public String name;
   public Department dept;
 
}


An object cycle would be created if you constructed the following objects:

Employee emp1 = new Employee();
emp1.name = "Fred Smith";
 
Department dept1 = new Department();
dept1.name = "Accounting";
 
emp1.dept = dept1;
dept1.employees.add(emp1);
 
JAXBContext ctx = JAXBContext.newInstance(new Class[] { Department.class });
ctx.createMarshaller().marshal(dept1, System.out);

A cycle is detected in the object graph. This will cause an infinite loop: Department@122cdb6 -> Employee@1ef9157 -> Department@122cdb6


By implementing the CycleRecoverable interface on the Department class, the user has the opportunity to provide a new Object for marshalling, replacing the duplicate Department. In this example, we will return a DepartmentPointer object that holds the id of the real Department.

import java.util.*;
import javax.xml.bind.annotation.*;
import com.sun.xml.bind.CycleRecoverable;
 
@XmlRootElement
public class Department implements CycleRecoverable {
 
   @XmlAttribute
   public int id;
   public String name;
   public List<Employee> employees = new ArrayList<Employee>();
 
   public Object onCycleDetected(Context arg0) {
       // Context provides access to the Marshaller being used:
       System.out.println("JAXB Marshaller is: " + cycleRecoveryContext.getMarshaller());
 
       DepartmentPointer p = new DepartmentPointer();
       p.id = this.id;
       return p;
   }
 
}
public class DepartmentPointer {
 
    public int id;
 
}

Note: In this case, DepartmentPointer must be explicitly specified in the list of classes when creating the JAXBContext, as it is not reachable from the Department class:

JAXBContext ctx = JAXBContext.newInstance(new Class[] { Department.class, DepartmentPointer.class });


This time, marshalling dept1 will succeed:

JAXB Marshaller is: org.eclipse.persistence.jaxb.JAXBMarshaller@18fd984
<?xml version="1.0" encoding="UTF-8"?>
<department>
   <id>123</id>
   <name>Accounting</name>
   <employees>
      <id>111</id>
      <name>Fred Smith</name>
      <dept xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="departmentPointer">
         <id>123</id>
      </dept>
   </employees>
</department>