views:

389

answers:

3

I used to design my application around anemic domain model, so I had many repository object, which were injected to the big, fat, transaction-aware service layer. This pattern is called Transaction script. It's not considered a good practice since it leads to the procedural code, so I wanted to move forward to the domain driven design.

After reading couple of articles on the web, listening to the Chris Richardson's talk on Parleys and reading DDD chapters of the POJOs in Action, I think I got the big picture.

Problem is, that I don't know, how to organize transactions in my application. Chis Richardson in his book states:

The presentation tier handles HTTP requests from the user’s browser by calling the domain model either directly or indirectly via a façade, which as I described in the previous chapter is either a POJO or an EJB.

Good so far, but Srini Penchikala on InfoQ article states:

Some developers prefer managing the transactions in the DAO classes which is a poor design. This results in too fine-grained transaction control which doesn't give the flexibility of managing the use cases where the transactions span multiple domain objects. Service classes should handle transactions; this way even if the transaction spans multiple domain objects, the service class can manage the transaction since in most of the use cases the Service class handles the control flow.

Ok, so if I understand this correctly, repository classes should not be transactional, service layer (which is now much thinner) is transactional (as it used to be in Transaction script pattern). But what if domain objects are called by presentation layer directly? Does it mean, that my domain object should have transactional behavior? And how to implement it in Spring or EJB environment?

This seems kind of weird to me, so I'd be happy if somebody would clarify that. Thank you.

+2  A: 

See this extremely useful blog-post. It explains how to achieve smooth DDD while not loosing Spring's and JPA's capabilities. It is centered around the @Configurable annotation.

My opinion on these matters is a bit non-popular. Anemic data model is actually not wrong. Instead of having one object with data+operations, you have two objects - one with data and one with operations. You can view them as one object - i.e. satisfying DDD, but for the sake of easier use they are physically separated. Logically they are the same.

Yes, this breaks encapsulation, but it doesn't make you use some 'magic' (aop + java agent) in order to achieve your goals.

As for the transactions - there is something called Transaction propagation. Spring supports it with @Transactional(propagation=Propagation.REQUIRED). See this, point 9.5.7. In case you want your transactions to span multiple methods (of multiple objects) you can change the propagation attribute accordingly.

You can also use @Transactional in your service layer, where appropriate, but this might introduce a lot of boilerplace service-classes in cases when you want to use simple, single-step operations like "save".

Bozho
Hi, thank you for answer. I've already read that article. The first two proposed solutions are unacceptable. I don't like the solution with hibernate interceptors either, because (as far as I understood) it only solves injection of hibernate-instantiated beans. AspectJ solution seems quite fine. I would only have to figure out how to use transactions in @Configurable classes.But it doesn't answer the question, whether or not my domain model should be transactional or not. If not, where are the transactions supposed to be.
semberal
I added a paragraph regarding transactions.
Bozho
I know, but the article you posted mentions, that the @Configurable classes don't work with @Transactional.
semberal
not quite - the comment below this article http://olafsblog.sysbsb.de/why-configurable-and-transactional-dont-belong-to-into-the-same-class/ show that it is possible.
Bozho
Oh, I see, thanks. So, you propose, that I should inject repository objects to the entities and make the entities transaction-aware with @Configurable and @Transactional. I actually quite like the idea, but don't know whether is it considered a good practice.
semberal
To be honest, I don't know. But it sounds fair.
Bozho
+4  A: 

My personal take on applying DDD with Spring and Hibernate, so far, is to have a stateless transactional service layer and access the domain objects through that. So the way I'm doing it the domain model does not know about transactions at all, that is handled entirely by the services.

There is an example application you might find helpful to take a look at. It looks like Eric Evans was involved in creating it.

Nathan Hughes
Thanks for your answer. So, for example when you want to persist an entity, you call service.save(entity). My goal is to persist entities by calling entity.save(), as described by Craig Wells here: http://groups.google.ca/group/EtoE/browse_thread/thread/cac1eafe15f06f5b/
semberal
You're right, my code does stuff like service.save(entity).I don't care for the 'entity.save()' approach, I will read the article you linked to and edit my answer with an explanation.)
Nathan Hughes
And in case of service.save(entity) what logic remains in the domain object?
Bozho
Well, this is anemic domain model, where domain objects are just data holders and contain no business logic.
semberal
No, if you look at the DDD example I linked to there is plenty of business logic in the domain objects. I disagree that absence of a save method on a domain object is sufficient evidence to call it anemic.
Nathan Hughes
You are right and I'll probably use this approach. Thanks.
semberal
A: 

I think one easy way to get started with DDD and Spring and have good examples of how to deal with transactions is by looking at one of the sample apps that get shipped with Spring Roo. Roo churns out code that follows the DDD principles. It relies heavily on AspectJ. I suspect it was implemented building on the ideas put forward (back in 2006) by one of SpringSource's heavyweights, Ramnivas Laddad, in this talk.

Hans Westerbeek