EJB design: Mixing Design Patterns?
I've been trying to get my head around the pros and cons of using Entity vs Session beans for a pretty simple database application.
I'm trying to stick to the following patterns as recommended by amongst others Ed Roman in his JavaOne talk at http://www.javasoft.com/javaone/javaone00/replay.html , and by alot of other people at the Archives of EJB-INTEREST at http://archives.java.sun.com/archives/ejb-interest.html
1. The client should access entity beans only through business logic within session beans.
2. Value objects should be used to access entity beans' data, using inheritance from the value objects to implement the Entity Beans and so avoid code duplication.
3. Do Validation in value objects.
4. Keep transactions short and on the server.
However I've run into the following question when trying to successfully combine these patterns:
How do I cope with the data on my client's screens getting out of date? i.e. If I pass my client a value object obtained from an entity bean via a session bean then because I'm not doing client side transactions I run the risk of my client editing this data while another client is making changes i.e. I can't have strong isolation without starting and stopping transactions on the client.
A possible solution to this is to keep a copy of the original value object and then compare it with another version obtained from the entity bean just before doing an update. It would be no use doing this on the client if I wasn't using client side transactions so I would have to keep a copy in a Stateful Session Bean on the server and have it do the compare/update with serializable isolation, throwing an exception back to the client if the original copy didn't match the current entity bean. This seems ugly.
Another issue of not have clients access entity beans is that I don't have to use them! I can just as easily implement my Session Beans using a data access layer that produces and consumes value objects. This gives a big speed increase when the client wants to browse lists of data as the server doesn't have to create loads of entity beans and I can optimimize the database access to get all of the Value Objects with a single database query. The client won't know if I'm using Entity Beans or not and shouldn't care.
For EJB1.1 servers I can't see many good reasons for using entity beans, especially when you have dependent tables in your database in which case you end up having to use BMP in any case.
PS thesiderside.com is an excellent resource. It's good to have an independent forum like this.
Thanks for the well-phrased post. I will try to answer your questions as best I can.
You're right that value objects are not transaction-aware, and that is problematic if you are not comfortable taking your data outside of the isolation 'umbrella' that transactions offer you. Value objects still have their place, and we use them here on TheServerSide.com for marshaling entity bean data into a JSP. However, those value objects lose cache consistency immediately, and are only useful to see a 'snapshot' of the database at any given time. Once the client clicks a button in his browser, the underlying data may have changed by a different client, and so the value object needs to be re-extracted from the entity bean.
If you need the data to be cache-consistent for long periods of time, your idea of versioning the value object would work, although that would be kind of arduous (however it would allow for very fine-grained control of conflicts.. you could detect conflicts at a field level rather than at an instance level).
Another possibility you might want to consider is to use a 'sequence number' and store that in the entity bean. The idea is that whenever anyone updated the entity bean, it would increment its sequence number by 1. When a client asks for a value object from that entity bean, the client would get the value object with the sequence number inside. When the client modifies the value object and tries to repopulate an entity bean with the new value object, the entity bean can check the sequence number to determine if data was overwritten from another client, and throw an exception if necessary.
This idea is actually analogous to optimistic locking, since you are hoping that a conflict doesn't happen, and if it does happen then you throw an exception. This is in stark contrast to pessimistic locking, where you lock up the object prior to modifying it. To achieve pessimistic locking, the only solution I can think of is to use a long-term distributed object locking service such as the CORBA locking service, which (unfortunately) J2EE does not have an equivalent.
Your next question was about entity beans. You're right that you don't have to use them, and Microsoft certainly doesn't yet people somehow manage to produce working web sites. However, as far as speed increases, I disagree that entity beans are a slow technology. Entity beans can be much faster than straight JDBC due to long-term distributed shared object caching. Furthermore, if you choose the right application server (such as the Inprise Application Server) then your entity bean calls can be optimal and speedy due to efficient bean-bean communications, allowing you to create fine-grained entity beans without incurring a performance hit. I recommend that you read my EJB/COM+ technical whitepaper on this web site that discusses those issues. I talk a lot there about the value of entity beans.
Finally let me say that the value object inheritence design pattern is only one approach. An alternative was recommended to me by a developer after my talk, which is basically to delegate from an entity bean to a value object rather than to use inheritence. I would like to hear people's opinions on this.