Issue
Hope you'll be able to help me stop hitting my head against a wall.
Here's my problem, after plenty days of research on many forums, I didn't found any compatible answer with the problem I'm encountering.
I have the org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.supinfo.suppicture.entity.User.pictures, no session or session was closed
that seems to be a known Exception, but still drives me crazy...
I've tried to force Eager loading instead of lazy loading but still having the same issue.
Here are my classes:
category.java
@Entity
@Table(name = "category")
@XmlRootElement
public class Category{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String Name;
@OneToMany(mappedBy = "category")
private Collection<Picture> pictures;
(getters and setters)
user.java
@Entity
@Table(name = "user")
@XmlRootElement
public class User {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String username;
private String password;
private String firstName;
private String lastName;
private String phoneNumber;
private String postalAddress;
private String email;
@OneToMany(mappedBy = "author")
private Collection<Picture> pictures;
(getters and setters)
picture.java
@Entity
@Table(name = "picture")
@XmlRootElement
public class Picture {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
private String description;
@Column(columnDefinition="longblob")
private byte[] image;
private Date dateOfPublish;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "category_id")
private Category category;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
private User author;
(getters and setters)
And here is an example of how I try to retrieve my pictures in database (which is the only one that have foreign keys)
@Override
public List<Picture> getAllPictures() {
EntityManager em = emf.createEntityManager();
try {
CriteriaQuery<Picture> criteriaQuery = em.getCriteriaBuilder()
.createQuery(Picture.class);
criteriaQuery.from(Picture.class);
return em.createQuery(criteriaQuery).getResultList();
} finally {
em.close();
}
}
Finally called like this:
@Path("/picture")
public class PictureController {
@GET
@Path("/all") @Produces(MediaType.APPLICATION_JSON)
public List<Picture> getAllPictures(){
return DaoFactory.getPictureDao().getAllPictures();
}
Full stacktrace of exception below:
févr. 03, 2019 4:38:48 PM org.hibernate.LazyInitializationException GRAVE: failed to lazily initialize a collection of role: com.supinfo.suppicture.entity.User.pictures, no session or session was closed org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.supinfo.suppicture.entity.User.pictures, no session or session was closed at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383) at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375) at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368) at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111) at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:272) at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.iterator(Lister.java:266) at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.iterator(Lister.java:253) at com.sun.xml.internal.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:118) at com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:144) at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:345) at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681) at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143) at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:345) at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:578) at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:326) at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:479) at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308) at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:163) at com.sun.jersey.json.impl.provider.entity.JSONListElementProvider.writeList(JSONListElementProvider.java:145) at com.sun.jersey.core.provider.jaxb.AbstractListElementProvider.writeTo(AbstractListElementProvider.java:264) at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:306) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1448) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1360) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1350) at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:538) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:716) at javax.servlet.http.HttpServlet.service(HttpServlet.java:725) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1081) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1566) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1523) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748)
févr. 03, 2019 4:38:48 PM org.apache.catalina.core.StandardWrapperValve invoke GRAVE: "Servlet.service()" pour la servlet jersey-servlet a généré une exception org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.supinfo.suppicture.entity.User.pictures, no session or session was closed at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383) at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375) at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368) at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111) at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:272) at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.iterator(Lister.java:266) at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.iterator(Lister.java:253) at com.sun.xml.internal.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:118) at com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:144) at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:345) at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681) at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143) at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:345) at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:578) at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:326) at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:479) at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308) at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:163) at com.sun.jersey.json.impl.provider.entity.JSONListElementProvider.writeList(JSONListElementProvider.java:145) at com.sun.jersey.core.provider.jaxb.AbstractListElementProvider.writeTo(AbstractListElementProvider.java:264) at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:306) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1448) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1360) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1350) at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:538) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:716) at javax.servlet.http.HttpServlet.service(HttpServlet.java:725) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1081) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1566) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1523) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748)
Solution
Let divide this step by step
1) Your jersey web controller is calling your dao method to get list of pictures (No error)
2) Now your dao layer is getting data from database (No error)
3) Value is returned to your web service controller method (No error)
4) But you are using automatic json converter to convert object data to json. Your pictures has data associated with user. When json converter tries to get data of user the value is null because your transaction has already ended which is resulting in exception. Try ignoring category and user fields during json conversion as shown below.
@JsonIgnore
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "category_id")
private Category category;
@JsonIgnore
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
private User author;
5) You should not use the picture object directly for json conversion as it will result in cyclic redundancy (infinite loop). Try to create another wrapper class of picture to handle this scenario
Picture -> User -> Picture -> User (Cyclic redundancy)
So for fixing this create three wrapper classes
public class PictureWrapper
{
private int id;
private String name;
private String description;
private byte[] image;
private Date dateOfPublish;
private CategoryWrapper category;
private UserWrapper author;
}
public class UserWrapper
{
private int id;
private String username;
private String password;
private String firstName;
private String lastName;
private String phoneNumber;
private String postalAddress;
private String email;
}
public class CategoryWrapper
{
private int id;
private String Name;
}
Then change getAllPictures method to following
public List<PictureWrapper> getAllPictures()
{
List<PictureWrapper> resultList = new ArrayList<PictureWrapper>();
EntityManager em = emf.createEntityManager();
try
{
CriteriaQuery<Picture> criteriaQuery = em.getCriteriaBuilder().createQuery(Picture.class);
criteriaQuery.from(Picture.class);
List<Picture> list = em.createQuery(criteriaQuery).getResultList();
if(list != null && list.size() != 0)
{
for(Picture picture : list)
{
PictureWrapper pictureWrapper = new PictureWrapper();
//Load data from picture to picture wrapper with user and category
resultList.add(pictureWrapper);
}
}
}
finally
{
em.close();
}
return resultList;
}
Answered By - Santosh Balaji
Answer Checked By - David Marino (JavaFixing Volunteer)