Here are some of my thoughts on some issues I see with using container-managed relationships and why I will steer clear of them. I would be interested to hear other opinions on the topic (and/or criticisms of mine!):
1. Manageability. For two or more entity beans to be part of a container-managed relationship, they must be deployed together in the one JAR file, sharing the one ejb-jar.xml file and whatever other XML files are required by your EJB server. This is OK I suppose on a per application basis. However when you have a common reference table (and therefore entity bean) that is shared across multiple applications (your Customer table, say) you end up either having the same bean deployed more than once to the EJB server (you will need to deploy it once for every application that requires it) or you face the situation of having all your beans packed into one JAR file and released together. This "all-in-one" solution has its own problems as the entity beans from various projects will end up sharing a common class-loader. This in itself is not a major issue as you are prohibited from using static fields etc within beans but it is still not nice! Also, the larger this "all-in-one" ejb-jar.xml file becomes, the more prone it will be to bugs when more and more developers (or deployers) are playing around with their CMR tags. Prudence would require that every bean and its corresponding relationships are tested every time a change is made to the ejb-jar.xml file. A nightmare for any decent sized system.
2. Scalability. Container-managed relationships only work when the Local interfaces of an entity bean are used as the return types and parameters of the gets and sets for the container-managed fields. Or, in the case of 1:N relationships, you need to specifiy a java.util.Set or java.util.Collection as the return type and parameter to the get and set methods of the CMR field. As the Local interface and the set/collection interfaces are not serializable, you cannot return these to remote clients. This presents an issue regarding scalability. If all of your CMRs are based on local interfaces how will your EJB's scale when you decide to add a new server to handle all of those new clients?? I know you can put all of your entity and session beans on multiple servers and load balance between them, but what do you do in the case where you want to move some portion of your entity beans off to another server and not replicate all your beans? In this situation your CMRs would be useless as they would not be able to communicate across servers.
So, what can you do? Go for a complete BMP solution and code it all yourself? Not likely. I would suggest that the best way around these issues is to still use CMP wherever possible, but use your own code in conjunction with CMP finders to control the relationships in place of CMR.
So, in the case of 1:N relationship where you want to retrive the child records based on the parent the solution is simple: a findByParentID method on the child bean will suffice. Child beans will need to have a findByXXX for every foreign key in their table.
Should you need a bidirectional relationship, in our instance to go from the child to the parent, you will need a getParent method on the child. This method is where you will need to do some coding (but not much). All that you will need to do is call the findByPrimaryKey method of the parent based upon the foreign key field of the child. A 5 liner that should take too much effort.
This solution is, I think, neat in the way you don't have to change the parent bean no matter how many different children beans are developed; as all of the relationship code lies within the child bean.
Even in the case of N:M relationships, the parent never need to modifed as all you will need is an intersection bean to handle the relationship which will have all the required lookup code.
In summary, I think this is a neat solution as it addresses the issues raised above. 1: The EJB's can be deployed separately and only once and won't need knowledge of each other. Each bean can have its own classloader (if required). 2: You are free to use the Remote interfaces for the beans so that you're beans can still have relationships without requiring the related beans to be co-located - this should be of assistance when your boss asks you what you are doing about scalability. However, a problem I can see is when it comes to removing a bean. This will require the parent to know of its children so that the referential integrity of the DB can be maintained. However, this cascade delete operation can be implemented at the database level by using triggers which won't affect you beans portability.
That's about all that is in my head on this issue. I would be interested to hear from anyone else who has similar or, even better, differing opinions.
So you are saying EJB 2.0 CMP has no merit? Then why so many people are excited about it?
In the case of clustering, how would remote interfaces help you better than local interafces? You still have to deploy all EJB's to all members in a cluster, not EJB_A on machine A, EJB_B on machine B.
Not at all, I think CMP has a heap of merit - its just the implementation details of CMR that I have concerns about.
As for the clustering issue - yes, in a cluster of servers you would need to deploy all beans onto all servers. However, I just have conerns about being restricted to an entire session running within the one server. This could arise where you have a distributed system and you want to access a database in another country. An entity bean would be good here to provide course-grained access to the data via a server sitting in the remote site. With the restrictions that CMR imposes this wouldn't be possible.
Well, I know you are not arguing about CMP in general, but EJB 2.0 CMP to be exact. Basically you are creating your own entity relationship manager in your CMP EJB. As such you are only using EJB 1.1 CMP features and totally ignore the CMR feature of EJB 2.0 CMP.
Entity beans should not be COARSE-GRAINED anymore, with the advent of EJB 2.0 CMP. You can read the review chapter in Floyd's book for details.
As for the scenario you described about the remote database, you don't need a second app server to access a second database. WebLogic 6.x support distributed transactions in EJB's and one app server can host EJB's that access multiple databases in the same EJB.
What about the manageability side of CMR? Don't you find that having to deploy all related beans together is an absolute nightmare?? How would you approach the situation where you have many applications reliant on a few common beans?
I agree that all EJB's have to live in the same .jar in order to participate in CMR is a bit limiting. However, I believe this is not a problem with EJB 2.0 API, rather a issue with container vendor implementation. I read somewhere that a near future version of WebLogic will allow EJB's in separate jars to participate in relationships.
As a side, the articles by Tyler Jewell about J2EE/EJB packaging and deployment available at this web site and at ONJava.com are helpful to understand the packaging and class loading scenarios under EJB 2.0.
After my first reading of the CMR, (Enterprise JavaBeans, Monson-Haefel, page 174), I found one statement astounding. Does one have to modify the database schema to accomodate CMR? If so, the designers of CMR have lost respect for the data model so never will I use CMR for that reason alone.
First off, never say "never".
These days there is a lot of debate on which of object model and data model should be done first. People who are "hard-core" OO designers and who firmly believe in UML modeling tend to argue the object model should be design first and the data model is based on it. If this is the case in your development, you should have little difficulty using the new CMP.
For legacy database systems, as long as your data model confirms to at least the 3rd Normal form of relational database, you should have little difficulty mapping CMP entity beans to tables. The typical 1:1, 1:N, and M:N cases are well covered by the EJB 2.0 CMP model.
As for the specific example Richard Monson-Haefel uses in his book, even if the foreign key (customer id) is in the address table (meaning a customer can have many addresses, e.g. a ship-to and a bill-to), you can still do this easily using EJB 2.0 CMP. He put an address_id foreign key in the customer table to simplify the probelm to demo an 1:1 relationship.
Your arguments are very valid when you are going for very big systems which needs a very high level of scalability. But, in most of the scenarios these high scalability and managebility is not required.
Here is my comments -
1. Manageabality - IMHO, CMR's are good for most of the projects. If data model is carefully designed, you can put the related CMP entity beans in small groups. Probably you can have a session bean to act as a facade to link these groups of CMP entity beans.
Your solution of writing your own entity relationship handling in session bean involves more coding. More the code more the manpower, cost and then follows the bugs.
2. Scalability - Can be achieved in many ways. Most designs use the simpler load sharing algorithm (ex. round robin) instead of more complex load balancing. You can scale the incoming request at the session bean itself. Trying to scale at each entity bean will degrade the performance as the related entity bean might be on any server.
In my opinion in most of the scenarios CMR's are easier to code and less error-prone than manually implemented entity relationship.
>>As for the clustering issue - yes, in a cluster of
>>servers you would need to deploy all beans onto all
>>servers. However, I just have conerns about being
>>restricted to an entire session running within the one
>>server. This could arise where you have a distributed
>>system and you want to access a database in another
>>country. An entity bean would be good here to provide
>>course-grained access to the data via a server sitting in
>>the remote site. With the restrictions that CMR imposes
>>this wouldn't be possible
Is this really a problem. I would like to believe that assuming all EBs are deployed on all nodes in a cluster, the container would manage CMR local-reference-relationships on EACH node by instantiating a local EB to a particular mode when a session starts on one server and finishes onto another.
Am I missing something? If so, we probably need to look a little closer at CMR. Frankly my experience with CMP is limited but I'm talking about pre EJB 2.0 days. But if CMR is not gonna work for me, I would much rather stick with BMP. True CMR gets rid of a lot of book keeping and error prone aspects of managing relationships. But having done this for some time, I personally don't find it to be a chore.