What I have in my hands are 4 deeply related entities.
The first one is Sickness defined as follows:
public class Sickness {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
@JsonView(Views.Superficial.class)
private Long id;
/*
* ...
*/
@OneToMany(fetch = FetchType.LAZY)
private List<Diagnostic> Diagnostic; // <---- The first problem :)
/*
*...
*/
Now the diagnostic for the sickness is defined as followed
@Entity
/*
* ...
*/
@Table(name = "Diagnostic")
public class Diagnostic{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonView(Views.Superficial.class)
private Long id;
/*
*...
*/
@JsonIgnore
private String label;
@ManyToMany(fetch = FetchType.EAGER)
@JsonView(Views.Detailed.class)
private List<Question> questions; // <-- Second Problem !
@JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
private Sickness sickness;
The question Entity is defined like this :
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Builder
@Setter
@Table(name = "question")
public class Question {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
@JsonView(Views.Superficial.class)
private Long id;
@Enumerated
@JsonView(Views.Superficial.class)
private TypeQuestion type;
@JsonView(Views.Superficial.class)
private String question_label;
@ManyToMany
@JsonView(Views.Superficial.class)
private List<Choice> choiceList; // <-- Third problem XD
And finally the Choice entity is defined as such :
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Builder
@Table(name = "choice")
public class Choice {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@JsonView(Views.Superficial.class)
private Long id;
@JsonView(Views.Superficial.class)
private String label;
@OneToOne
@JsonView(Views.Detailed.class)
private Diagnostique diagnostique; // <-- :) ; did this because you could have multiple
// diacnostics for a sickness symtome
@OneToOne
@JsonView(Views.Superficial.class)
private Traitement traitement;
@JsonView(Views.Superficial.class)
private String noTreatementNoDiagnosticChoice;
}
The problem is probably the Choice
entity since it calls the diagnostic entity recursively in one or two records.
I have manually injected data records, now it works for the case where I have a single nested diagnostic entity in the Choice object (Diagnostic -> Question -> Choice -> Diagnostic -> Question -> Choice -> Treatment)
But for the double nested case it throws that error (Diagnostic -> Question -> Choice -> Diagnostic -> Question -> Choice Diagnostic -> Question -> Choice -> Treatment ).
I really don’t know what to do at this point, the data modeling of the case is not that great and I’m really too invested in this version of modeling to change it.
Can anyone help?
Here’s some stack traces:
When I query the Sickness
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: 4; nested exception is com.fasterxml.jackson.databind.JsonMappingException: 4rntat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:465)rntat org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:104)rntat org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:290)rntat org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:219)rntat
When I query the diagnostic
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: 4; nested exception is com.fasterxml.jackson.databind.JsonMappingException: 4 (through reference chain: com.nst.onercp.domain.Diagnostic$HibernateProxy$SlDHxnlx["questions"])rntat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:465)rntat org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:104)rntat org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:290)rntat org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:219)rntat org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:78)
Sorry for the long post 🙂
2
Answers
Solved with @JsonIgnoreProperties(value="diagnostique") and a dedicated api endpoint to get the diagnostic of a choice if present.
You should use DTOs pattern
https://en.wikipedia.org/wiki/Data_transfer_object
Try learning about Mapstruct it might help with this use case
https://mapstruct.org/