From the IBM WebSphere Developer Technical Journal.
In each column, The EJB Advocate presents the gist of a typical back-and-forth dialogue exchange with actual customers and developers in the course of recommending a solution to an interesting design issue. Any identifying details have been obscured, and no "innovative" or proprietary architectures are presented. For more information, see Introducing the EJB Advocate.
|
Dear EJB Advocate, I am writing you in the hopes that this dialogue will fuel change within the IBM® WebSphere® Application Server product concerning a problem that we encountered with the current implementation of EJB References. Some background: Our application development team is scattered across the globe with over 1,000 developers in four countries. Our current architecture uses a session EJB with a remote interface as a facade to various services implemented in a POJO (plain old Java™ object). Each service can be thought of as executing a workflow of one or more tasks that are themselves implemented in a separate POJO for reuse (a given task may be reused in multiple workflows and services). Further, tasks can use other services (such as would happen in a complex workflow). In order to fully leverage this reuse and the skills of our development organization, we generally do not want our programmers to know the session facade exists as an execution context for their POJOs. The problem is that each session facade needs to have an EJB-REF entry in the deployment descriptor for each session facade that it accesses. Practically speaking, this requirement means knowing all the services called by the tasks called by a given service implementation. And since we do not really want to break the encapsulation on the tasks called by a given service, this becomes more than just a maintenance headache, requiring us to duplicate lists of references over and over again. Any help would be appreciated, especially if you know of a tool that can examine our code and automatically generate the EJB references for us. Yours truly, |
Digging deeper to reveal an architectural inconsistency
The EJB Advocate himself got a headache just by reading about having to know "all the services called by all the tasks called by a given service implementation". This recursion pointed out an inconsistency in the way services and tasks were implemented and used -- even though both were developed separately and possibly by different people. However, The EJB Advocate wanted to make sure of the details:
|
Dear Cross, Your architecture seems very similar to a number of others I have encountered before where workflow-like behavior is handled by session beans and helper classes. A solution to your problem probably does not require code-understanding tools, but before proposing anything specific, I'd like to make sure that I have all the details right. Figure 1 is what I understand to be the high level architecture from your description. Figure 1. High level architecture A number of questions (more or less from left to right in the architecture above):
Figure 2. Sequence diagram for a stateful command pattern OK then, |
The following was the reply:
|
Dear EJB Advocate, Thanks for the prompt reply. Here are the answers to your questions:
Hope that these answers help you propose a solution. Yours truly, |
A modest proposal: Use session EJBs for the tasks, too
The answers were almost as The EJB Advocate expected, except for tasks not being stateful. Oh, well. In any event, the problem seemed to arise from not treating tasks like the full-fledged components they are (the adage "if it walks, quacks, and looks like a duck..." came to mind).
Here was the proposal:
|
Dear Cross, Thanks for your answers, because they do give me enough detail to propose as solution. Here is the modified class diagram capturing the extra information you provided to use for comparison purposes from those that I will recommend below. Figure 3. Corrected high level architecture A rule of thumb I like to apply is that when code is developed and tested separately, it should be packaged as a component. Let's pretend for a minute that your team was not opposed to EJBs. In this case, I would recommend that both Services and Tasks be implemented as session beans. Why? Because a major benefit of session EJBs that your team seems to overlook is maintainability and reliability. One distinction you seem to make between Services and Tasks is that Services are accessible remotely, and Tasks are accessible locally. Therefore, I would expose and use a Remote interface for Services, and a Local interface for Tasks, as shown in Figure 4. Figure 4. Proposed high level architecture with remote services and local tasks If the Tasks had exposed a stateful programming model to the services (like I first assumed they did), they would be declared as stateful instead of stateless in the EJB deployment descriptor. The overhead of a local session EJB is relatively low, so performance should not be an issue, even if they are stateful. (As an aside, some might argue that stateful session beans should never be used. However, we never say never. We are happy to recommend them in this case, since they are deployed locally to a Service; therefore, the statefulness occurs within the context of a transaction started on the outermost session bean representing a Service. In short, if you are willing to accept local entity EJBs behind a session facade, you should be willing to accept a local stateful session EJB behind one as well.) In any event, there are benefits that make it worth the tradeoff for Tasks to be session EJBs, whether stateful or not. Of course, the most important benefit is that this architecture solves your reuse and EJB-REF problems. Programmers that build Services can use Tasks (and Services, under certain circumstances as you described). Programmers that build Tasks can use Services. In either case, the deployment descriptor for each session bean (Task or Service) simply includes an EJB-REF for each session bean that it actually uses. Encapsulation is maintained, which is a key to maintainability. Another benefit of making each Task an EJB is that you can unit test the Tasks independently of the Services that may call them (which includes testing the EJB-REFs that they use). Anything that makes a component easier to test is good for reliability. Also, an often overlooked benefit of an explicitly EJB-based approach is that your business logic can take advantage of the EJB context to get access to information, such as the user making the call, and the transaction currently active. This ability simplifies the signatures of the Service and Task methods (while I did not ask, I suspect that user IDs and other information available in the session context is explicitly passed on the Service and Task POJO method signatures -- but we can save that for a separate discussion). But even with all this said, I suspect that you still could not yet sell the explicit use of EJBs to the team. A compromise is to generate a "business delegate" and associated session EJB components from the Task POJOs as shown in Figure 5. Figure 5. Generate business delegate and associated EJB components for services and tasks The Service POJO code will need to be changed to new up a Task Delegate rather than a Task POJO. But a good IDE will simplify the migration. And the change will be worth it, since this approach will help make the architecture much more service oriented and flexible with respect to the deployment options. Good luck in your future endeavors. OK then, |
Through this exchange, we saw applications of Session EJBs -- both remote and local, both stateless and stateful. Hopefully, we added maintainability and reliability to the list of benefits that architects will consider when choosing EJBs, beyond distribution, security, and transactions.
The rule of thumb to remember is that service oriented architectures require functional decomposition: decomposition results in components that ultimately need to be managed, and components in Java are best implemented with session EJBs (with or without a helper class, which makes the session EJB a facade). Trying to hide the use of EJBs is one thing (usually leading to some justifiable tradeoffs), but trying to avoid using components is another (usually leading to problems).
In the next column, we will examine an exchange that gets into the details of how to design EJB method signatures. We will expand on uses of the EJB context information, as well as the stateful programming model introduced here, and show how a stateful programming model can always be converted to a stateless one -- if you are willing to make the tradeoffs.
- Introducing the EJB Advocate
- Java 2 Platform, Enterprise Edition (J2EE) specification, the definitive source
- Enterprise Java Programming with IBM WebSphere, Second Edition, by Kyle Brown, Gary Craig, Greg Hester, Russell Stinehour, W. David Pitt, Mark Weitzel, JimAmsden, Peter M. Jakab, Daniel Berg. Foreword by Martin Fowler.
- Browse for books on these and other technical topics.

Geoff Hambrick is a lead consultant with the IBM Software Services for WebSphere Enablement Team and lives in Round Rock, Texas (near to Austin). The Enablement Team generally helps support the pre-sales process through deep technical briefings and short term Proof of Concept engagements. Geoff was appointed an IBM Distinguished Engineer in March of 2004 for his work in creating and disseminating best practices for developing J2EE applications hosted on IBM WebSphere Application Server.
Comments (Undergoing maintenance)





