views:

48

answers:

2

I am building an application under DDD architecture, thus I have implemented rich domain objects that can also be entities. These entities can also have full access to (injected) repositories that can do add & remove operations on other objects/entities. So far, this all works without any problems.

But can side effects for objects/entities that are added or removed be programmed? For example, when an object/entity is removed, I want other objects to get informed about it, so they can (re)query the database for storing for example new totals.

At first impression I thought JPA lifecycle methods @PreRemove and @PostRemove could handle this situation. But after studying the JPA documentation, the possibilities of these lifecycle methods are very limited. It’s not allowed to refer to any other entities and neither are you allowd to run queries via the EntityManager.

An other solution could be to handle the remove & add operations always via their repository calls. In the repository the needed side effects can then be implemented in these methods. But this is still a leaky API, even if all calls are done via the repository (and not directly via an EntityManager) there still is the possibility that entities get removed by automatic JPA deletes that result from cascading or orpahed deletes. In those instances the side effects programmed in the repository, will not be called.

My questions: how can I best implement these kinds of side effects under a DDD architecture?

A: 

If you need to keep track of deleted entities, the way to go is @PreRemove, DDD or not. If you can't directly make the desired changes from there, you can store these changes in some form of a batch to be executed later (using some AOP for example)

This article of mine discusses that you should not save your entities from within the entities themselves, even in DDD.

One thing to note is that spring allows your to have your jpa event listeners managed by spring, so you can inject whatever you want there.

Bozho
Problem with @PreRemove is that it cannot be used to update dependent entities, thus it's impossible to change things like totals, counters, etc. that are located on other model objects (by for example an event listener implementation based on @PreRemove). And BTW I liked you’re article, but I disagree with no DI for model objects, because you will need repositories to efficiently navigate you’re model objects, as no performance can be expected of navigating collections that have for example 100.000 items. You will need to query you’re model for performance reasons.
Kdeveloper
there is no problem in having DAOs (repositories) that query the database, and that are not injected into the domain objects. You can store the changes needed to be done by `@PreRemove` in some batch that will be executed later.
Bozho
Thanks for your answers. But batching changes implies that entities are for a while in an inconsistent state, doesn’t sound very attractive to me. Other architectures don’t have that result and seems to solve this without the complexity of doing batch job handling. Like many DDD enthusiast, I think the query possibility of repositories in entities is essential as most operations will start by method calls to these entities. How else can you do operations involving multiple entities? By a service layer?
Kdeveloper
yes, by a service layer. might sound as anemic data model, but view it as coordinating, rather than performing actions on the internal state of the domain objects.
Bozho
+1  A: 

First of all, there is no such thing as INSERT or DELETE in Domain-Driven Design. Customers are being registered, Orders are being submitted and later canceled, but nothing gets INSERTed or DELETEed. These are DB terms. You should model the behavior entirely in the domain when doing DDD.

For example, when customer is registered it calls all the appropriate methods to 'update the totals'. You shouldn't be using technology magic to implement the domain model, otherwise i

Szymon Pobiega