10

I have tried several things I found while searching but nothing helped or I did not implement it correctly.

Error I'm getting

Direct self-reference leading to cycle (through reference chain: io.test.entity.bone.Special["appInstance"]->io.test.entity.platform.ApplicationInstance["appInstance"])

Both these extend the base entity and in the base (super class) it has an appInstance as well.

Base entity looks similar to this

@MappedSuperclass
public abstract class BaseEntity implements Comparable, Serializable {

@ManyToOne
protected ApplicationInstance appInstance;

//getter & setter

}

Application entity looks like this

public class ApplicationInstance extends BaseEntity implements Serializable { 
   private List<User> users;
// some other properties (would all have the same base and application instance . User entity will look similar to the Special.)
}

Special entity

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "objectType")
@JsonIgnoreProperties({"createdBy", "appInstance", "lastUpdatedBy"})
public class Special extends BaseEntity implements Serializable {

    @NotNull
    @Column(nullable = false)
    private String name;

    @Column(length = Short.MAX_VALUE)
    private String description;

    @NotNull
    @Column(nullable = false)
    private Double price;

    @OneToOne
    private Attachment image;

    @Enumerated(EnumType.STRING)
    @ElementCollection(targetClass = SpecialTag.class)
    @CollectionTable(name = "special_tags")
    @Column(name = "specialtag")
    private List<SpecialTag> specialTags;

    @Temporal(TemporalType.TIME)
    private Date specialStartTime;

    @Temporal(TemporalType.TIME)
    private Date specialEndTime;

    @Enumerated(EnumType.STRING)
    @ElementCollection(targetClass = WeekDay.class)
    @CollectionTable(name = "available_week_days")
    @Column(name = "weekday")
    private List<WeekDay> availableWeekDays;

    @OneToMany(mappedBy = "special", cascade = CascadeType.REFRESH)
    private List<SpecialStatus> statuses;

    @OneToMany(mappedBy = "special", cascade = CascadeType.REFRESH)
    private List<SpecialReview> specialReviews;

    @Transient
    private Integer viewed;

    private Boolean launched;

    @OneToMany(mappedBy = "special")
    private List<CampaignSpecial> specialCampaigns;


  @Override
  @JsonIgnore
  public ApplicationInstance getAppInstance() {
    return super.getAppInstance(); 
  }
}

All entities in Special inherits from BaseEntity which contains AppInstance

then i have a method to get the special

@GET
@Path("{ref}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(value = MediaType.TEXT_PLAIN)
public Special findByGuestRef(@PathParam("ref") String pRefeference) {
  // find the special and return it
 return special;
}

On the special entity I tried the following

  • Added jsonIgnoreProperties
  • Added an override for appInstance to annotate with @JsonIgnore
  • @JsonIdentityInfo

links for the above

none of those solutions works. Am I doing something wrong?

Note: Would it also just be possible to edit special, since the other entities are in a different package and would not like to edit them.

Tinus Jackson
  • 3,397
  • 2
  • 25
  • 58
  • Make `protected ApplicationInstance appInstance` private and add some getter(s) and setter(s) for it (either protected or public) then override the getter(s) in the `ApplicationInstance` with a `@JsonIgnore` annotation. – ConductedClever Aug 19 '17 at 15:02
  • @aristotll I have added a bit more detail but don't think it will change. all reference the Application Instance – Tinus Jackson Aug 21 '17 at 05:55
  • Just to clarify: you would exclude appInstance from this instance only and this is why You cannot add `@JsonIgnore` on the mapped class? – Hash Aug 21 '17 at 11:36
  • @Mark I could exclude the appInstance from anyplace if necessary. Would prefer to avoid making changes to BaseEntity as well as Appinstance itself. Special does contain other entities with appinstance , should i exclude it on all ? – Tinus Jackson Aug 21 '17 at 11:43
  • Probably yes, but it would be easy to tell if you could include the whole entity definition. Could You add it? And I'll be able to test it myself as well. – Hash Aug 21 '17 at 11:45
  • Can you provide the json string example you want to read value from? – aristotll Aug 21 '17 at 12:43
  • @aristotll it should be simple, i just want the basics special{name,description,price,image} – Tinus Jackson Aug 21 '17 at 12:50
  • Reason for downvote? – Tinus Jackson Aug 21 '17 at 13:04
  • Does the class `Attachment ` extends `BaseEntity` as image is something you need. – aristotll Aug 21 '17 at 13:07
  • @aristotll All entities in Special inherits from BaseEntity which contains AppInstance, including attachment. – Tinus Jackson Aug 21 '17 at 13:18

2 Answers2

3

Usually excluding attributes in a response is as easy as adding a @JsonIgnore annotation to their getters, but if you don't want to add this annotation to a parent class, you could override the getter and then add the annotation on it:

public class Special extends BaseEntity implements Serializable {
    ...
    @JsonIgnore
    public ApplicationInstance getAppInstance() {
        return this.appInstance;
    }
    ...
}

NOTE: As there are several frameworks, make sure that you are using the correct @JsonIgnore annotation or it will be ignored, see this answer for instance.

Another option, more "manual", is just creating a bean for the response which would be a subset of the Special instance:

@GET
@Path("{ref}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(value = MediaType.TEXT_PLAIN)
public SpecialDTO findByGuestRef(@PathParam("ref") String pRefeference) {
  // find the special and return it
 return new SpecialDTO(special);
}


public class SpecialDTO {

    //declare here only the attributes that you want in your response

    public SpecialDTO(Special sp) {
        this.attr=sp.attr; // populate the needed attributes
    }

}
Pablo Lozano
  • 10,122
  • 2
  • 38
  • 59
  • Thanks, the manual does work and can use it. Will try the other way to edit the super class, since i have a lot of entities like special and don't want to create a DTO class for each. – Tinus Jackson Aug 21 '17 at 13:34
  • Please tell us if it works, because I haven't tested it, it's just a theoretical solution – Pablo Lozano Aug 21 '17 at 14:01
  • i have tried it and still does not work. For now i will use the "manual option" suggested, that currently works. – Tinus Jackson Aug 21 '17 at 14:29
  • same error. Will accept this as an answer if nothing pops up (did most part "manually" so far). Thanks – Tinus Jackson Aug 23 '17 at 07:30
  • Just one last check: Make sure your are using the proper @JsonIgnore annotation: https://stackoverflow.com/questions/19894955/spring-jsonignore-not-working – Pablo Lozano Aug 23 '17 at 07:33
  • .Currently using import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonTypeInfo;. Should i use codehaus instead like the answered question? – Tinus Jackson Aug 23 '17 at 07:51
  • I'm not sure, it depends of which implementation of JAX-RS and Jackson you are using: some comments say they had to do the opposite change. I was just wondering why your application is ignoring the @JsonIgnore annotation and I found that answer. – Pablo Lozano Aug 23 '17 at 08:18
1

To me, problem seems to be in the Special object and the fields being initialized in it. I guess that there is a circular reference detected when serialisation happens. Something similar to:

class A {
    public A child;
    public A parent;
}

A object = new A();
A root = new A();
root.child = object;
object.parent = root;

In the above code, whenever you will try to seralize either of these objects, you will face the same problem. Note that public fields are not recommended.

I'll suggest to peek into your Special object and the references set in it.

Sunil Singhal
  • 593
  • 3
  • 11
  • 1
    Please read the whole question, OP knows it. The question is how to fix that without modifying the parent class which declares the problematic attribute – Pablo Lozano Aug 21 '17 at 14:04