简体   繁体   中英

GSON error in Play framework 1.2.5

The bug seems to be a recursion bug, that Company asks for Worksheets which asks for Company again, which .... you get the drift. I have searched the internet and stack overflow for this, I found out why the error happens, but the solution is always write your own parser or use flexjson or some other. I just want to know if there is a solution to this, there has to be since play is quite popular and surely people are fetching Posts and comments in one operation, or aren't they ?

There has to be a solution to this, without swapping out json parsers or writing your own.

Company.java

package models;

import java.util.*;
import javax.persistence.*;

import play.db.jpa.*;

@Entity
public class Company extends Model {
    public String name;
    public String address;
    public String city;
    public String zipcode;
    public String country;
    public String phonenumber;
    public String website;
    public String footer;
    public String maincontactperson;
    public String email;
    public String password;
    public Blob logo;
    @OneToMany(mappedBy = "company", cascade = CascadeType.ALL, orphanRemoval = true, fetch=FetchType.EAGER)
    public List<Worksheet> worksheets;


    }

}

and

Worksheet.java

package models;

import java.util.*;
import javax.persistence.*;

import play.db.jpa.*;

@Entity
public class Worksheet extends Model {
    public String contactname;
    public String name;
    public String address;
    public String phonenumber;
    public String city;
    public String email;
    public String partnumber;
    @Lob
    public String partdescription;
    public String password;
    public Date due_date;
    public Date in_date;
    @Lob
    public String notes;
    @ManyToOne(cascade=CascadeType.ALL)
    public Company company;
...
}

In my controller, I just run this :

List<Company> companies = Company.FindAll();
renderJSON(companies);

This works if there are no worksheets, but once there is a worksheet, it crashes with a mile long error message. Here is the top of it :

00:31:02,623 ERROR ~ 

@6cbn7gi1o
Internal Server Error (500) for request POST /companies/login

Execution exception
InvocationTargetException occured : null

play.exceptions.JavaExecutionException
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:239)
    at Invocation.HTTP Request(Play!)
Caused by: java.lang.reflect.InvocationTargetException
    at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:557)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:508)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:484)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:479)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:161)
    ... 1 more
Caused by: java.lang.StackOverflowError
    at java.util.Date.getTimeImpl(Date.java:870)
    at java.util.Date.getTime(Date.java:866)
    at java.sql.Timestamp.getTime(Timestamp.java:126)
    at java.util.Calendar.setTime(Calendar.java:1076)
    at java.text.SimpleDateFormat.format(SimpleDateFormat.java:875)
    at java.text.SimpleDateFormat.format(SimpleDateFormat.java:868)
    at java.text.DateFormat.format(DateFormat.java:316)
    at com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:90)
    at com.google.gson.internal.bind.DateTypeAdapter.write(DateTypeAdapter.java:41)
    at com.google.gson.internal.bind.TypeAdapters$22$1.write(TypeAdapters.java:522)
    at com.google.gson.internal.bind.TypeAdapters$22$1.write(TypeAdapters.java:515)
....

    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:879)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)

IMHO this isn't a bug, you have a recursion in your model and the framework can't really know automatically how it should serialize the model.

I usually solve this with the @Expose annotation. Add it to all the members you want to show up in your serialized JSON and create a helper method that does something like this:

    Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
    String json = gson.toJson(your_model_instance);

Optionally you can also implement the JsonSerializer interface as suggested in the comment.

In another question , I found a link to this class , which seems to solve the circular reference problem nicely (and without modification of the model classes).

See the approved answer to the linked question for an example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM