Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LazyLoadingException when using @ElementCollection #36

Closed
CalamarBicefalo opened this issue Jun 7, 2013 · 13 comments
Closed

LazyLoadingException when using @ElementCollection #36

CalamarBicefalo opened this issue Jun 7, 2013 · 13 comments

Comments

@CalamarBicefalo
Copy link

When using javax.persistence.ElementCollection and hibernate 4.2.1.Final I get the undesirable LazyLoadingException.

Anyway, Is ElementCollection supported by jackson-module-hibernate? Is it a known bug? Or something is wrong with my project?

NOTE: As far as i could guess proxys are quite similar in both ordinary @OneToMany collection and @ElementCollection. Anyway, using value types is quite a good practice in order to achieve data integrity and adjust life cycle of child attributes.

@CalamarBicefalo
Copy link
Author

I've been debugging and I guess Jackson is receiving an org.hibernate.collection.internal.PersistentMap (my collection is a map) when looking for a serializer. As far as I understood (asuming I'm completely lost) jackson expects org.hibernate.proxy.HibernateProxy in order to let jackson-hibernate-module serialize the bean.

Anyway as I said Both Jackson and jackson-hibernate-module are quite dificult to me, just to try...

Thank you for your amazing work.

@cowtowncoder
Copy link
Member

Quick question: are you using version 2.2.2?

The problem on my end is that I do not use Hibernate. So I can run (and modify unit tests), but my knowledge and experience are somewhat limited. Unit tests fortunately do set up reasonable test setup, so if it is possible to replicate this issue with them, I may be able to help.

@CalamarBicefalo
Copy link
Author

I was using 2.2.1, but in order to provide some feedback I've just upgraded to 2.2.2 through maven repository. Unfortunately, It still throws LazyLoadingException when serializing a @ElementCollection.

I've just used Hibernate as ORM provider, so I can't say anything about other persistence providers, I'm really sorry. Anyway since JPA 2 ElementCollection is included in the specification, and Hibernate implements it properly. If i'm not wrong it is similar to the old CollectionOfElements of Hibernate.

I'm going to try a bit more, if I make some guess I'll let you know.

Thank you very much for your interest!

@CalamarBicefalo
Copy link
Author

With @ElementCollection:

  • When using @ElementCollection over a java.util.List and the list is wrapped with hibernate proxy (still uninitialized) jackson sees it as a org.hibernate.collection.internal.PersistentBag when looking for a serializer and the serializer it uses to get the work done is com.fasterxml.jackson.databind.ser.std.CollectionSerializer.
  • When using @ElementCollection over a java.util.Map and the list is wrapped with hibernate proxy (still uninitialized) jackson sees it as a org.hibernate.collection.internal.PersistentMap when looking for a serializer and the serializer it uses to get the work done is com.fasterxml.jackson.databind.ser.std.MapSerializer.
    • Both cases fail when invoking serializer.serialize()

If i change @ElementCollection with @OneToMany:

  • Using a List is similar but in this case Serializer is com.fasterxml.jackson.datatype.hibernate4.PersistentCollectionSerializer which ends with a proper serializer.serialize()
  • Using a Map is similar but in this case Serializer is com.fasterxml.jackson.datatype.hibernate4.PersistentCollectionSerializer which ends with a proper serializer.serialize()

I can understand than for some reason jackson is not getting the proper serializer while using ElementCollection, but although I've tried I don't really understand how Jackson choose each serializer for each property.

I'm sorry but I can't say much more. Thank you (and apologize my english, Im not native speaker)

@cowtowncoder
Copy link
Member

No prob wrt only using Hibernate -- Hibernate module only supports Hibernate really. I am just saying that I am not necessarily the person that can fix this. This is why discussing this also on Jackson dev list would help; to make sure other Hibernate users/devs can help. We of course want to make sure this but entry has all the necessary info, but not everyone follows updates to tickets here.

As to checking how typing works: the thing is that Jackson tries to find serializer as soon as it knows for sure what the type is. This may be possible when only considering nominal type (without context); or when context is known (which POJO contains property that refers to value); or during runtime. So there are multiple code paths involved. There is also the possibility of proxy being used, and finally, checks for types may be incomplete (like: maybe Bags are not recognized as Hibernate types same way as Collections are?).
Further, handling of Maps (key/values to JSON Objects) and Collections differs (sequences of values to JSON Arrays).
So it is possible that difference is due to one or more code paths not doing all the checks.

I hope to have a look at this later on: but what would be REALLY useful would be to have unit tests to point this.
If you had any chance to try to modify existing unit tests, I would have much bigger chance of fixing the underlying issue. If not, fix will probably be found eventually, but will just take longer.

Thank you again for your help in explaining what you see; these are complicated problems to resolve (due to multiple systems interacting). But this is the only way to make sure Jackson is the best tool for handling JSON on JVM platform.

@cowtowncoder
Copy link
Member

I wonder fix for #39 by @drvdijk might help here too...

@szmeti
Copy link

szmeti commented Oct 18, 2013

I have also encountered this issue. It seems to happen when I have a Set of Strings as an ElementCollection. After doing some debugging, the issue seems to be in PersistentCollectionSerializer. It has a method called usesLazyLoading, but it does not handle the case when we have an ElementCollection (and therefore thinks we want to do eager fetching), so createContextual just returns the underlying serializer, which in this case is StringCollectionSerializer.

@cowtowncoder
Copy link
Member

Oh. So the problem here being that instead of checking super-classes for inheritance, there would need to be additional checking for annotations to realize lazy-loading nature of collections as per @ElementCollection.
That explains it.

One modelling challenge here is that all annotation access by Jackson is designed to go through AnnotationIntrospector. In this case need is for a specific (kind of) annotation. So there's the question of whether to add a method in AnnotationIntrospector, or to do it using module-specific mechanism. There are pros and cons to each approach.

@cowtowncoder
Copy link
Member

Ah. Never mind -- we already do direct annotation access from PersistentCollectionSerializer. So what is needed is just one more annotation to check.

In future it may still make sense to make "lazy-loaded-ness" a globally discoverable property via AnnotationIntrospector, so that it can both be used by other modules AND provided by alternative means, but for now there is no need.

@cowtowncoder
Copy link
Member

@CalamarBicefalo one more question: I can easily add detection for @ElementCollection (and will do so). My only concern is whether this is enough; that is, whether collection will be of type PersistentCollection or not. I assume it is, for now, and will check the fix in. But I'd need someone to verify it with a real example; I don't trust that I can replicate it correctly with a unit test (since I don't use Hibernate). Help with unit test would be greatly appreciated of course!

@cowtowncoder
Copy link
Member

Ok -- I will assume this is enough to fix the issue. Will be resolved for 2.2.4 (if such is released), and 2.3.0 which should be out in couple of weeks (first RC in 2 weeks).

@szmeti
Copy link

szmeti commented Oct 19, 2013

When I was debugging it, it was a PersistentSet, which is a PersistentCollection, so I think it should be enough.

@cowtowncoder
Copy link
Member

Ok. I think this should work then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants