Skip to content
This repository has been archived by the owner on Oct 7, 2019. It is now read-only.

Demonstrate solution for lazy-loading #33

Closed
glassfishrobot opened this issue Oct 13, 2013 · 9 comments
Closed

Demonstrate solution for lazy-loading #33

glassfishrobot opened this issue Oct 13, 2013 · 9 comments

Comments

@glassfishrobot
Copy link

In the application some JPA relations are one-to-many and by default lazy loaded. When fetching the aggregate-root through the repository the returned root object will be detatched. Eclipselink handles this for read operations but Hibernate would throw a LazyInitializationException.

A traditional solution would be to add methods to a DAO such as loadCargoWithLoadedLegs();
With a lot of lazy collections and many combinations this would quickly be a bloated interface.

As a developer I would like to fetch the root, access and make changes to any object in graph, then store the root and have all changes persisted.

@glassfishrobot
Copy link
Author

Reported by danpeter

@glassfishrobot
Copy link
Author

Was assigned to reza_rahman

@glassfishrobot
Copy link
Author

reza_rahman said:
Would you still think it will be a bloated interface if it was something like: CargoRepository.find(TrackingId, LOADING_STRATEGY->[MINIMAL|DEFAULT|COMPLETE])? It's certainly not necessarily always the case, but what I have found in my experience is that lazy loading is actually surprisingly sparsely applied for many project (including this one). What other technique would you rather see that would fit DDD well? Would you mind doing a bit of research with the DDD community/other technologies and form a recommendation for us?

Keep in mind, we have a very important design alternatives section to the site planned where we can discuss various design alternatives and their pros/cons so that folks know about them and can make their own choices.

Also, we could make recommendations to the JPA EG that the EclipseLink behavior is more desirable and should be standardized .

Thanks for logging the issue and your interest in the project!

@glassfishrobot
Copy link
Author

danpeter said:
If the Project have very few lazy loaded Collections the least complex solution is preferred, in such a case a loading strategy is fine.

For more complex domain models the extended entity manager looks promising. I put this very simple sample together:
https://github.com/danpeter/extendedentitymanager

@glassfishrobot
Copy link
Author

reza_rahman said:
Sorry for the belated response to this - I just came back from a pretty hectic trip to India...

First a few comments on the code for your consideration:

  • JSF backing beans are not really controllers, but models - JSF and Wicket are the only two Java web frameworks that I know of to completely abstract away the controller responsibilities into the framework...
  • EntityManagers are actually not enrolled in stateful bean transactions unless they are explicitly referenced in the business method. In order to actually ensure a flush, I would add EntityManager.flush() to CompanyRepository.save(). I would also consider changing the repository API semantics to be more like CompanyRepository.save(Company). Besides CompanyRepository.save() being somewhat ambiguous (what is being saved - the repository or the entity?) imagine the unintended usage of invoking the getters multiple times. I think it's better to stick to the OO principle of abstraction and not force API users to understand implementation details.

Did you get a chance to check with the DDD community as to their thoughts on lazy loading? Last I checked, the consensus appeared to be that lazy loading was largely antithetical to DDD practices as indicated on this thread as an anecdote: http://stackoverflow.com/questions/15851122/domain-driven-design-entity-lazy-loading. That being said, I would not go so far as to categorizing lazy loading into an anti-pattern. Clearly there are cases where it is a valid technique. I just want to know what the current thinking is (I am sure this issue had to have been discussed).

Going the more classical DDD route, one option that might be of interest is JPA 2.1 entity graphs: http://www.datanucleus.org/products/datanucleus/jpa/entity_graphs.html.

Another interesting observation is that lazy loading actually is dealt with somewhat gracefully using DTOs at the application layer. It's only in the simplified layering case that I was trying to demonstrate that appears more complexity need be introduced in the repository layer...

Thoughts?

@glassfishrobot
Copy link
Author

danpeter said:
Hi, thanks for looking into the code. I think that Adam Bien describes it better than me here:
http://www.adam-bien.com/roller/abien/entry/building_perfect_anti_facades_almost he also mentions it as a good way to implement DDD in his book.

The nice thing with the extended persistance manager is that I can fetch the aggregate root object and traverse/modify the object graph in the the UI over several http request. Then when I am finished I call the save method on the reposity and all changes will be persisted/merged. Using the Word "flush" in the comment may have been a mistake.

Your stackoverflow link has a valid Point, maybe I am mixing DDD and data access too much.

I will have a look at entity graphs.

@glassfishrobot
Copy link
Author

reza_rahman said:
As much as I respect Adam, in this case, the empty save() method is unfortunately erroneous since it likely dependent upon implementation specific behavior (I am guessing in GlassFish). I would take a look at this and the JPA specification itself: http://stackoverflow.com/questions/7272354/why-do-we-have-to-manually-flush-the-entitymanager-in-a-extended-persistenceco.

I am also aware of Adam's views on DDD and unfortunately differ from them. In my long years of enterprise development, I can't begin to cite examples when layering and API abstraction has proven to be invaluable in keeping systems flexible, maintainable and technology agnostic in the long run.

That being said, we should document those views in this project as valid alternatives to choose, especially for relatively small, simple, young greenfield systems (sans the somewhat understandable misinterpretation/misunderstanding of the JPA automatic transaction enrollment/flush capability).

@glassfishrobot
Copy link
Author

This issue was imported from java.net JIRA CARGOTRACKER-33

@glassfishrobot
Copy link
Author

Closing this as this issue is migrated to eclipse-ee4j/cargotracker#33

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

No branches or pull requests

1 participant