For 5 years now, EJB have been used in many projects, sometimes successfully, but also with great pain. Such a great pain was for developers, who had to fight with complex objects, learn a new technology and new design patterns, and for some project managers, who saw their applications getting heavier, slower, and more costly that ever to develop. So, one could naturally ask for the reason of such a failure. Is it a conspiracy from Sun to crash the economy ? Is an inability from Sun newbies to produce a consistent and effecient specification ? Or could it be a misunderstanding of what EJB are intended for ?
To better the rationale for EJB, lets first face problems that can arise with objects. If you consider the example of Car, Engine and Fuel objects, you will see that each objects implementation is bound to another object interface : Cars implementation references Engines interface, and Engines implementation references Fuels interface. This implies a dependency : a Car cannot be used without some Engine, and an Engine cannot without Fuel. Is such a dependency a problem ? No, because a Car doesnt make sense without an Engine because it couldnt be operational. Similary, an Engine doesnt make sense without Fuel. So everything is ok, and that even does not preclude the Car (with its Engine), the Engine (with its Fuel), or the Fuel to be used independently in various contexts.
Now lets say that I want to protect my Engine run() command by some authentication system for instance. From a end (car-)users point of vue, that should only be a matter of modifying my objects implementation, or even interface. From a developper/designer (car vendor) point of vue however, that means a lot of problems : what about customers that dont want a car authentication system ? Should I write two (or more) Engine implementations ? This will probably be too costly and error-prone. So, as a car vendor, my solution is to design a general-purpose car framework able to assemble various car components like Engines, components that can be parameterized to use an authentication system or not. This way, I will be able to reuse my Engine components in different contexts by parameterizing my components instead of modifying their code. The words has been pronounced : framework, and components.
A component framework helps to reuse parts of a system for use in different contexts, instead of multiplying them for specialization. In our case, we needed Engine to be pluggable and parameterizable as a component. The parameterized behavior of my component will be handled by the framework instead of the component, usally using code generation, but that's is not a definitive rule.
In our example the Car component framework only handles one context variation (authentication) that Im able to parameterize my Engine components for, but I could apply the same principle to handle a larger number of context variation types.
So, should every object be a component ? The answer is the same as for Would I need Engines to be components if my Engines didnt need to be sometimes authenticated ? No. A component answers the need for use of the same objects in various contexts. While your software dont experience various contexts, you dont need to componentize it. The corrolaire is : dont make components before you need it.
Now lets get back to EJB. What are they intended for ? Persistence ? So why do they also provide security services ? Or distribution ? So why RMI wasnt sufficient for that ? So maybe the intend of EJB is... lets say... both persistence and distribution... and security... and transactions ? Doesnt it sound strange ? What kind of API is that all-services API ? Is it what an API intended for ? Does it make sense ? Of course not.
EJB is not an API. Is is a component framework. As such, it allows you to parameterize some parts of your system to allow you to reuse them in various contexts, without modifying them.
Now lets have a look at the rationale for all these EJB services. Here we can see that they provide a flexibility for two main categories of context variations :
- the client call type can be secured or not, transactional or not, remote or local, synchronous or asynchronous, or even timed.
- the component state can be empty of not, and persistent or not.
This allow to handle 2 * 2 * 2 * 3 * 2 * 2, so around one hundred of context variations. To handle of these cases, my code wont have to be either complex (handle all the different cases) or duplicated for specialization (writing 2 * 2 * 2 * 3 * 2 * 2 implementations). Again, this sound useful to me only because I know that I have to face to a number of these context variations. To handle only one, maybe two of these cases, a specific implementation might be more efficient than a general-purpose framework.
A lot of people misunderstanding the purpose of EJB asked a lot for features that are completely opposed to the component paradigm. As they used EJB as objects, they asked for inheritance and fine-grained relationships. If they looked at EJB as components, they would probably want to avoid inheritance as a strong dependency, loosely specified dependency between components. To make the complex state of a component persist, they would also surely boosted the emergence a real persistence service for fined grained objects like JDO, that comes today after the battle.
EJB are not perfect however. Nobody does. Even when considered as what they really are, EJB sometimes fails to provide proper code independency to context variations. For instance, the EJB persistence should allow a component to be persistent or not, without modyfing its code. This is definitely not the case : stateless, stateful session beans and entity beans cannot have the same code. Actually, there should be only one EJB implementation interface, not five.
We saw that EJB failed to show themselves as a component framework, but the EJB specification itself is far from being innocent about that. When people asked to use explicit transaction demarcation or persistence for example, the specification answered to those people misundertanding and misusing EJB You can do it if you want, instead of Use objects instead, not components.
The fact is that EJB failed to be (understood as) a component framework, and surrender by allowing car factories to patch the car framework when they want to build specific F1 engines. Unfortunaltely, it is getting worse and worse, with new EJB types (and code variations between them) in the latter EJB specifications. They also plan to support inheritance in a future release.
Actually I discussed recently with some colleagues about this subject and found out that the "component" term isn't even understood the same way by many people. Some view them as the UML/UP point of vue, other view them as "big objects" or "objects containing objects". To me, that doesn't make sense as the "object" term is enough to define that, which is only a matter of granularity and encapsulation from the object paradigm.
JavaBeans were effectively quite successful but as visual components only. This is because they provided a way to plug in visual containers and bind themselves (some remember the great work of VisualAge for Java in that domain). However, instead of decorating themselves (with additional generated code) depending on parameterized context variations, they had to be implemented as an "all-cases" support implementation, i.e. providing the expected behavior depending on their specified state/properties. This is not really the intent of components as I stated in my previous post, because this "all-case support" strategy still has an implementation overhead as it makes the code more complex to supports all the parameterizable aspects of the "component". Instead EJB focus on *one* implementation and decorate (generated additional code) to implement paramerized behavior suited to the application context.
I would agree as your statement "it's hard to think of a component that functions well from one domain to another" if you're talking about a business component framework. Let me explain this : the fact is that standardizing business is very difficult, maybe even impossible. This has been tried by the IBM San Francisco framework, CORBA facilities, SAP, etc. and all failed to serve customers : either such business frameworks were unused because they didn't fit the customer business model/weren't flexible enough or they constrained the customer business model to fit their product. What I mean is that business-oriented frameworks can only be specified by the customers because what makes the customer make money is the specificity of the way it performs its business.
This is the reason why, in my opinion component frameworks can only be successful if they are technical component frameworks. The only universal application context variations are technical variations (authentication, persistence, distribution, etc.).
Unfortunately the fact is that, even technical only, EJB failed to be a component framework today, and destroyed, once again, the interest of the component idea in many minds.