Endless recursion with the release of Jackson JSON and Hibernate JPA (another one)

I found many resources on this, such as this Endless recursion with the release of Jackson JSON and Hibernate JPA . I tried to implement all the various suggestions described there (including basic @JsonIgnore), but to no avail. I can't get anything but endless recursion errors, no matter what I'm trying to do. I think I have a pretty similar / typical setup, but obviously with something wrong, because despite using @JsonManagedReference, @JsonBackReferencere and @JsonIdentityInfo annotations, I keep getting the error.

My tables are "exchange" and "stock", with many of them between them, and I tested them through ExchangeEndpoint. I confirmed that if I completely remove the β€œstock” from the β€œexchange” object, the service works fine, but for some reason, json annotations do not seem to affect. Below I think this is a solution based on the second (but more popular) answer in the above Endless recursion with Jackson JSON and Hibernate JPA problem .

Exchange.java

@Entity @Table(name = "exchange", schema = "public") @XmlRootElement @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id") public class Exchange implements java.io.Serializable { ... @OneToMany(fetch = FetchType.LAZY, mappedBy = "exchange") @JsonManagedReference public Set<Stock> getStocks() { return this.stocks; } ... 

Stock.java

 @Entity @Table(name = "stock", schema = "public") @XmlRootElement @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id") public class Stock implements java.io.Serializable { ... @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "exchangeid", nullable = false) @JsonBackReference @JsonIgnore public Exchange getExchange() { return this.exchange; } ... 

ExchangeEndpoint.java

 @Stateless @Path("/exchanges") public class ExchangeEndpoint { @PersistenceContext(unitName = "postgresql-ss4") private EntityManager em; ... @GET @Produces("application/json") public List<Exchange> listAll(@QueryParam("start") Integer startPosition, @QueryParam("max") Integer maxResult) { TypedQuery<Exchange> findAllQuery = em .createQuery( "SELECT DISTINCT e " + "FROM Exchange e " + "LEFT JOIN FETCH e.stocks " + "ORDER BY e.exchangeid", Exchange.class); if (startPosition != null) { findAllQuery.setFirstResult(startPosition); } if (maxResult != null) { findAllQuery.setMaxResults(maxResult); } final List<Exchange> results = findAllQuery.getResultList(); return results; } 

edit:

some error conclusion to be sure that I am not misinterpreting something;

15: 35: 16,406 ERROR [org.jboss.resteasy.resteasy_jaxrs.i18n] (http- / 0.0.0.0: 8080-1) RESTEASY000100: Failed to execute GET / exchange /: org.jboss.resteasy.spi.WriterException: org .codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError) (via the chain of links: net.hb.forge2RestServices.model.Exchange ["shares"] β†’ org.hibernate.collection.internal.PersistentSet [0] β†’ net.hb .forge2RestServices.model.Stock ["exchange"] β†’ net.hb. forge2RestServices.model.Exchange ["shares" β†’ org.hibe ...... Exchange ["share"] β†’ org.hibernate.collection.internal .PersistentSet [0] β†’ [net.hb.forge2RestServices.model.Stock "share"] β†’ [net.hb.forge2RestServices.model.Exchange "share"]) on org.jboss.resteasy.core.ServerResponse.writeTo (ServerResponse .java: 262)

Please let me know what additional information I can provide to help explain my debacle. Tia.

+6
source share
4 answers

Such problems are much easier to avoid if you do not expose your JPA objects via REST.

You should consider using the DTO on the REST side and the display objects in the DTO and vice versa, either by manually encoding the cartographer or by generating one of them using MapStruct .

As a bonus, you will avoid security issues.

+2
source

It seems that the problem was import. I'm not sure why, but org.codehaus.jackson.annotate.JsonIgnore works for me, but com.fasterxml.jackson.annotation.JsonIgnore does not.

+1
source

Use @JsonManagedReference, @JsonBackReference

 public class User { public int id; public String name; @JsonBackReference public List<Item> userItems; } public class Item { public int id; public String itemName; @JsonManagedReference public User owner; } 

Note that:

@JsonManagedReference is a direct part of the link - the one that is usually serialized. @JsonBackReference is the back of the link - it will be omitted from serialization.

http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion

+1
source

The problem is that you have a link to Stock and back with Stock , you have a link to Exchange . Therefore, JSON goes to stock, back to Exchange , and then to Exchange it will generate all Stock , etc.

To break the loop, it is best to add a JsonIgnore annotation to the field that references the parent object - ManyToOne - in this case, Stock.exchange (or the recipient for this).

0
source

Source: https://habr.com/ru/post/946344/


All Articles