This is a proto-pattern that MartinFowler and I made up while trying to puzzle over the EJB 2.0 specification. Personally, neither of us have tried it because we're not yet working with an EJB 2.0 EJB server...
One of the problems (IMHO) with the EJB 2.0 specification is the limitation that it puts on Dependent Objects. In EJB 2.0 an EntityBean is a more complex object than an EJB 1.0 EntityBean. It can contain relationships to other Entity Beans, or relationships to more lightweight classes called EjbDependentObjectClasses (dependent objects). This means you really could have (for instance) an Order EntityBean that contained a Collection of Line Items and that referenced a Customer EJB that contained an Address.
The limitation is that according to the spec Dependent objects cannot be returned as return values of methods of the Remote Interface of the EntityBean. (See EjbDependentValueClasses) That makes it a bit difficult to manipulate these objects outside the EntityBean, to say the least.
A premise that we've been working on is that EntityBeans are objects that will be shared across multiple projects. That has led us to want to avoid putting project-specific code inside a particular EntityBean (see LimitParametersForEjbCreates). In a similar vein, we could have a method in the Remote Interface with code inside the Order EJB to say, sum up the total and calculate tax. For a customer service application, that's great, but if I'm working in shipping and receiving, I don't need that capability. Also, if I needed to do the totaling and tax calculation differently, say in the U.S. and Europe, I'm hosed.
So anyway, what Martin and I concluded is that you could save yourself this trouble by creating a single method on the Remote Interface that would take as its argument a Command (or Functor) object and return something just typed to Object, like so:
public Object executeCommand(Command aCommand);You could then code up as many Command objects as you want to actually manipulate the Dependent Objects, since the Commands would execute inside the context of the EntityBean. The cool thing about this is that according to the spec the methods of the EJB implementation can be public (and some, like ejbSelect methods, should), so it makes it easy to write your Commands to work with this interface.
This all may seem a bit abstract, but RichardMonsonHaefel is working on code to demonstrate this. Hopefully I'll be able to append it soon...
Yabbut, are you and Martin at all worried that this might obfuscate the conceptual behavioral interface of the entity bean? Will you end up with a bunch of entity bean remote interfaces whose only method is executeCommand? And then you have to go look at the Command class hierarchy to find out what's really going on? What does all this buy you? --RandyStafford
What it buys you is that it makes the current EJB 2.0 spec work. As you know, that thing is seriously broken enough that it takes something this drastic to make it usable. Also, I've NEVER been a fan of putting business methods AT ALL in the EntityBean remote interface, so I'm fine with a Remote Interface that says basically "here's some data, or here's a hole for you to get your own data out of". Remember that the EntityBeans aren't Domain objects -- they're data gateways...
We've done something similar with SessionBeans. The point was to have a very generic presentation layer where commands that apply to specific objects on the client are supplied by the SessionBean. --MichaelSchuerig
I like the idea of encapsulating business logic (or application logic) in commands, too. I'm using it on my (non-EJB) project and it works fine for me. What object is the receiver for the command (what object does the command directly reference) in your implementation? The entity bean implementation? Also, there seems to be an almost irresistible temptation for some people to trigger business logic from deep down in the domain object layer, or even the persistence layer, if they only have a chance to do so. Eventually, that causes the borders between these layers to become more and more blurred. So that might be something to watch out for.--OliverKamps
Those are actually really interesting issues, Oliver - what "kind" of logic belongs in the domain layer, versus what "kind" of logic doesn't, and what layers should have rights to trigger (or even see) other logic and other layers. It sounds like we're in agreement here. Obviously there has to be another layer to hold business or application logic that doesn't belong in the domain layer. I call that the services layer. AlistairCockburn writes about this in his HexagonalArchitecture and ApplicationBoundary patterns. --RandyStafford
I don't want to make any absolute statements about what kind of logic belongs where, but my thinking is along the lines of this: If at all possible, I want to be able to use my domain objects in different applications within an enterprise. Therefore, I try not to put any application-specific logic (here I mean logic implementing business rules or business processes specific to any application) into my domain object layer. An example: In the context of a telecom customer care and billing system, I might have to perform a credit check on the customer when subscribing the customer to a new service (such as call forwarding or voice mail). I would implement this business process and trigger this credit check in what you call the service layer and what MartinFowler in AnalysisPatterns called the application tier. Another, but as I believe undesirable, approach would be to trigger the credit check from within my service object (the object modelling a (subscription to a) telecom service), say in a validation method that is called whenever the service object is saved. This is undesirable because the order processing application, for example, may have to update the service object but will never trigger a credit check (but will have to pay for it in terms of code size, dependencies, build time, etc.).
Field validations (is the service code valid? are all mandatory fields set?), however, may be triggered from such validation method as probably all of my applications will be interested in saving objects with valid state only.
I would also be careful with implementing associations between domain objects in the domain object layer, if these associations exist only in some of the applications. For example, most if not all the applications will need to understand the associations of customer orders to their respective order line items. Therefore, it is probably fine to implement this association in the domain object layer. Another example might be an address at which I want to have a particular telecom service installed. This relationship is only of interest to some of my applications. Other applications that are only interested in the address object (say for saving an employee's address) should not have to pay for this association.--OliverKamps
Comments, anyone? Agreement? Disagreement?--ok
I think you're right on, Oliver. You talk about implementing certain business logic or application logic (credit checks, etc.) in what MartinFowler calls the "application layer". I agree with that. But Fowler (and KyleBrown and others) also talks about the need to "stretch the application layer across a distribution boundary". This is where the services layer, and Service-Based Architecture, comes from - see http://www.javasuccess.com/patterns/service_based.html for a commercialized version of my write-up of that pattern, and relevant literature refs.
I agree with you that validating itself (semantically) is one of the responsibilities of a DomainObject. Syntactic validation of field values is a responsibility of the presentation layer.
The idea of selectively implementing associations on a per-application basis is interesting. I assume you do it by making relationships first class objects? If so, doesn't that introduce a lot of complexity? If not, do you still consider your domain object classes reusable? What about databases of domain object data? --RandyStafford
Randy, I think we're pretty much in agreement about the layering. I had a look at the Service-based Architecture document you pointed me to--it is much cleaner and clearer than what I was trying to say.
All our domain objects live in a relational database; our system is database-centric and the database is pretty big. From my point of view, you don't necessarily have to turn the relationships between domain objects into first class objects themselves--how about turning the management of these relationships into (low-level) services? I don't think this will add too much complexity. From a database point of view, I wish we had managed most (if not all) our relationships in link tables and not as foreign keys on the domain objects. One reason for that (and for management of relationships as low-level services) is flexibility: I've seen many one-to-many relationships turn into many-to-many, and unidirectional navigation turn into bidirectional... --OliverKamps
EjbTwo only specifies dependent objects for CMP beans - BMP beans are free to pass their dependents by value. The reason they made this distinction is that one has to separate the notion of reference vs. value objects (Martin Fowler explains this well in AnalysisPatterns I believe) -- objects passed to the client have no intrinsic object identity, out of necessity, because they leave the memory space (contrasted to a distributed object which retains its object identity by staying on the server's address space and being accessed by a stub).
IBM SanFransisco? had a lot of influence on EJB and is more explicit in this approach (to the point where they explain the pattern of using Commands to perform business transactions on your Entities, similar to SessionBeanWrapsEntityBeans).
On another note, VladaMatena's book does a good job showing what he intended to accomplish with EJB (finally!), and his code is very readable.
Entity beans are very much like CICS transaction programs with the added benefit that you can use OO to design them. The use and reuse of dependent objects became clearer in 1.1 but one could only use them if they were using BMP, or a spec-bending tool like TopLink.
One way to look at it is to design your domain model as you normally would, and then use EJB to componentize it. This has the benefit of reducing dependencies and coupling -- something that most complex domain models often have problems with. Once you've done this, you create relatively non-reusable business transactions (Jacobsen's "control" objects) as stateless session beans and conversational state holders with stateful session beans.
One could wire entity beans together with business transactions in new and different ways by just redeploying them with different transactional settings in their deployment descriptors. For example, one could forsee a bean's business methods belonging to a larger transaction, hence the "Requires" property on the business method. In another business process you may want to isolate this transaction so you'll use "RequiresNew?" to suspend the invoking transaction context. Other attributes like Mandatory or Never get more difficult and really become dependent on the bean's implementation...
Unfortunately since session beans are remoteable and state is not guaranteed to stick around in the event of a failure (by the spec), it's not as useful as CICS session -- but it's close.
A lot of this changed with the introduction of the EJB Spec Final Draft 2. (http://java.sun.com/products/ejb/docs.html). See my comments in InPraiseOfLocalEjbs