Issue
I have list of objects clients
List<Client> clientsList=new ArrayList<Client>();
clientsList=clientDao.GetAllClients();
Entity Client has others list as attributes:
@ManyToOne(optional=false)
private User createdBy;
@ManyToMany(mappedBy = "Clients")
private Set<ClientType> Types=new HashSet();
@ManyToOne(optional=false)
private LeadSource id_LeadSource;
@ManyToOne(optional=false)
private Agencie id_Agencie;
@OneToMany(cascade=CascadeType.ALL,mappedBy="Owner")
private Set<Propertie> properties=new HashSet();
@OneToMany(cascade=CascadeType.ALL,mappedBy="buyer")
private Set<Sale> sales=new HashSet();
@OneToMany(cascade=CascadeType.ALL,mappedBy = "client")
private Set<Rent> Rents=new HashSet();
@OneToMany(cascade=CascadeType.ALL,mappedBy = "clientDoc")
private Set<Document> Docuements=new HashSet();
and when i try to convert list of clients to json format
out.write(new Gson().toJson(clientsList));
i get this error :
java.lang.StackOverflowError
at com.google.gson.stream.JsonWriter.beforeName(JsonWriter.java:603)
at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:401)
at com.google.gson.stream.JsonWriter.value(JsonWriter.java:512)
at com.google.gson.internal.bind.TypeAdapters$8.write(TypeAdapters.java:270)
at com.google.gson.internal.bind.TypeAdapters$8.write(TypeAdapters.java:255)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:113)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:240)
Solution
That is because your entities have bidirectional connections. So for example Client
has a set of Rent
s and each rent has a reference to Client
. When you try serializing a Client
you serialize its Rents
and then you have to serialize each Client
in Rent
and so on. This is what causes the StackOverflowError
.
To solve this problem you will have to mark some properties as transient
(or use some similar anotation), for example use transient Client
in Rent
Then any marshalling lib will just ignore this property.
In case of Gson you can do the other way around marking those field you do want to be included in json with @Expose
and creating the gson object with:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
P.S. Also, I would like to mention that converting your JPA entity to json and sending it somewhere is generally not a very good idea. I’d recommend creating a DTO(Data Transfer Object) class where you include only the info you need and ideally using only simple types like int
, Date
, String
and so on. If you have questions about this approach you can google for DTO
, Data Transfer Object
or follow this link: https://www.tutorialspoint.com/design_pattern/transfer_object_pattern.htm
Answered By – Nestor Sokil
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0