How to serialize a json containing LAZY associations

Multi tool use
How to serialize a json containing LAZY associations
I am having an Person
entity which has @ManyToOne
association with Contact
entity with fetch type LAZY. I am using spring-boot to expose REST API. One of my POST call contains nested JSON to save the parent entity Person
along with association Contact
Person
@ManyToOne
Contact
Person
Contact
Since Contact
fetch type is LAZY, I am encountering into following exception
Contact
ERROR 17415 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.example.rest.RestResultObject["results"]->java.util.ArrayList[0]->com.example.model.Person["contact"]->com.example.model.Contact_$$_jvst8d1_4["handler"])] with root cause
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.example.rest.RestResultObject["results"]->java.util.ArrayList[0]->com.example.model.Person["contact"]->com.example.model.Contact_$$_jvst8d1_4["handler"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.9.3.jar:2.9.3]
Without changing Contact to EAGER. Is there any best way to solve this problem?
Updated:
Person.java
public class Person {
private long id;
private String name;
private String rno;
@ManyToOne(fetch = FetchType.LAZY)
private Contact contact;
// Getters and setters
}
Contact.java
public class Contact {
private long id;
private String info;
@OneToMany
private List<Person> persons;
}
@MarufHassan Updated my post
– Achaius
Jul 2 at 4:01
2 Answers
2
The problem, most likely, is related to transaction processing. JSON serialization is executed out of transaction scope. If so, the easiest solution (not necessarily the best from the architectural point of view) is to create the service that wrap the entity loading (dedicated for REST operations) and perform "delazyfication" of related data, e.g. (the key element is @Transactional
anotation).
@Transactional
@Sevice
@Transactional(readOnly=true)
public class DataReaderServiceImpl extends DataLoaderService{
//initialization code
public Person loadPerson(PredicatesType somePredicate){
Person person = //get person using predicates expression
//"delazy" contacts in transaction scope
person.getContacts();
return person;
}
}
Architecturally, it would be better, in such a service, to have mapping to DTOs and return DTO instances instead of entities.
I have added the following things
Person class
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String rno;
@JsonManagedReference
@ManyToOne(fetch = FetchType.LAZY)
private Contact contact;
//setter & getter
}
Contact class
@Entity
public class Contact {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String info;
@JsonBackReference
@OneToMany(cascade = CascadeType.ALL, mappedBy = "contact")
private List<Person> persons;
//setter & getter
}
and add a dependency
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
</dependency>
and finally add a new config
@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer addCustomBigDecimalDeserialization() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
jacksonObjectMapperBuilder.modules(new Hibernate5Module());
}
};
}
}
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
could you please add code for person & contact?
– Maruf Hassan
Jul 1 at 14:55