Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

EclipseLink/Release/2.4.0/JAXB RI Extensions/Cycle Recoverable

Design Documentation: CycleRecoverable

ER 372404

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, 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.


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.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) {
       return new DepartmentPointer(this.id);
   }
 
}
public class DepartmentPointer {
 
    public int id;
 
}

This time, marshalling dept1 will succeed:


<?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>

Copyright © Eclipse Foundation, Inc. All Rights Reserved.