-2

I am getting a lazy initialization exception that I don't understand...

I work with Java, Hibernate, Spring and Wicket.

So, from the save method of the Form (extends wicket Form) I get a LazyInitializationException when accesing a colletion of an object, but right away I can access another collection of the same object which has the same "configuration" as the collection that fires the exception:

Here is the code in the Form:

therapyGroup.getTherapies().clear();
therapyGroup.getTherapies().addAll(therapiesOldGroup);
therapyGroup.getToxicities().add(lastTherapy.getToxicity());

And here the part where the collections are defined in the class:

@OneToMany(mappedBy = "therapyGroup", fetch = FetchType.LAZY, orphanRemoval=true)
@Cascade(value = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.DELETE, CascadeType.SAVE_UPDATE })
@OrderBy(value = "date asc")
@Filters( { @Filter(name = "deletedFilter", condition = "deleted <> :deletedParam") })
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "TherapyGroup")
@Lazy
public Set<Therapy> getTherapies() {
    return therapies;
}


@OneToMany(mappedBy = "therapyGroup", fetch = FetchType.LAZY, orphanRemoval=true)
@Cascade(value = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.DELETE, CascadeType.SAVE_UPDATE })
@OrderBy(value = "date asc")
@Filters( { @Filter(name = "deletedFilter", condition = "deleted <> :deletedParam") })
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "TherapyGroup")
@Lazy
public Set<Toxicity> getToxicities() {
    return toxicities;
}

The "Problematic" collection is the toxicities collection. If I swap the order and call toxicities first, it also throws the LazyInitializationException. The exception is always fired by the toxicities and not by the therapies... why?

EDIT: Here's the stack trace

Root cause:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mycompany.myapp.data.TherapyGroup.toxicities, 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.PersistentSet.add(PersistentSet.java:212)
at com.mycompany.myapp.web.support.therapyend.TherapyEndSupportForm.onSaveFormData(TherapyEndSupportForm.java:135)
at com.mycompany.myapp.web.base.BaseForm.doSave(BaseForm.java:370)
at com.mycompany.myapp.web.base.BaseForm.saveAndTrigger(BaseForm.java:1137)
at com.mycompany.myapp.web.base.BaseForm.switchModalWindow(BaseForm.java:1128)
at com.mycompany.myapp.web.base.BaseForm.switchModalWindow(BaseForm.java:1077)
at com.mycompany.myapp.web.base.BaseForm.onSubmit(BaseForm.java:567)
at com.mycompany.myapp.web.comp.QuasiAjaxSubmitButton.onSubmit(QuasiAjaxSubmitButton.java:49)
at com.mycompany.myapp.web.comp.QuasiAjaxButton$1.onSubmit(QuasiAjaxButton.java:65)
at com.mycompany.myapp.web.comp.QuasiAjaxFormSubmitBehavior.onEvent(QuasiAjaxFormSubmitBehavior.java:151)
at org.apache.wicket.ajax.AjaxEventBehavior.respond(AjaxEventBehavior.java:177)
at org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.onRequest(AbstractDefaultAjaxBehavior.java:286)
at org.apache.wicket.request.target.component.listener.BehaviorRequestTarget.processEvents(BehaviorRequestTarget.java:119)
at org.apache.wicket.request.AbstractRequestCycleProcessor.processEvents(AbstractRequestCycleProcessor.java:92)
at org.apache.wicket.RequestCycle.processEventsAndRespond(RequestCycle.java:1250)
at org.apache.wicket.RequestCycle.step(RequestCycle.java:1329)
at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1428)
at org.apache.wicket.RequestCycle.request(RequestCycle.java:545)
at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:479)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:312)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1139)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:113)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1139)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:378)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:535)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:880)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:747)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:520)

com.mycompany.myapp.web.support.therapyend.TherapyEndSupportForm.onSaveFormData(TherapyEndSupportForm.java:135) is the line where I call therapyGroup.getToxicities().add(lastTherapy.getToxicity());

diminuta
  • 1,545
  • 8
  • 32
  • 55
  • 1
    there is another call in the same line: lastTherapy.getToxicity(). Are you sure that this is not the issue? – kostja Jun 18 '14 at 15:41
  • 1
    Without the complete stack trace, including all the "Caused By" sections this question cannot be answered. Just yesterday I saw this exact exception where the "Caused By" showed the database connection failed, i.e. the cause was unrelated to the code. This may not be your problem, but unless we can see the whole stack trace the answer could be anything. – Jim Garrison Jun 18 '14 at 15:46
  • I have added the complete stack trace. – diminuta Jun 18 '14 at 16:00
  • 2
    The why is quite clinical: apparently the therapies collection is already loaded when you reference it outside of the session in which it was fetched, and the toxicities collection is not. In any case you're trying to use a detached entity without making it managed again first; that's the base for this incredibly well documented exception that anyone using Hibernate runs into. Its expected behavior and quite logical once you research the how and why behind it. – Gimby Jun 18 '14 at 16:06
  • Ok Gimby, and how I make it managed? – diminuta Jun 18 '14 at 16:09
  • @Gimby: You have a link where is't incredibly well documented (or rather: incredibly well *explained* for first-time users of Hibernate)? :-) – Aaron Digulla Jun 19 '14 at 07:02
  • That would most likely be an illegal download, good documentation exists in books and rarely on the internet. EDIT: but this little blog at least gives a simple demonstration: http://javarevisited.blogspot.nl/2014/04/orghibernatelazyinitializationException-Could-not-initialize-proxy-no-session-hibernate-java.html . That was 1 minute of google effort, imagine what more there is to find. – Gimby Jun 19 '14 at 07:11
  • Oh god, I had no idea that google existed... But I have already read that valuable document you are linking... The problem here is that the two collections are read for the first time in that piece of code that belongs to a method in the Form. That method doesn't have a session management, I mean, I don't open or close a session voluntarily... And I don't want toxicities to be fetched eagerly. That's why I have asked here, if I had found a solution over google I wouldn't have asked... I think that is what this site is for. But forgive me sir for wasting your precious time. – diminuta Jun 19 '14 at 08:17

2 Answers2

1

Set a breakpoint in both methods. When you run the code, you'll see that somewhere, getTherapies() is called inside of a transaction. That means that you have a collection there and Hibernate will use that instead of trying to load it from the database when you call the method inside of save().

The same isn't true for the getToxicities(). So Hibernate tries to load it but there is no current transaction, so the loading fails. So make sure save() gets a transaction from somewhere. Maybe you forgot an annotation somewhere?

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
0

I use to get this kind of exception when I forgot to write the @Transaction annotation in my service Classes.

stephane06
  • 261
  • 1
  • 4
  • 12