So I am working on a RESTful data API using Java, Hibernate, JPA annotations, JAX-RS annotations, JAXB annotations, Jersey, and the Jackson JSON parser.
After trying various configurations of the MAPPING and NATURAL JSON notations that Jersey provides, I finally decided to use the Jackson JSON parser instead. Jackson would be perfect except for this one issue...
The issue I have come across is that Jackson does not work with the JAXB annotations, "@XmlID" and "@XmlIDREF", which I use to signify my entity relationships, and although the "@JsonBackReference" and "@JsonManagedReference" help with this. The combination seems to break down when dealing with direct self-referencing properties.
This seems like it would be a fairly common problem. How have any of you circumvented this limitation with Jackson?
With my POJO as...
@XmlRootElement
public class Employee implements Serializable {
private Date lastUpdatedOn;
private Employee lastUpdatedBy;
private Integer empId;
@JoinColumn(nullable=false)
@OneToOne
@XmlIDREF
public Employee getLastUpdatedBy() {
return createdBy;
}
public void setLastUpdatedBy(Employee lastUpdatedBy) {
this.lastUpdatedBy = lastUpdatedBy;
}
@Temporal(TemporalType.TIMESTAMP)
public Date getLastUpdatedOn() {
return createdOn;
}
public void setLastUpdatedOn(Date lastUpdatedOn) {
this.lastUpdatedOn = lastUpdatedOn;
}
@XmlID
@XmlJavaTypeAdapter(IntegerAdapter.class)
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
}
... and the following EmployeeResource...
@Path("/Employees")
public class EmployeeResource {
private List<Employee> employees;
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
@GET
@Path("/{empId}")
public Response getEmployees(
@Context UriInfo ui
, @PathParam("id") Integer empId
) {
this.employees = HibernateUtil.pagedQuery(
Employee.class
, new ArrayList() {
Restrictions.eq("empId",empId)
}
);
return Response.ok(this).build();
}
}
My JAX-RS resource will produce the following error
org.codehaus.jackson.map.JsonMappingException: Direct self-reference leading to cycle (through reference chain: resources.EmployeeResource["employees"]->java.util.ArrayList[0]->entities.Employee["lastUpdatedBy"])
... but I want it to produce...
{
"employees" : [ {
"lastUpdatedOn" : 1331149770737,
"lastUpdatedBy" : 10150,
"empId" : 10150,
} ],
}
Thanks in advance, everyone!
NOTES:
- I use the IntegerAdapter.class to convert it to a string so that it will work with the @XmlID annotation.
- The Employee and EmployeeResource classes described above are merely abbreviated versions of my actual implementation, but they represent the portion of my implementation that is relevant to this direct self-referencing issue.
EDIT #1 2012.03.10 I'm sorry, in my first version of this question I had gotten confused between the version I have using Jersey's natural notation vs the version I have running with Jackson. I have revised my question to more accurately reflect the direct self-referencing issue I have with Jackson.