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:
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.
Jackson 1.x does not have specific support for resolving cyclic references, but there is support for handling parent/child style dependencies: this blog entry has more info.
Jackson 2.0 will have support for arbitrary Object Id / reference handling, using new @JsonIdentityInfo
annotation, so perhaps that could be used to solve the problem. Official 2.0 release is not out yet, but release candidates (latest being RC2) are, in case you wanted to have a look. Not sure if it would handle your problem, but maybe it would help.
EDIT: Actually, Jackson JAXB annotation module will have support for @XmlID
/ @XmlIDREF
for 2.0.0 -- this was just implemented, see here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With