Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Using Eclipselink with Streams in parallel gives NullPointerException
Using Eclipselink with Streams in parallel gives NullPointerException [message #1828297] Sat, 06 June 2020 09:31 Go to next message
Dave Griffiths is currently offline Dave GriffithsFriend
Messages: 7
Registered: February 2010
Junior Member
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 #1828383 is a reply to message #1828297] Mon, 08 June 2020 20:03 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1388
Registered: July 2009
Senior Member
An EntityManager is not thread safe, and neither are the instances read from them. Each process should have its own EntityManager instance to read an instance it needs to work with from; If using the shared cache, these will just be copies of the shared data, which will handle concurrent fetches of the shared data for you.

Otherwise, you are responsible for ensuring the data is fetched by only a single process. This might mean using a fetch group to ensure what the processes may need is preloaded before being 'shared' or cached, or putting synchronization lookups over methods that might be fetching lazy data.
Re: Using Eclipselink with Streams in parallel gives NullPointerException [message #1828386 is a reply to message #1828383] Mon, 08 June 2020 21:56 Go to previous messageGo to next message
Dave Griffiths is currently offline Dave GriffithsFriend
Messages: 7
Registered: February 2010
Junior Member
Hi, thanks for replying. We can look at preloading but then we would lose the parallelism. As far as I know it is not possible to make the methods involved with fetching lazy data synchronous because that is all handled by the bytecode weaving. For instance the "getFamily" method in Person is auto-generated. Even if we could make it synchronised, that would be at the Person object level - the synchronisation needs to be deep inside the persistence code at the Family level and from what you're saying that's never going to happen.

I'd hoped that there was some way of making each Person object exist in its own Unit Of Work but then I guess to do that you'd lose the benefits of the nice weaving and lazy loading.

Cheers,

David
Re: Using Eclipselink with Streams in parallel gives NullPointerException [message #1828438 is a reply to message #1828386] Tue, 09 June 2020 15:42 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1388
Registered: July 2009
Senior Member
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 15:50]

Report message to a moderator

Re: Using Eclipselink with Streams in parallel gives NullPointerException [message #1828470 is a reply to message #1828438] Wed, 10 June 2020 11:15 Go to previous messageGo to next message
Dave Griffiths is currently offline Dave GriffithsFriend
Messages: 7
Registered: February 2010
Junior Member
Hi, I'm probably not explaining it well. We have Thread A accessing Person A and Thread B accessing Person B. Both Person A and Person B point to the same Family F. The problem is that the getFamily logic that is responsible for instantiating the common Family object is implemented by the eclipselink persistence weaving code. It is not something we have control over.

But thanks for the advice - it sounds like we should be prefetching as you suggest.

Cheers,

David
Re: Using Eclipselink with Streams in parallel gives NullPointerException [message #1828541 is a reply to message #1828470] Thu, 11 June 2020 16:22 Go to previous message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1388
Registered: July 2009
Senior Member
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.
Previous Topic:How to validate JSON with Moxy on marshaling/unmarshaling?
Next Topic:EntityGraph not working in GlassFish
Goto Forum:
  


Current Time: Thu Jun 24 19:48:29 GMT 2021

Powered by FUDForum. Page generated in 0.02039 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top