First off - Allen, thank you for the article. We'll be passing it around to our developers and deployers.
Secondly, two comments based on my experiences in a build manager/deployer type role for the past 2 years (that's a lot of two's):
1) We originally wanted to pursue an architecture like the one described in this article (where the 3 tiers are separated out); however, we ended up deciding to bundle all of our web applications into an EAR with the EJBs they depended on. Why? Our finding was that, in our application server, WARs were loaded (into the classloader) as peers to EARs if they were outside the EAR. In fact, the WebLogic resource the article points to (http://e-docs.bea.com/wls/docs70/programming/classloading.html#1073506) touches on this restriction:
"Although you could deploy the WAR and JAR files separately, deploying them together in an EAR file produces a classloader arrangement that allows the servlets and JSPs to find the EJB classes. If you deploy the WAR and JAR files separately, WebLogic Server creates sibling classloaders for them."
The text goes on to say that WAR files and JAR files can be located separately, but only by including home and remote interfaces in the WAR file, which brings me to my second comment.
2) The article does not address the problem of dependencies between EJBs that cross EAR files. In this case, as in the case of WARs and JARs that are not in the same EAR, the dependent component must have the proper interfaces (and supporting classes) co-located in its container. J2EE provides a mechanism for accomplishing this in the EJB client JAR (for more info on this JAR, including how it is produced and how it is used, see "J2EE.220.127.116.11 Dependencies" in http://java.sun.com/j2ee/j2ee-1_3-fr-spec.pdf).
In reality, this approach is the cause of many of my headaches. When one EJB changes, you must update the client JAR in the other EJBs and WARs that use it to ensure there are no marshaling errors. This change must occur in all environments (dev, test, and production), and will likely require cross-team coordination on the testing. The development/support teams responsible for each EJB must test to ensure there is no negative impact from the change.
These interdependencies become overly-burdensome as re-use increases. You can manage them to a reasonable level by increasing the automation, both in your deployment and promotion processes and in your testing processes. But even automation comes with its own problems, as convincing managers to include time for automated testing and build management can be a frustrating task.
Perhaps that's why I'm becoming a bigger and bigger fan of any solution (tuples or n-spaces, web services, etc.) that lends itself to component communication without involving classes. Otherwise the components are just too tightly coupled.