Using Eclipselink with Streams in parallel gives NullPointerException [message #1828297] |
Sat, 06 June 2020 05:31  |
Eclipse User |
|
|
|
We have an application that uses Eclipselink weaving with JPA. Let's say we have a Family object that has a one to many relationship with a Person object. We retrieve a set of Person objects from the database and then use Java 8 Streams and a spliterator to process the Person objects in parallel. We end up getting a NullPointerException which from poking around in the Eclipselink code appears to have been caused by two threads operating on different Person objects but trying to instantiate the same Family clone object at the same time (in buildObjectInUnitOfWork).
It appears from googling that Eclipselink using weaving and lazy loading in this manner is not thread safe, is that correct? If so, what's the best way of handling this whilst still retaining some degree of parallelisation?
Thanks,
David
|
|
|
|
|
Re: Using Eclipselink with Streams in parallel gives NullPointerException [message #1828438 is a reply to message #1828386] |
Tue, 09 June 2020 11:42   |
Eclipse User |
|
|
|
I don't follow the person/family level synchronization issue. If the problem is accessing indirection within Person on multiple threads concurrently, synchronizing on person fixes that. Add accessors to wrap the getFamily method that your application uses, store the getFamily result in person (transient Family fetchedFamily; // for example), and just use synchronization on getFamily or on 'this' when calling getFamily if fetchedFamily is null. Multiple threads trying to get the family concurrently wait for one to fetch/build it before seeing it is there and just use it, and you avoid synchronization if it was already fetched.
As for prefetching - this depends on how you are looking at that object graph. In my current project, we have long lived caches, and the cost of fetching 'anything' during the processing is quite high compared to the processing itself. Having to sometimes delay to fetch a family is a non-starter for us; it needs dependable, predictable performance that necessitates building it upfront before starting. If you don't want the synchronization costs in your application, you might decouple the person->family relationship, and have it accessed separately from the object graph - something that fetches it from a separate cache (and EntityManager) when needed. Multiple concurrent threads looking up a person's family can then be handled how ever you need without adding synchronization or having concurrent access issues on the getFamily lazy indirection being triggered.
[Updated on: Tue, 09 June 2020 11:50] by Moderator
|
|
|
|
Re: Using Eclipselink with Streams in parallel gives NullPointerException [message #1828541 is a reply to message #1828470] |
Thu, 11 June 2020 12:22  |
Eclipse User |
|
|
|
I don't know how these same object could have been read in without a single point. As mentioned, EntityManagers and the object read from them are not thread safe, so PersonA and PersonB coming from the same EM still cannot be used in multiple threads. If PersonA and PersonB come from different EntityManagers, they should have a different view/instance of FamilyF, so there shouldn't be a concurrency issue.
Prefetching should resolve the issue regardless though, and offer performance improvements if you know you need the family fetched anyway.
|
|
|
Powered by
FUDForum. Page generated in 0.04829 seconds