I've faced the problem, which is a little bit close to this issue, but when I've done all the steps, i still have such an exception:
org.codehaus.jackson.map.JsonMappingException: No serializer found for
class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and
no properties discovered to create BeanSerializer (to avoid exception,
disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) ) (through
reference chain:
java.util.ArrayList[0]->com.myPackage.SomeEntity["mainEntity"]->com.myPackage.MainEntity["subentity1"]->com.myPackage.Subentity1_$$_javassist_8["handler"])
here is code with my entities:
#JsonAutoDetect
public class MainEntity {
private Subentity1 subentity1;
private Subentity2 subentity2;
#JsonProperty
public Subentity1 getSubentity1() {
return subentity1;
}
public void setSubentity1(Subentity1 subentity1) {
this.subentity1 = subentity1;
}
#JsonProperty
public Subentity2 getSubentity2() {
return subentity2;
}
public void setSubentity2(Subentity2 subentity2) {
this.subentity2 = subentity2;
}
}
#Entity
#Table(name = "subentity1")
#JsonAutoDetect
public class Subentity1 {
#Id
#Column(name = "subentity1_id")
#GeneratedValue
private Long id;
#Column(name = "name", length = 100)
private String name;
#JsonIgnore
#OneToMany(mappedBy = "subentity1")
private List<Subentity2> subentities2;
#JsonProperty
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#JsonProperty
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//here I didin't add #JsonProperty, cause it leads to cycling during serialization
public List<Subentity2> getSubentity2s() {
return subentity2s;
}
public void setSubentity2s(List<Subentity2> subentity2s) {
this.subentity2s = subentity2s;
}
}
#Entity
#Table(name = "subentity2")
#JsonAutoDetect
public class Subentity2 {
#Id
#Column(name = "subentity2_id")
#GeneratedValue
private Long id;
#Column(name = "name", length = 50)
private String name;
#ManyToOne
#JoinColumn(name = "subentity1_id")
private Subentity1 subentity1;
#JsonProperty
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#JsonProperty
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#JsonProperty
public Subentity1 getSubentity1() {
return subentity1;
}
public void setSubentity1(Subentity1 subentity1) {
this.subentity1 = subentity1;
}
here is code of my method for transformation:
private String toJSON(Object model) {
ObjectMapper mapper = new ObjectMapper();
String result = "";
try {
result = mapper.writeValueAsString(model);
} catch (JsonGenerationException e) {
LOG.error(e.getMessage(), e);
} catch (JsonMappingException e) {
LOG.error(e.getMessage(), e);
} catch (IOException e) {
LOG.error(e.getMessage(), e);
}
return result;
}
I'll very grateful for any help, pieces of advice or code :)
UPD
alsp, I forgot to add piece of code from my controller:
String result = "";
List<SomeEntity> entities = someEntityService.getAll();
Hibernate.initialize(entities);
for (SomeEntity someEntity : entities) {
Hibernate.initialize(someEntity.mainEntity());
Hibernate.initialize(someEntity.mainEntity().subentity1());
Hibernate.initialize(someEntity.mainEntity().subentity2());
}
result = this.toJSON(entities);
I can't ignore any fields, cause I need them
Basically some of your fields are wrapped into lazy hibernate proxies.
Call Hibernate.initialize(model) before serializing your object, it will load your lazy collections and references.
But I would not mix database and view models, this is a bad practice. Create set of classes for your restful model and convert database entities to them before serialization.
I created a Bean with plane fields(String, Boolean, Double, etc.), which are in my classes and made method for transformation
If you are using lazy loading add this
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
Related
I have a next question: while working with Hibernate 3.3.0 run into a situation when I have two tables with one-to-many relationships and I need to get the list of parents. In each entity must be filled the several fields from the parent table and a list of all children mapped in the parent. For the easiest understanding, I give an example. I have two tables with one-to-many relationships: parent is "recipients" and child is "requisites". And I have two classes whose objects are the rows of these tables. Class for the table of recipients:
#Entity
#Table(name = "recipients")
#JsonFilter(value = "recipientsFilter")
public class POJORecipient implements POJO {
private static final long serialVersionUID = 4436819032452218525L;
#Id
#Column
private long id;
#Version
#Column
private long version;
#Column(name = "client_id")
private long clientId;
#Column
private String inn;
#Column
private String name;
#Column(name = "rcpt_country_code")
private String rcptCountryCode;
#Column(name = "rcpt_passp_ser")
private String rcptPasspSer;
#Column(name = "rcpt_passp_num")
private String rcptPasspNum;
#OneToMany(mappedBy = "recipient", fetch = FetchType.LAZY)
#JsonManagedReference
private Set<POJORequisite> requisites = new HashSet<>();
public POJORecipient(){}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
public long getClientId() {
return clientId;
}
public void setClientId(long clientId) {
this.clientId = clientId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInn() {
return inn;
}
public void setInn(String inn) {
this.inn = inn;
}
public String getRcptCountryCode() {
return rcptCountryCode;
}
public void setRcptCountryCode(String rcptCountryCode) {
this.rcptCountryCode = rcptCountryCode;
}
public String getRcptPasspSer() {
return rcptPasspSer;
}
public void setRcptPasspSer(String rcptPasspSer) {
this.rcptPasspSer = rcptPasspSer;
}
public String getRcptPasspNum() {
return rcptPasspNum;
}
public void setRcptPasspNum(String rcptPasspNum) {
this.rcptPasspNum = rcptPasspNum;
}
public Set<POJORequisite> getRequisites() {
return requisites;
}
public void setRequisites(Set<POJORequisite> requisites) {
this.requisites = requisites;
}
}
and for requisites table:
#Entity
#Table(name = "requisites")
public class POJORequisite implements POJO {
private static final long serialVersionUID = -35864567359179960L;
#Id
#Column
private long id;
#Version
#Column
private long version;
#Column
private String bic;
#Column
private String bill;
#Column
private String comments;
#Column
private String note;
#ManyToOne
#JoinColumn(name = "recipient_id")
#JsonBackReference
private POJORecipient recipient;
public POJORequisite(){}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
public String getBic() {
return bic;
}
public void setBic(String bic) {
this.bic = bic;
}
public String getBill() {
return bill;
}
public void setBill(String bill) {
this.bill = bill;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public POJORecipient getRecipient() {
return recipient;
}
public void setRecipient(POJORecipient recipient) {
this.recipient = recipient;
}
}
So, I want to select from the recipients only names and all mapped requisites. Consequently, after the selection, I will have a list of POJORecipient objects and in each object filled only the field "name" and set of POJORequisite objects.
As answer of my question I want to discover one of next: how can I do that with help HQL or Criteria API (the second variant is preferable), or understand it is impossible in Hibernate at all, or that this possibility appeared in later versions (also preferably with example). I'm trying to resolve this question for several months now and will be immensely grateful for any help. All clarifications and advices also will be so helpful. Thanks in advance!!!
Course.java
package com.example.jpa_training.JPAD.model;
#Entity
#Table(name = "COURSE")
public class Course implements Serializable{
public Course() {}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
private String description;
#ManyToOne(targetEntity=Department.class)
#JsonIgnore
private Department department;
#ManyToMany(mappedBy="courses", targetEntity=Student.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JsonIgnore
private Set<Student> students = new HashSet<Student>();
#ManyToOne(cascade = CascadeType.MERGE)
#JoinColumn(name="professor_id")
#JsonManagedReference
private Professor professor;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Professor getProfessor() {
return professor;
}
public void setProfessor(Professor professor) {
this.professor = professor;
}
public Set<Student> getStudents() {
return students;
}
public void addStudent(Student student) {
this.students.add(student);
}
public void removeStudent(Student student) {
this.students.remove(student);
}
#OneToMany(mappedBy = "course", fetch = FetchType.LAZY)
private Set<Review> reviews;
}
Review.java
#Entity
public class Review implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long reviewId;
#ManyToOne
private Course course;
private String reviewDescription;
private double courseRating;
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
public String getReviewDescription() {
return reviewDescription;
}
public void setReviewDescription(String reviewDescription) {
this.reviewDescription = reviewDescription;
}
public double getCourseRating() {
return courseRating;
}
public void setCourseRating(double courseRating) {
this.courseRating = courseRating;
}
}
Postman Input
{
"course": {
"id": 4,
"name": "Data Analysis",
"description": "Just take it",
"professor": {
"name": "Kapil Dev",
"qualification": "M.Tech",
"department": {
"deptId": 1,
"deptName": "Big Data",
"buildingName": "DS-04"
}
}
},
"reviewDescription": "Good course, nice teaching",
"courseRating": 0.0
}
Error Log
Failed to evaluate Jackson deserialization for type [[simple type, class com.example.jpa_training.JPAD.model.Review]]: com.fasterxml.jackson.databind.JsonMappingException:
2020-12-30 11:45:00.869 WARN 11152 --- [nio-8080-exec-2] .c.j.MappingJackson2HttpMessageConverter : Failed to evaluate Jackson deserialization for type [[simple type, class com.example.jpa_training.JPAD.model.Review]]: com.fasterxml.jackson.databind.JsonMappingException:
2020-12-30 11:45:00.869 WARN 11152 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type
'application/json;charset=UTF-8' not supported]
Tried solutions
Using #JsonBackReference and #JsonManagedReference
Using #JsonIdentityInfo and #JsonIgnore
but the error is the same
I can save and retrieve the data from Java but when I send data over postman or using curl command I get the above error, I tried many ways but couldn't fix it
I wouldn't suggest exposing entities directly to your controller. Entities should only contain JPA annotations in your case. You can expose a DTO (Data Transfer Object) to your controller and then map the DTO to the corresponding entity.
ReviewDto
public class ReviewDto {
private String reviewDescription;
private double courseRating;
private CourseDto course;
// getters, setters, etc
}
CourseDto
public class CourseDto {
private Long id;
private String name;
private String description;
// professorDto, getters, setters, etc
}
An example demonstrating how your controller class will be
#RestController
public class DemoController {
private final ReviewDtoMapper reviewDtoMapper;
private final ReviewService reviewService;
public DemoController(ReviewDtoMapper reviewDtoMapper,
ReviewService reviewService) {
this.reviewDtoMapper = reviewDtoMapper;
this.reviewService = reviewService;
}
#PostMapping(value = "demo")
public ResponseEntity<String> postReview(#RequestBody ReviewDto reviewDto) {
final Review review = reviewDtoMapper.mapFrom(reviewDto);
reviewService.save(review);
return ResponseEntity.ok("");
}
}
The class to map from reviewDto to review entity and the opposite.
#Component
public class ReviewDtoMapper {
public ReviewDto mapTo(final Review entity) {
ReviewDto reviewDto = new ReviewDto();
reviewDto.setReviewDescription(entity.getReviewDescription());
// set all the properties you want
return reviewDto;
}
public Review mapFrom(ReviewDto dto) {
Review review = new Review();
review.setReviewDescription(dto.getReviewDescription());
// set all the properties you want
return review;
}
}
Of course, you have to make adjustments according to your needs.
If you like this way of doing things I would suggest you check
MapStruct, it will automatically make the mappers for you.
I have some JPA models: "Category" and "Article":
#Entity
#Table(name = "categories")
public class Category {
private int id;
private String caption;
private Category parent;
private List<Category> childrenList;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column
public String getCaption() {
return caption;
}
public void setCaption(String caption) {
this.caption = caption;
}
#ManyToOne
#JoinColumn(name = "parent_id")
public Category getParent() {
return parent;
}
public void setParent(Category parent) {
this.parent = parent;
}
#OneToMany
#JoinColumn(name = "parent_id")
public List<Category> getChildrenList() {
return childrenList;
}
public void setChildrenList(List<Category> childrenList) {
this.childrenList = childrenList;
}
}
#Entity
#Table(name = "articles")
public class Article {
private int id;
private String caption;
private boolean isAvailable;
private String description;
private int price;
private Category category;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Column
public String getCaption() {
return caption;
}
public void setCaption(String caption) {
this.caption = caption;
}
#Column(name = "is_available")
#Type(type = "org.hibernate.type.NumericBooleanType")
public boolean getIsAvailable() {
return isAvailable;
}
public void setIsAvailable(boolean available) {
isAvailable = available;
}
#Column
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Column
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
#ManyToOne
#JoinColumn(name = "category_id")
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
}
Also i have some REST controller with two methods:
1)In the first method i need to get and serialize last 10 Articles, but i don't need "childrenList" and "parent" field in Categegory.
2)In the second method i need to get the same but serialize "parent" field.
How can i solve this?
If i will use #JsonIgnore annotation to these fields then they will be never serialized.
Or should i use DTO classes?
How can i dynamically set field for ignoring?
I never use my Entitys for generating JSON, I think another set DTO classes will make you happier in the long run. My DTO typically has a constructor which takes the Entity as argument (it still needs a default constructor if you plan to use it for parsing incoming JSON).
If you really want to use your Entities, I would recommend that you use MixIns, which allows you to register a MixIn class, that augments the serialization of a specific class.
Here is a link to a MixIn example I made for another answer.
Use a custom serializer, the psedo code is below.
public class CategorySerializer extends StdSerializer<Category> {
public CategorySerializer() {
this(null);
}
public CategorySerializer(Class<Category> t) {
super(t);
}
#Override
public void serialize(Category value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
// put the logic here to write the parent and child value or not
// here is the example to how the data is serialized
jgen.writeStartObject();
jgen.writeNumberField("id", value.id);
jgen.writeStringField("caption", value.caption);
jgen.writeEndObject();
}
}
Now, to utilize the custom serializer put this annotation above your Catagory entity class.
#JsonSerialize(using = CategorySerializer.class)
I am using Hibernate 4.3.8.Final and have problem with retrieving #Id property of lazy fetched property: For attached classes calling aidConfiguration.getChipApplication().getId() allways returns null. Other properties, eg. aidConfiguration.getChipApplication().getVersion() returns correctly the value from DB. If chipApplication is not lazy loaded (see the comment in the code), then aidConfiguration.getChipApplication().getId() returns correct non-null value.
What am I dong wrong?
BTW I need it to be lazy.
BaseEntity:
#MappedSuperclass
public class BaseEntity implements Serializable {
#Id
#Column(name = "ID", unique = true)
#Size(min = 1, max = 255)
private String id;
#PrePersist
public final void generateUuid() {
if (this.getId() == null) {
this.setId(UUID.randomUUID().toString());
}
}
public final String getId() {
return id;
}
public final void setId(final String id) {
this.id = id;
}
}
AidConfiguration:
#Entity
#Audited
public class AidConfiguration extends BaseEntity {
#Column
#NotBlank
private String name;
#NotNull
#ManyToOne(fetch = FetchType.LAZY) // if it is EAGER (defaut) then then aidConfiguration.getChipApplication().getId() returns correctly non-null value
private ChipApplication chipApplication;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "aidConfiguration", cascade = CascadeType.ALL) // cascade for auto-saving and deleting items
private List<AidConfigurationItem> aidConfigurationItems;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public ChipApplication getChipApplication() {
return chipApplication;
}
public void setChipApplication(final ChipApplication chipApplication) {
this.chipApplication = chipApplication;
}
public List<AidConfigurationItem> getAidConfigurationItems() {
return aidConfigurationItems;
}
public void setAidConfigurationItems(final List<AidConfigurationItem> aidConfigurationItems) {
this.aidConfigurationItems = aidConfigurationItems;
}
}
ChipApplication:
#Entity
#Audited
public class ChipApplication extends BaseEntity {
#Column
#NotBlank(message = "Aid can not be empty")
private String aid;
#Column
#NotBlank(message = "Product can not be empty")
private String product;
#Column
#NotBlank(message = "Version can not be empty")
private String version;
#NotNull(message = "Network is mandatory")
#ManyToOne(fetch = FetchType.LAZY)
private Network network;
#ManyToMany(fetch = FetchType.EAGER)
private List<AidTag> aidTags;
public String getAid() {
return aid;
}
public void setAid(final String aid) {
this.aid = aid;
}
public String getProduct() {
return product;
}
public void setProduct(final String product) {
this.product = product;
}
public String getVersion() {
return version;
}
public void setVersion(final String version) {
this.version = version;
}
public Network getNetwork() {
return network;
}
public void setNetwork(final Network network) {
this.network = network;
}
public List<AidTag> getAidTags() {
return aidTags;
}
public void setAidTags(final List<AidTag> aidTags) {
this.aidTags = aidTags;
}
}
Bit late, but the issue HH-9588 is still unresolved, and I just had the same issue (XML mapping rather than annotations, though).
Could not get the id from the getter when the binding was lazy. Got it when eager or fetch join.
Fixed it by getting rid of the "final" modifier on the getId() accessor. (final here was an attempt to protect the way primary keys/identifiers are defined in the superclass for all the entities)
before :
public abstract class Foo {
Long id;
public final Long getId() {
return id;
}
protected final void setId( Long id ){
this.id = id;
}
...
after :
public abstract class Foo {
Long id;
// No more final
public Long getId() {
return id;
}
// No more final
protected void setId( Long id ){
this.id = id;
}
...
Now, I can get the Id with a lazy binding as well.
Seems to me that this "final" modifier does not allow Hibernate to proxy this accessor as intended. The other accessors being not "final", one can access their values from the proxy.
So, I wonder whether HH-9588 is really a bug or a misunderstanding of the hibernate ways ?
That seems a bug, if you do not miss anything. I would report it on Hibernate's bug tracking system. It would be nice if you would update this answer afterwards with a link to the bug.
This is my Controller method, i am trying to read my database by providing zip, cityname and province name.
#RequestMapping(value = "/retrieve", method = RequestMethod.GET)
public #ResponseBody String retrieveObjectThroughAjax(ModelMap model){
//Calling Service Method to read data according to zip,cityName and province provide
PropertyItems propertyItems=getPropertyTypeandAddressService.readAddressFromZip("H2H-
2N3","Montreal","Quebec");
Gson gson = new Gson();
String json = null;
try{
json = gson.toJson(propertyItems); // serializing object
}catch(Exception e){
logger.error(Constants.METHOD_INSIDE_MESSAGE +"getAuthors",e);
}
logger.debug(json);
return json;
}
}
Service Method
#Service
public class GetPropertyTypeandAddressServiceImpl implements GetPropertyTypeandAddressService{
#Autowired
private GetPropertyTypeandAddressDAO getPropertyTypeandAddressDAO;
#Transactional
public PropertyItems readAddressFromZip(String zipCode,String cityName,String provinceName){
PropertyItems propertyItems=getPropertyTypeandAddressDAO.getAddressFromZip(zipCode, cityName, provinceName);
Hibernate.initialize(propertyItems);
return propertyItems;
}
}
DAO Method
#Repository
public class GetPropertyTypeandAddressDAOimp implements GetPropertyTypeandAddressDAO{
#Autowired
private SessionFactory sessionFactory;
#Override
public PropertyItems getAddressFromZip(String zipCode,String cityName,String provinceName) {
PropertyItems propertyitems = new PropertyItems();
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(PropertyItems.class,"propertyItemsClass");
if(zipCode != null){
criteria.createAlias("propertyItemsClass.address","address");
criteria.add(Restrictions.eq("address.zip",zipCode));
List<PropertyItems> propertyitem = criteria.list();
if(propertyitem.size()>0){
propertyitems = propertyitem.get(0);
}
}
else if(cityName != null){
criteria.createAlias("propertyItemsClass.address","address");
criteria.add(Restrictions.eq("address.city","city"));
criteria.add(Restrictions.eq("city.cityname",cityName));
List<PropertyItems> propertyitem = criteria.list();
if(propertyitem.size()>0){
propertyitems = propertyitem.get(0);
}
}
else if(provinceName != null){
criteria.createAlias("propertyItemsClass.address","address");
criteria.add(Restrictions.eq("address.city","city"));
criteria.add(Restrictions.eq("city.provinces","provinces"));
criteria.add(Restrictions.eq("provinces.provinceName",provinceName));
List<PropertyItems> propertyitem = criteria.list();
if(propertyitem.size()>0){
propertyitems = propertyitem.get(0);
}
}
return propertyitems;
}
}
Console Error
09:53:56,988 ERROR HelloController:567 - Inside Method: getAuthors org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.agilemaple.common.entity.Property.propertyType, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
As requested my Property Items Look like this
Entity:
Propert Items
#Entity
#Table(name="web_property_item")
public class PropertyItems {
#Id
#GeneratedValue
private Integer id;
private String name;
#ManyToOne
#JoinColumn(name="property_type_id")
private PropertyType propertyType;
#OneToOne(mappedBy="propertyItems",cascade=CascadeType.ALL)
private Address address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public PropertyType getPropertyType() {
return propertyType;
}
public void setPropertyType(PropertyType propertyType) {
this.propertyType = propertyType;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
Entity : Property Type
#Entity
#Table(name="web_property_type")
public class PropertyType {
#Id
#GeneratedValue
private Integer id;
private String name;
#ManyToOne
#JoinColumn(name="property_id")
private Property property;
#OneToMany(fetch = FetchType.LAZY,mappedBy="propertyType", cascade=CascadeType.ALL)
private Set<PropertyItems> propertyItems;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Property getProperty() {
return property;
}
public void setProperty(Property property) {
this.property = property;
}
public Set<PropertyItems> getPropertyItems() {
return propertyItems;
}
public void setPropertyItems(Set<PropertyItems> propertyItems) {
this.propertyItems = propertyItems;
}
}
The problem in hibernate. Your field Set of properties has Lazy fetch method, it means that it will try to get when you call method get of this set. When u calling tojson methods, gson calls all get methods of object but in this moment hibernate session is close and hibernate can't open it in controller. I've faced with the same problem but directly on JSP. In a three weeks i resolved it by one more property for hibernate ( in your case) and I write code to opening session in view interceptor. I'm underground just right now, so I can't show property, but in a hour I will edit this answer and add property.
Added:
I remembered ! property is: hibernate.enable_lazy_load_no_trans = true
If it won't help, I will add code of opensessioninviewinterceptor.
#Override
public void addInterceptors(InterceptorRegistry registry) {
OpenSessionInViewInterceptor sessionInViewInterceptor = new OpenSessionInViewInterceptor();
sessionInViewInterceptor.setSessionFactory(sessionFactory());
}