Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Json (fasterxml) stackoverflow exception

When trying to serialize a Category I get a stackoverflow.

Exception

Warning: StandardWrapperValve[dispatcher]: Servlet.service() for servlet dispatcher threw exception java.lang.StackOverflowError at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:760) at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.findClass(BundleWiringImpl.java:2279) at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1501) at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:75) at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1955) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:660) at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152) at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:100) at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:21) at com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:183) at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:541) at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:644) at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)

Category.java

@Entity
public class Category implements DataObject, Serializable {

    @Id
    @GeneratedValue 
    private Long id;
    private String title;
    private String description;

    @ManyToOne @JsonIgnore 
    private Category parent;


@Override
public long getId() {
    return id;
}

@Override
public void setId(long id) {
    this.id = id;
}

public String getTitle() {
    return title;
}

public void setTitle(String title) {
    this.title = title;
}
public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

public Category getParent() {
   return null;//return parent;
}

public void setParent(Category parent) {
   // this.parent = parent;
}

public boolean isMainCategory()
{
   return true;// return this.parent == null;
}

/**
 * Returns the chain of parent categories with the main category on index 0
 * @return Chain of categories 
 */
public List<Category> getParentChain()
{

   List<Category> cats = new ArrayList<>();
    Category current = this;
    while(!current.isMainCategory())
    {
        cats.add(current);
        current = current.getParent();
    }
    cats.add(current);
    Collections.reverse(cats);
    return cats;
}

@Override
public String toString()
{
    return this.title;
}

@Override
public boolean equals(Object o)
{
    if(!(o instanceof Category))return false;
    Category c = (Category)o;

    return c.title.equals(this.title);
}

@Override
public int hashCode()
{
    return super.hashCode();
} 
}

Rest Controller function

@RequestMapping(value="/{id}", method=RequestMethod.GET)
public ResponseEntity<Category> get(@PathVariable("id") long categoryId)
{
    Category c  =  service.getCategoryRepository().ReadValue(categoryId);
    if(c == null)
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    return new ResponseEntity<>(c,HttpStatus.OK);
}

Note

Even when I replace return new ResponseEntity<>(c,HttpStatus.OK); with return new ResponseEntity<>(new Category(),HttpStatus.OK); I will get a stackoverflow whilist none of the fields contain a value.

It works fine with my other classes it's only this class that causes a stackoverflow.

like image 401
Svexo Avatar asked Aug 05 '15 19:08

Svexo


People also ask

Why stackoverflow error occurs?

StackOverflowError is a runtime error which points to serious problems that cannot be caught by an application. The java. lang. StackOverflowError indicates that the application stack is exhausted and is usually caused by deep or infinite recursion.

What is stackoverflow error?

A stack overflow is a type of buffer overflow error that occurs when a computer program tries to use more memory space in the call stack than has been allocated to that stack.


1 Answers

Sure thing, @JsonIgnore does the job. But what if we need ignored field in our JSON output?

The solution is very simple.

We annotate our 'guilty' field by @JsonManagedReference annotation on the one side of our relation (which means our @ManyToMany annotation).

And @JsonBackReference on the other side of relation (where @OneToMany has been placed).

And that's it. No more recursive loops.

like image 69
Rafal Avatar answered Oct 02 '22 16:10

Rafal