1

I am using Spring MVC, AJAX/JSON and Hibernate to get all persons from a MySQL database. I wrote JUnit integration tests to verify my service and all is okay.

Now I call it in this kind:

@RequestMapping(value="/allpersons", method=RequestMethod.GET)
public @ResponseBody Set<Person> getAllPersons() {
    Set<Person> persons= new PersonServiceImpl().getAllPersons();
    return persons;
}

I debugged it. The line with

return persons;

everything is fine. I have a HashSet with all persons in it. Debugging more steps, I come to this line:

this.objectMapper.writeValue(jsonGenerator, o);

in

org.springframework.http.converter.json.MappingJacksonHttpMessageConverter

Then I do not see the source code, but my debugger tells me:

StdSerializerProvider._serializeValue(JsonGenerator, Object) line 297

After this line, I get the error:

ERROR: org.hibernate.LazyInitializationException - failed to lazily initialize a collection of role: com.mydomain.project.dom.Person.projects, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mydomain.project.dom.Person.projects, 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.PersistentSet.iterator(PersistentSet.java:186)
    at org.codehaus.jackson.map.ser.ContainerSerializers$CollectionSerializer.serializeContents(ContainerSerializers.java:339)
    at org.codehaus.jackson.map.ser.ContainerSerializers$CollectionSerializer.serializeContents(ContainerSerializers.java:314)
    at org.codehaus.jackson.map.ser.ContainerSerializers$AsArraySerializer.serialize(ContainerSerializers.java:112)
    at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:268)
    at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:160)
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:131)
    at org.codehaus.jackson.map.ser.ContainerSerializers$CollectionSerializer.serializeContents(ContainerSerializers.java:363)
    at org.codehaus.jackson.map.ser.ContainerSerializers$CollectionSerializer.serializeContents(ContainerSerializers.java:314)
    at org.codehaus.jackson.map.ser.ContainerSerializers$AsArraySerializer.serialize(ContainerSerializers.java:112)
    at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:297)
    at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:224)
    at org.codehaus.jackson.map.ObjectMapper.writeValue(ObjectMapper.java:1030)
    at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.writeInternal(MappingJacksonHttpMessageConverter.java:153)
    at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:181)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.writeWithMessageConverters(AnnotationMethodHandlerAdapter.java:975)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.handleResponseBody(AnnotationMethodHandlerAdapter.java:933)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.getModelAndView(AnnotationMethodHandlerAdapter.java:882)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:428)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
    at org.tuckey.web.filters.urlrewrite.NormalRewrittenUrl.doRewrite(NormalRewrittenUrl.java:195)
    at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:159)
    at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:141)
    at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:90)
    at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:417)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:619)

It seems, that is has something to do with the serialization / JacksonMapping. It wants to get the associated projects of a person, which are not needed and they are normally lazily loaded.

What's the problem here?

Thank you in advance & Best Regards.

4
  • 1
    there are about a million results for this problem. Both on SO and in google. Commented Dec 7, 2010 at 14:43
  • because it has to serialize the whole object hierarchy Commented Dec 7, 2010 at 14:58
  • How can I avoid this? I do not want that this will try to fetch more data? The fetch type should be lazy, not eager. Commented Dec 7, 2010 at 15:00
  • Problem with this not working by default is that Jackson would need to have good understanding of a third party library (hibernate) to be able to do special handling -- basic procedure is to follow the properties, serialize. Commented Dec 10, 2010 at 18:54

4 Answers 4

8

What you encounter is similar with this: Lazy Loading error

In a nutshell, you are accessing a lazy-loaded collection outside the Hibernate Session.

Possible solutions:

  • fetch it eagerly
  • make sure your Hibernate Session is still open at the point where you access the collection. You can use OpenSessionInView filter. That in itself may not be enough, as Hibernate may end your session where you close your transaction. So you will need to extend your transaction scope or find a way to prevent Hibernate to close the session upon transaction end.
  • make sure you access the lazy-loaded collection inside your transaction, to make sure Hibernate loads it.

Please check the post specified above for further details.

UPDATE 1 From what I've understood, this is caused by the Jackson mapper receiving a model that wasn't completely loaded (some collections are lazy loaded). You're saying you don't need the objects in those collections to be mapped by Jackson. The alternatives I'm seeing are:

  • Give Jackson a correct model, simple POJOs created based on your Person objects, containing only the information you want to map with Jackson. So, instead of giving Jackson a list of Persons, you'll give it a list of PersonDetails (or however you want to call them)
  • Configure Jackson to ignore that collection - not sure whether that's possible

Hope this helps.

Sign up to request clarification or add additional context in comments.

6 Comments

I encapsulated all in my Dao class when I have fetched all my needed data. The serialization is done in the last step and I do not have control of that.
You could, inside your transaction, explicitly access the projects collection, to force Hibernate to load it. Otherwise, your transaction will end, the Hibernate Session gets closed and when the mapper tries to access that collection it will fail as there is no way to fetch the collection as the session has been already closed..
I want to load it lazily. I do not need the projects while loading the persons. So, what is the best way to solve this? Should I stop getting domain objects with the ORM Hibernate and only get data which I really need (in this case only firstname and lastname) or how do professional Java programmer handle this?
It looks like the model you're returning isn't suited for the rendering operation you desire. I'd say instead of returning incomplete Person objects, create a POJO used only for rendering. This POJO can be created explicitly by you, so the JSON mapper won't try to access things it shouldn't access. The alternative would be to configure Jackson to not access that particular collection (haven't used Jackson so I don't know whether that's possible)
So I should crete besides the Person.java which is mapped with the database, a PersonPojo.class where I put all the values of the Person.java into the PersonPojo.java? Or how can I handle this?
|
2

While this does not immediately help you with the easy, it may be good to know that there is a new Jackson-related project, jackson-module-hibernate (at GitHub) that aims to solve this problem along with other commonly problematic use cases.

But on short term, you might find this article useful: http://kyrill007.livejournal.com/2577.html

2 Comments

I also saw it a few days ago. I will go the way with POJOs and then, if it more stable, I will switch to such a solution. But thanks a lot for this helpful comment!
No problem. I hope it'll work, Jackson + Hibernate is such a potentially good combination, would be shame it it was hard to make working properly.
2

If you don't want to map in you're JSON object the field which is linked in hibernate relation, you can add annotation "@JsonIgnore" in your model class :

@JsonIgnore
@OneToMany(mappedBy = "person")
private List<ProjectEntity> projects = new ArrayList<ProjectEntity>();

Comments

0

Use this. This has worked for me.

Jackson Module for Hibernate, https://github.com/FasterXML/jackson-datatype-hibernate/blob/master/README.md

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.