I started on my assignment for part II with the intention not to end up with an anemic domain model. I had the firm intent that when I used EJB3 Entities they would have rich behavior. However, ...
I have done the design sequence diagrams for two of the five use cases now and updated the design class diagram accordingly and guess what ? Until now there are mostly getters/setters in my "domain" classes. I have noticed that as soon as you start using patterns like a Model Facade or say you want to use an EJB3 Timer Service, or even if you want to use the Value List Handler (with session facade strategy), the use of these patterns all seem to lead towards a rather anemic domain model (my EJB3 Entities that is).
All these patterns exist for good reason and they solve very real problems indeed, but the consequence almost inevitably (at least to me) seems to be a rather poor, in behavior that is, domain model.
Is it just me or have you also noticed this to some degree ? If it's just me and you guys have a rich behavioral domain model, please let me know because that would mean I have some serious redesigning to do.
But for me, domain model will be good or bad, it's not depend on frameworks/technologies we use. It's depend on how we analyze and design.
Could you please be more specific? Are you saying that Java EE 5 prevents us to design good domain model?
In my assignment I have an Auction domain model class. I am designing/implementing my model classes as ejb3 Entities. A typical method I wanted to add to this class was "start" meaning you start the auction. This seemed like a logical place to put this method right ? This method would need to be called from a collaborating domain model class (another ejb3 entity). So, you would have an EJB3 Entity class Auction with a start method. But then you start thinking about all sorts of implementation details like, how will you end the auction once you have started it ? Does it have to be transactional ? What about security ? You start thinking about things like maybe I should use an EJB timer for this ? You "try it out" in a sequence diagram to get a "feel" for the dynamics of the scenario taking into account all the NFRs I just mentioned above and ra ra ra, what happened ? The start method can no longer be on the entity because entities do not support timeout methods. You can imagine other scenarios like this. You start by putting the business method where it belongs, on the entity / model class, then JEE technology implementation requirements force you to do otherwise.
Well maybe it's not the technology as such but the NFRs of the assignment in combination with the technology being used to implement those NFRs, I am not sure anymore now ...
Does it have to be transactional ? What about security ?
Because EJB3 entities are POJOs they obviously don't have access to any container services. That doesn't me you can't implement business logic/algorithms specific to the entity in the entity. If it cuts across multiple entities then put it in an application service. The point is you're not going to be calling that business logic directly; you're going to be invoking it via a session bean that does support transactions, security and can also be a timed service.
Jonathan Aotearoa wrote:The point is you're not going to be calling that business logic directly; you're going to be invoking it via a session bean ...
My point exactly !!!
Best case you will end up with kind of a "double layer" of "business" logic : one call, a "wrapper" business method (on the session bean/application service) to make use of the appropriate JEE container services, and the second call which may simply be a delegate call to the Entity/model class. However, you would first have to retrieve the entity again before you could even make the second delegate call, otherwise the entity would not be "managed" by the entity manager and you would not be able to persist any changes. You would obviously want to give similar names to the methods on the session bean and entity or even give the Session bean and entity the same class name (but in a different package so they would have distinct FQN). If you do the latter, you even end up with a double "model" layer if you can call it that ...
I don't sure what you mean, why do we have to retrieve the entity again?
I think about an example, if we implement an Java EE 5 RPG game, we have session bean, AutoFightBean, and call method fight().
In method fight, we query current characters and current opponents.
After that we call method autoFight for each character, this method will use best strategy for each character against opponents. If win the battle, update EXP point for each character and persist to repository.
Isn't this good enough? Or I don't understand your point?
you should however consider the possibility that during the time the entity was detached it was removed by another user in which case the merge operation will fail with an IllegalArgumentException. The detached entity may also have been updated in the mean time in which case the merge will overwrite any changes done by another user.
In case you are using a statefull session bean with an extended-scope persistence context and your entity is a member variable of the statefull session bean, so part of the stateful session bean's state, then it was never detached in the first place. In that case however I would assume the entity never "crossed-over" to the webtier, thereby never leaving the current persistence context scope, and the values used to update the entity's state are being passed in as parameters to the method call on the statefull session bean instead of the entity itself.
The detached entity may also have been updated in the mean time in which case the merge will overwrite any changes done by another user.
Not if you're entities have a version property, which should always be the case if you're detaching and merging them.
To get back to the original topic, the ejb3 in action book, chapter seven says this:
. However, the "business behavior" shown in this book is "limited" to getters and setters.
A rich domain model on the other hand, encapsulates both object attributes and behavior and utilizes objected oriented design such as inheritance, polymorphism and encapsulation.
In his article on anemic domain models , Martin Fowler says
The catch comes when you look at the behavior, and you realize that there is hardly any behavior on these objects, making them little more than bags of getters and setters.
An OO guru like Fowler, doesn't consider getters/setters "real" business behaviour and I agree with him on that.
That is also what I was trying to get across in my original posting. Taking advantage of JEE container services, by using core JEE design patterns, reduces the ejb3 entities to little more than bags of getters and setters.
Some interesting links on the subject:
And links you posted don't relate to this topic, I think this topic is about Java EE 5 prevents us to design good domain model
However, I don't quite understand yet how does it prevent good design, you discussed about JPA, do you mean JPA design doesn't support Entity classes to have business methods, or you mean something else?
Maybe, I don't understand because I lack experience in EJB 3. Can anyone please to say clearly, how Java EE 5/EJB 3 prevents us to add business methods to Entity classes, what will happen if we do?
I looks like Spring addresses this issue with the help of aspect oriented programming and dependency injection by injecting resources into a POJO after it's been instantiated by a persistence provider. The example discussed here talks about Hibernate, but the principle is the same.
The InfoQ article talks about using Domain Driven Design to combat anemic domain models. Some of the comments are also very interesting in relation to what we're discussing here - i.e. people arguing about whether an anemic domain model really is that bad.
The point is that there's a lot of people out there asking the same question, so it would seem reasonable to assume that the EJB3 architecture is directly responsible for the proliferation of anemic domain models.
Jonathan Aotearoa wrote:The problem with having JPA POJOs for you domain model in an EE environment is that you can't inject an entity manager into them
One last thought before signing of for the day (feeling sleepy here). What if you inject an entity manager in a session bean and call a setter for the entity manager on the entity. Inside the entity, the instance variable holding the reference to the entity manager would marked @Transient. The entity could then maybe say something like: this.myEntityManager.persist(this). Could this work ?
Talk to you guys tomorrow.
Jonathan Aotearoa wrote:The problem with having JPA POJOs for you domain model in an EE environment is that you can't inject an entity manager into them. That means your domain model objects can't even do the basics like persist themselves. People get round that by introducing a service layer made up of stateless session beans. The result is an anemic domain model with lots of transaction scripts.
We cannot blame Java EE 5, because usually we cannot DI to post-instantiation beans. Normally we cannot do that in ANY environment, not just Java EE 5. Aspectj can help, but it's a different story.
And about domain objects persist themselves, it is just Active Record pattern, for me it's not object-oriented but it's data oriented.
If you have read Domain-Driven Design (I believe you have), Eric suggests to use Repository. You can read DAOVersusRepository.
But I think your main point is, we cannot inject dependencies to Entity domain objects, right? Can we use Service Locator pattern?
So far, I understand, I don't think Java EE 5 is responsible for this problem. If I misunderstand anything, please tell me.
And to clarify, not all domain models are in Entities, we can also have domain models in Services, Value Objects, and Modules (refer to DDD).