Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC: exception when using @ResponseBody and entity with circular reference

I have the following method, which behind scenes uses Jackson to parse the list of entities to json:

@Controller
@RequestMapping("/user/")
public class EditarLugarController {    

@RequestMapping(value = "stores/{id}/branches", method = RequestMethod.GET)
public @ResponseBody List<Branch> renderBranchesPerStore(@PathVariable(value = "id") Integer id) {
    if(branches == null) {
        //get branches based on store's id 
    }
   return branches;
}

This method is called from the view through ajax using jquery

var idBranch = '${store.id}';
$.get("http://localhost:8080/myapp/user/stores/" + idBranch+ "/branches",
    function(data) {
        // show json objects in page
}); 

The problem is that when this method ends, it throws the following exception:

java.lang.IllegalStateException: getOutputStream() has already been called for this response
    at org.apache.catalina.connector.Response.getWriter(Response.java:639)

I tried removing the @PathVariable (returning some default value) and it works ok, but I need that parameter. Is there a workaroung to this issue?

EDIT: here's the branch code as requested, but again: I DONT think it's related to the issue because if I don't use @PathVariable it works ok, the list of Branches is parsed ok to json and sent to the view. Also, I'm using a Jackson plugin for Hibernate that tells Jackson not to parse attributes that are lazy loaded, to prevent exceptiosn

@Entity
@Table(name = "BRANCH")
public class Branch implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@Column(name="BRANCH_ID")
@GeneratedValue(strategy= GenerationType.TABLE)
private Integer id;

@Column(name = "DESCRIPTION")
@Size(max = 500)
private String description;

@Column(name="STREET")
@NotNull
@Size(max = 100)
private String street;

@Column(name="NUMBER")
@NotNull
@Size(max = 6)
private String number

@Column(name="FLOOR")
@Size(max = 3)
private String floor;

@Column(name="APT")
@Size(max = 10)
private String apt

@OneToMany(cascade = CascadeType.ALL, mappedBy="branch")
private List<BranchPhoto> photos;

@JoinColumn(name = "STORE_FK", referencedColumnName = "STORE_ID")
@ManyToOne(optional = false)
private Store store;

public Branch() {}

// getters & setters

}

EDIT: I've realized that even without PathVariable it thorws same exception, I must have tested that wrong. So the problem actually is for circular reference while parsing json

like image 385
damian Avatar asked Mar 24 '23 10:03

damian


1 Answers

As NimChimpsky said, problem was caused for circular references in the model, in class Branch. Besides using dtos to make serialization simple, another solution for those who do not want to use DTOs (like me) is to use some annotations to tell Jackson how to handle the attributes. these are the annotations needed:

In class Store, the attribute branches:

@OneToMany(mappedBy = "store", cascade = CascadeType.ALL)
@JsonManagedReference // this annotation prevents the exception
private List<Branch> branches

And in class Branch, in the attribute store:

@JoinColumn(name = "LUGAR_FK", referencedColumnName = "LUGAR_ID")
@ManyToOne(optional = false)
@JsonBackReference // this annotation prevents the exception
private Lugar lugar;
like image 83
damian Avatar answered Apr 06 '23 02:04

damian