Spring and the anemic domain model

spring domain driven design
rich domain model example java
spring boot thymeleaf
domain-driven design java
domain-driven design microservices java example
djava zone
domain-driven design package structure java
java developer zone

So, I've noticed that I definitely have a tendency to pattern my Spring/Hibernate stack objects like this:

  • Foo controller makes a call to "FooService"
  • FooService calls FooRepository.getById() method to get some Foos.
  • FooRepository makes some Hibernate calls to load Foo objects.
  • FooService does some interactions with the Foos. It may use a related TransactionalFooService to handle things that need to be done together in a transaction.
  • FooService asks FooRepository to save the Foos.

The problem here is that the Foos don't have any real logic. For example, if an email needs to be sent every time a Foo expires, there's not a call to Foo.expire(). There's a call to FooService.expireFoo(fooId). This is for a variety of reasons:

  • It's annoying to get at other services and objects from a Foo. It's not a Spring bean, and it was loaded by Hibernate.
  • It's annoying to get a Foo to do several somethings transactionally.
  • It's hard to decide whether Foo should be responsible for choosing when to save itself. If you call foo.setName(), should foo persist the change? Should it wait until you call foo.save()? Should foo.save() just invoke FooRepository.save(this)?

So for these sorts of reasons, my Spring domain objects tend to be basically glorified structs with some validation logic. Maybe this is okay. Maybe web services are okay as procedural code. Maybe as new features get written, it's acceptable to create new services that deal with the same old objects in new ways.

But I'd like to escape from this sort of design, and I'm wondering what other Spring uses do about it? Do you combat it with fancy tricks like load-time weaving (which I'm not that comfortable with)? Do you have some other trick? Do you think procedural is fine?

You can get Spring to inject your services into your Hibernate instantiated instances, using AOP. You can also get Hibernate to do the same, using Interceptors.

See http://www.jblewitt.com/blog/?p=129

Regarding "It's annoying to get a Foo to do several somethings transactionally", I would expect your service implementations would know/care about the transactions, and if you're now using the service interfaces within your domain model, that should now be not quite so annoying.

I suspect that deciding when a domain model should be saved is dependent upon what it is and what you're doing with it.

FWIW I have a tendency to produce just the same sort of anemic structures, but I'm getting there, now I know it's possible to do it a more sensible way.

Anemic Domain Model in Typical Spring Projects (Part 2), Continue learning about the anemic domain model, its benefits and drawbacks, and how to apply it to enterprise Spring projects. Anemic Domain Model in Typical Spring Projects (Part 1) One developer talks about how design patterns hold up in the real world as they examine layered architecture and domains models. by

It sounds like your application is designed around procedural coding principles. This alone will hinder any object-oriented programming you're trying to do.

It's possible that a Foo has no behavior it controls. It's also acceptable to not use a Domain Model pattern if your business logic is minimal. A Transaction Script pattern sometimes just makes sense.

The problem comes in when that logic starts growing. Refactoring a Transaction Script into a Domain Model isn't the easiest thing, but it's certainly not the most difficult. If you have tons of logic surrounding Foo, I'd recommend moving to the Domain Model pattern. The encapsulation benefits make it very easy to understand what's going on and who is involved with what.

If you want to have Foo.Expire(), create an event in your Foo class such as OnExpiration. Wire up your foo.OnExpiration += FooService.ExpireFoo(foo.Id) on object creation, possibly through a factory used by the FooRepository.

Really think about first. It's very possible that everything's already in its right place... for now.

Good luck!

Spring and the anemic domain model, You can get Spring to inject your services into your Hibernate instantiated instances, using AOP. You can also get Hibernate to do the same,� Anemic Domain Model in Typical Spring Projects (Part 2) Continue learning about the anemic domain model, its benefits and drawbacks, and how to apply it to enterprise Spring projects. by

I think that there is a simple refactoring pattern that will solve your problem.

  1. Inject your service into your repository.
  2. Before returning your Foo set its' FooService
  3. Now have your your FooController ask for the appropriate Foo from the FooRepository
  4. Now call the methods you want on you Foo. If it cannot implement them itself, have it call the appropriate method on the FooService.
  5. Now remove all the calls to the FooService through what I like to call "bucket bridge" methods on Foo (it just passes the parameters along to the service).
  6. From now on, whenever you want to add a method add it to Foo.
  7. Only add stuff to the service when you really need to for performance reasons. As always, these methods should be called through the model object.

This will help evolve you towards a richer domain model. It also preserves the Single Responsibility Principle since all your DB-dependent code remains in the FooService implmentations and helps you migrate the business logic from FooService to Foo. In you want to switch your back-end to another DB or in-memory or mock (for testing) you don't need to change anything but the FooService layer.

^ I am presuming that FooService does DB calls that would be too slow to do from an ORM like selecting the most recent Foo that shares property X with a given Foo. That is how most I've seen work.


Example

Instead of:

class Controller{
    public Response getBestStudentForSchool( Request req ){
        Student bestStudent = StudentService.findBestPupilForSchool( req.getParam( "schlId" ).asInt() );
        ...
    }
}

You'll move towards something like this:

class Controller{
    public Response getBestStudentForSchool( Request req ){
        School school = repo.get( School.class, req.getParam( "schlId" ).asInt() ); 
        Student bestStudent = school.getBestStudent();
        ...
    }
}

Which I will hope you will agree already seems richer. Now you are making another database call, but if you keep the School cached in session the penalty is neglible. I'm afraid that any truly OOP model will be less efficient than the anemic model you are using, but the reduction of bugs through code clarity should be worth it. As always, YMMV.

How to avoid the anemic domain model with Spring and Hibernate , It's called Domain Driven Design. It's a term coined by Eric Evans in his seminal book by the same name. In it he describes guidelines and examples of how the� An Anemic Domain Model is the result of having all, or almost all, the behavior of the Domain in separate classes (often called Services) that are directly changing the internal state of entities through setters. In that case the entities are merely a data model (often projected from a relational model through an ORM) with no behavior at all.

I recommend you the book Use Case Driven Object Modeling with UML by Doug Rosenberg and Matt Stephens. It talks about the ICONIX process a software development methodology that also talks about anemic domain model. It's also a topic developed by Martin Fowler in it's web site https://www.martinfowler.com/bliki/AnemicDomainModel.html . But how do we achieve when using Spring Framework and/or Spring Boot is what I'm also try to figure out.

Spring 2.0 vs. the Anemic Domain Model, Spring 2.0 vs. the Anemic Domain Model, Craig Walls, No Fluff Just Stuff, Java / Open Source Conference. The Anemic Domain Model: the Path to Confusion. After this little explanation, you can see in Dave’s eyes that he still sees the Anemic Domain Model as the way to go. Very well. You ask Dave to imagine that both examples above for Anemic and Rich Domain Model are for the same application, in parallel worlds.

DDD, Furthermore, most of the samples, even the official ones from the Spring guys, showcase this way of working. My questions are: is anemic domain� The anemic domain model is a pattern for structuring a domain model. It separates the objects in the domain model into service objects and data objects. As a result the data objects class diagram looks like a model with all the necessary relationships, however they contain only the data and getters and setters methods.

Creating a Domain Model rapidly with Java and Spring Boot, In this short article, we are creating a domain model for a simple application. We use Spring Boot to accelerate the application startup. A common problem for a domain is an anti-pattern named Anemic Domain by Martin� The anemic domain model is really just a procedural style design, exactly the kind of thing that object bigots like me (and Eric) have been fighting since our early days in Smalltalk. What's worse, many people think that anemic objects are real objects, and thus completely miss the point of what object-oriented design is all about.

DDD vs. Anemic Domain Models (Martin Fowler), In a discussion about how to implement domain objects when applying DDD, I was referred to Martin Fowler's article on Anemic Domain� Domain-driven design; GRASP information expert, an anemic domain model is the typical result of not applying the information expert principle, i.e. you can avoid an anemic domain model by trying to assign responsibilities to the same classes that contain the data; References

Comments
  • Great question that I've always thought about as well. Some great answers here too.
  • The Hibernate interceptor is an interesting idea. I like not having to make scary-looking edits to my Tomcat classloader.
  • Why would you want services in your objects? That sounds AWFUL.
  • @Jess because that is the idea of OOP... the same object that houses the data knows how to manipulate the instances. Anything else is just fancy structs from C.
  • @ArtB - small self-contained methods in an object aren't the problem, I was specifically referring to what most people would consider service methods (i.e. Transaction Scripts). For example, having a BankAccountObject know how to get a balance, update itself, etc is fine. Utilizing the same object to create annual statements, perform a reconciliation, etc seems ludicrous. A separate set of transaction scripts separate from your domain objects seems like a more sensible way to perform these lengthy operations.
  • @Jess Utilizing the same object to create annual statements, perform a reconciliation, etc seems ludicrous. Is it really? Why not give the BankAccount a StatementFactory ( or have it create instances of Statment ) so that they BankAccount can produce it's own statement without having that logic itself in the BankAccount?