I am trying out some very basic webservice. I get this exception everytime I try to return the Prtnr object.
Uncaught exception thrown in one of the service methods of the servlet: spitter. Exception thrown :
org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError)
(through reference chain: org.hibernate.collection.PersistentSet[0]->org.abc.dvo.PrtnrGeoInfo["id"]->org.abc.dvo.PrtnrGeoInfoId["partner"]->
org.abc.dvo.Prtnr["prtnrGeoInfos"]->org.hibernate.collection.PersistentSet[0]->org.abc.dvo.PrtnrGeoInfo["id"]->org.abc.dvo.PrtnrGeoInfoId["partner"]->
org.abc.dvo.Prtnr["prtnrGeoInfos"]->org.hibernate.collection.PersistentSet[0]->org.abc.dvo.PrtnrGeoInfo["id"]->org.abc.dvo.PrtnrGeoInfoId["partner"]->
org.abc.dvo.Prtnr["prtnrGeoInfos"]->org.hibernate.collection.PersistentSet[0]->org.abc.dvo.PrtnrGeoInfo["id"]->org.abc.dvo.PrtnrGeoInfoId["partner"]->
...
at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:164)
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446)
at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150)
...
The Prtnr class is :
public class Prtnr implements Cloneable, java.io.Serializable {
private static final long serialVersionUID = 201207021420600052L;
private Integer prtnrId;
private String creatUserId;
private Date creatTs;
private String updtUserId;
private Date updtTs;
private String prtnrNm;
private Integer cncilNum;
private Character prtnrTypCd;
private Set<PrtnrGeoInfo> prtnrGeoInfos = new HashSet<PrtnrGeoInfo>(0);
private Set<PrtnrDtl> prtnrDtls = new HashSet<PrtnrDtl>(0);
private Set<SuplyDtl> suplyDtls = new HashSet<SuplyDtl>(0);
private Set<TrnsprtDtl> trnsprtDtls = new HashSet<TrnsprtDtl>(0);
private Set<PrtnrFacil> prtnrFacils = new HashSet<PrtnrFacil>(0);
private Set<PrtnrHumanResrc> prtnrHumanResrcs = new HashSet<PrtnrHumanResrc>(0);
.....
.....
Getters and setters for these properties
...
}
The PrtnrGeoInfo class is :
public class PrtnrGeoInfo implements java.io.Serializable {
private PrtnrGeoInfoId id = new PrtnrGeoInfoId();
private String creatUserId;
private Date creatTs;
private String updtUserId;
private Date updtTs;
Getters and setters for these properties
}
The PrtnrGeoInfoId class is :
public class PrtnrGeoInfoId implements java.io.Serializable {
private Prtnr partner;
private GeoSegment geoSegment;
private static final long serialVersionUID = 201207060857580050L;
Getters and setters for these properties
}
I believe it is because of the classes refrencing each other. But how can this problem be resolved. Within the app which is Struts 2 and Spring, this object get passed just fine.
The controller class is as follows:
@Controller
@RequestMapping("/partners")
public class PartnerController {
@RequestMapping(value="/{id}", method=RequestMethod.GET, headers ={"Accept=text/xml,application/json"})
@ResponseBody
public Prtnr getPartner(@PathVariable("id") String id) throws Exception{
Prtnr partner = null;
try{
partner = partnerService.getPartnerById(Integer.valueOf(id));
System.out.println("******* Test message " );
}catch(Exception ex){
System.out.println("******* Exception thrown ... " + ex.getMessage());
}
return partner;
}
}
The calling class is public class TestTemplate {
private static final long serialVersionUID = 1130201273334264152L;
public static void main(String[] args){
Prtnr partner = (Prtnr)new RestTemplate().getForObject("http://localhost:9080/respondersApp/testWs/partners/{id}", Prtnr.class, "1");
System.out.println("partner name is : " + partner.getPrtnrNm());
}
}
In this link you can find how to solve this.
However below I'll paste the solution in practice.
It's very simple. Assuming that your database query already works without JSON, all you have to do is this:
Add the @JsonManagedReference In the forward part of the relationship (i.e. User.java class):
@Entity
public class User implements java.io.Serializable{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@Column(name="name")
private String name;
@ManyToMany
@JoinTable(name="users_roles",joinColumns=@JoinColumn(name = "user_fk"),
inverseJoinColumns=@JoinColumn(name = "role_fk"))
@JsonManagedReference
private Set<Role> roles = new HashSet<Role>();
...
Add the @JsonBackReference In the back part of the relationship (i.e. Role.java class):
@Entity
public class Role implements java.io.Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@ManyToMany(mappedBy="roles")
@JsonBackReference
private Set<User> users = new HashSet<User>();
...
The work is done. If you take a look at your firebug logs, you'll notice that the infinite recursive loop has disappeared.
This is quite a common scenario for me when you are trying to convert entity classes into JSON format. The simplest solution is just to use @JsonIgnore on the reverse mapping to break the cycle.
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