Increasingly, business applications are evolving into a client side that interacts with the user, and a server side that stores and retrieves data and manipulates it in various ways. The client side may run on a number of different hardware types including telephones, pagers and handhelds, in addition to the usual assortment of desktop and laptop computers. The intricacies of dealing with this assortment of client types from a single server would make a good article but will have to wait for another issue, because our subject today is the server side.
Responsible for satisfying requests from all of these client types, the server side is the key to success in e-business. But, unlike even the relative simplicity of years past, today's server side must integrate many functions and has grown increasingly complex as a result. Customers expect even a simple e-commerce sales application to check stock levels and tell them - truthfully! - whether or not their item is available today. Then they expect the application to interact with bookkeeping to charge their credit card and with shipping to set up their order. After they receive an e-mail confirmation with their order number, they'll expect to punch it into an Order Status Web page and find out if their stuff has shipped yet, and then to retrieve a tracking number that lets them follow up with the delivery service as their package wends its way from a warehouse to their house.
Clearly, this assortment of functionality is too complex to run on a single server. These days it takes a number of servers, each typically load-balanced on several to many computers, to provide the service level required by even a medium-sized enterprise. This makes the server problem inherently distributed. In addition, a server must have these four essential characteristics for businesses to rely on it:
- Scalability: A server must perform robustly and deliver the same good performance even when (or, perhaps, especially when) heavily loaded - financial trading applications need to handle the days when the markets swing way up or down and everyone wants to get in or out of positions; travel reservations systems have to handle the load when bad weather over half the country cancels flights and everyone needs new reservations.
- Transactionality: Business transactions, once completed, must be reliably committed to persistent storage and immediately become visible to every client. A trader must be allowed to sell his stock in XYZ company only once, and the last seat on the last flight to San Francisco must be assigned to only one traveler.
- Reliability: When the client side crashes, only one person notices. When your server crashes, every user notices. If your site is big enough, the outage becomes a headline in The Wall Street Journal and even more people notice. The ideal server never stops running - not for crashes, nor for upgrades of hardware, operating systems or even applications.
- Security: It doesn't matter whether you're buying books, bonds or seats - security is essential. We don't have to say why; you already know.
The first product tailored to this type of application was the transaction monitor, or TM. Based on transaction processing systems, TMs added scalability and robustness to business computing. But they were more of a genre than standards-based software, and each vendor's product used its own proprietary interfaces to provide essentially the same service as the other vendors'.
As client load increased the need for servers with these characteristics, advances in software architecture provided better ways to build them. Server-side infrastructure products combined resource control, load balancing and redundancy techniques in various ways, many using object-oriented techniques, until finally a number of standardized architectures emerged. We'll start with one you may already be familiar with - Enterprise JavaBeans (EJBs) - and see how the OMG has extended it into the CORBA Component Model (CCM). EJB is a good place to start because CCM is a superset of EJB, extended in two directions: programming language coverage and features, as we'll see.
Before components, it took a lot of skill and technical know-how to code a server application with the characteristics we listed - scalability, transactionality, reliability and security. For example, even if you had a TM-based infrastructure, you had to begin and end each transaction in hard code. This forced programmers to acquire a set of server-programmer skills above and beyond the knowledge they needed to code the business logic that was, after all, the reason the server was being built.
In the new server component architectures, in contrast, scalability, transactionality, reliability and security have become runtime characteristics of the system rather than the coded-in properties of any individual part. They're built into the component infrastructure, which provides them to every component instance as a service at runtime, through standardized interfaces. You buy a component system with development and runtime parts. Your system administrator installs the runtime, which includes a transaction-processing system, security, load balancing and possibly provisions for fault-tolerant operation. Components running in this environment automatically become scalable, transactional, reliable and secure.
After they've been built using the development environment, assembled into an application and configured properly (more on this coming up), components are installed in, and run in, a container whose standardized interfaces communicate between the environment and the component implementation. The container manages component instances' life cycle (creation and destruction) and resource control (activation and passivation), and provides infrastructure services including state persistence and transactionality via standardized interfaces.
In contrast to client-component interactions, which may be (and, virtually always will be) remote, component-container interactions must be local - that is, the container and component instance must reside on the same physical machine. The EJB 1.1 specification doesn't say much about load balancing, but we know that multimachine EJB servers are available from several vendors; the CCM specifically allows containers to span machines for load-balancing purposes.
Let's look at how EJB (and, looking ahead, the CCM) provides the four capabilities we listed:
- Scalability: This is provided mainly by server resource control. EJB instances don't run constantly; they may be passivated by their container and their memory resources reclaimed when idle, and activated automatically when invoked. (CCM uses the POA for this.) Additional scalability is provided by load-balancing techniques, although these aren't standardized by EJB. (Load balancing in CCM is supported by IIOP features that we won't detail here.)
Building an EJB Server and Application
- Transactionality: Both EJB and CCM runtimes include a transaction-processing system that provides two-phase commit and rollback behavior and all the other features of TP. You don't have to code transactionality into your EJBs or CCMs - you can get the behavior just by specifying it in your deployment descriptor files (container-managed transaction demarcation). Alternatively, you can code the beginning and ending of transactions in your components if you wish (bean- or component-managed transaction demarcation).
- Reliability: Although the EJB specification doesn't contain any explicit provisions for reliability, EJBs' encapsulation lets vendors build redundancy and other fault-tolerant features into their runtime. (CORBA has a separate fault-tolerance specification that can be applied to a CCM environment.)
- Security: The EJB 1.1 specification defines security functionality and a number of security interfaces. If you don't want to code security into your application, you can omit the calls and let the application assembler and deployer set security policies in configuration files. All security functionality resides in the container, of course. (CCM uses the same structure with CORBA security interfaces.)
Both the EJB and CCM specifications divide the creation and deployment of a server application into roles. We'll present the six roles described in the EJB specification; differences between these and the corresponding CCM roles are subtle enough that we don't have to discuss them separately. The first two roles are extremely technical, since these players create the development and runtime environments. These designers and programmers program transactionality, scalability, reliability and security into a product that can be used by any business to create applications that gain these desirable attributes from the system that runs them. They are:
Freed by the container architecture from the need to program technical details, domain business experts can now step in and play roles 3 and 4. The application they produce will then combine their best business logic with the enterprise qualities that the server and container providers built into the base system. These business roles are:
- Server provider: This player provides a development and runtime environment that is transactional, reliable, scalable and secure. It need not conform to any of the EJB interfaces, however - in fact, many TM suppliers could fill this role.
- Container provider: This player builds the container. On the outside, the container interacts with the server using its proprietary interfaces. On the inside, the container provides the standardized EJB functionality to the enterprise beans installed within it through the interfaces defined in the specification. This player must also provide configuration, installation and runtime support.
- Enterprise bean (or component) provider: This person is typically an application domain expert. Because the container provides scalability, transactionality, reliability and security, and the architecture allows for transparent distribution, he or she doesn't have to be an expert in these (or any other) system-level programming techniques. Still, this person should understand reusability enough to produce EJBs that can be used in a range of applications.
- Application assembler: This person assembles the coded enterprise beans into an application. Sometimes the provider and the assembler will be the same person, especially for applications written from scratch with no (or little) reuse of previously developed beans. In projects that reuse beans, the assembler's role is to put together an application that combines EJBs from multiple sources.
The architecture carries the division-of-labor principle one step beyond what we've described so far. By dividing application creation into two steps - bean provider and application assembler - it puts into place the foundation of a component marketplace where multiple supplier companies develop independent components that can later be assembled into multiple applications to fit most precisely the needs of the end user.
Some Technical Details
- Application deployer: This person takes one or more ejb-jar files and deploys and configures them so that all references are resolved.
- System administrator: This is the person who makes sure that everything runs, and continues to run, as the users take advantage of everything players one through five have created.
Four categories of EJBs allow developers to fine-tune resource management; these carry through without much change into the CCM, as we'll soon see. There are two types of session beans, which don't have identity and can be used by only one client: stateless and stateful. The former can only be called once. They do their thing on that one call, using only data that you've supplied as input arguments, and may be considered destroyed after the call completes. Stateful session beans, on the other hand, are conversational; they maintain their state from one call to the next, but typically don't store any of it persistently in the database.
There are also two types of entity beans, which have identity and can be registered in JNDI, or whatever naming service you have, and used by multiple clients. They typically represent entities in your database, adding whatever functionality you program into them. EJB divides this category into beans with container-managed and self-managed persistence. CCM divides this category into Process and Entity component types, differing in the way instances are identified; both of these types let you choose between container-managed and self-managed persistence.
EJB Homes add classlike functionality to the environment. Each type has a home, which provides at least its create operation; for entity beans the home also provides a find operation using the identity and a table of instances that the runtime maintains. This concept carries over into CCM.
Distribution is provided by RMI and, increasingly (since Sun has just made this a requirement in the new EJB 2.0 draft specification), by RMI-IIOP. Since the bean-container relationship is a local one, only client-bean (and client-home) interaction goes over the network.
And Now, to CORBA
OMG members, working closely with Sun's Java people, wrote the CCM specification to work closely with EJBs. How closely? The specification defines two levels of components. Basic-level CCM components have the same characteristics as revision 1.1 EJBs, except that their interfaces are defined in OMG IDL and the components themselves may therefore be written in any mapped programming language, not just Java. That's why we discussed EJBs in such detail. Extended-level components have additional features. We like these features a lot, and think that the extended CCM environment will be especially productive.
Before we go off into the features of extended CCMs, however, let's take a closer look at the architectural advantages we get from the tying of basic CCMs to EJBs. Remember that assembly step - the one where we built an application from a bunch of different components? Typically, a final server-side application will consist of multiple component types that call each other to get the entire job done. Each provides a subset of the application's functionality. In spite of their differences, the commonality of CCMs and EJBs lets them also call each other. (This will require a bridge, but only an extremely thin and efficient one due to the commonality of the models.) The bottom line is, when we assemble an application, we can use all of the components in our library - EJBs and basic CCMs together. Configuration files tell our system how to direct calls from one environment to another.
This architectural convergence adds CORBA's multilanguage capability to EJBs, allowing us to build components in whatever languages we need (C++ comes to mind right away) in addition to Java, and assemble them into an application along with our EJBs. EJB programmers can contribute to the libraries of a multilanguage environment without having to learn anything new, while CORBA programmers build components that can be used with the substantial libraries of EJBs, written by programmers who never learned to work in CORBA.
CCM's' interfaces are defined in OMG IDL, extended by the CCM specification to include new keywords including (no surprise here) component. IDL separates interface from implementation for CCMs just as it does for CORBA objects, transparently extending the CCM to the multilanguage CORBA environment. One caveat we hear from people who like the technical aspects of EJBs is, "But it's a single-language environment!" Whether you want to use other languages available today or are worried about the language that will come along sometime in the future and replace Java, the compatibility of EJBs and CCMs should set your mind at ease - on this score, anyway.
The CCM container is a specialized CORBA POA (portable object adapter). Designed to support scalable servers, the POA architecture allows an application to set policies that control (among other things) activation/passivation patterns for the executing code and data that constitute a CCM instance, which, by the way, is called a servant. In terms of resource control, a POA is more flexible than an EJB container, able to support several hundred patterns of instance activation/passivation defined by combinations of seven policy types.
This is our first sighting of a pattern that carries through all of the CCM. In much of CORBA there is a tremendous amount of flexibility, which requires a fair amount of technical knowledge to program. In the CCM, however, the pattern is to wrap these CORBA features in a layer that exposes a simpler, higher-level interface with fewer choices. This makes it easy for business-level developers to pick the right one, and lets the service provide the behavior using generated code. In many parts of CCM the coding required for a service is reduced to zero for developers who are willing to accept default behavior; for example, persistence, transactionality and security all work this way. If you love CORBA but feel intimidated by the programming, CCM is the environment for you!
So, instead of the hundreds of instance activation patterns available to a POA programmer, a CCM programmer gets a choice of four and they're patterned on the EJBs we just examined. There are two variants with nonpersistent component references: the service component, which corresponds to a stateless session EJB, and the session component, which corresponds to a stateful session EJB.
The two CCM types with persistent (and therefore sharable) references don't correspond directly to the two EJB entity types even though one uses that name. Persistence, provided by OMG's new Persistent State Service (PSS), may be controlled by either the component or the container for either of these types. The Process component lacks a key findable via its Home component while the Entity component has this key. Lacking a key, the Process component typically represents a process with a beginning and an end, one that may be interrupted and restarted later: applying for a mortgage, opening a bank account or shopping (where the shopping cart would be a Process component that lives only for the duration of a single shopping trip). Having a key and therefore retrievable by any client, the Entity component well represents permanent constructs, including the mortgage or bank account that we created with our Process components, or a Customer, or whatever.
With this, we leave the basic components behind and enter the extended world.
Multiple Interfaces, Navigation, Segmented Persistence
Figure 1 shows an extended CORBA component with the four interface types that it uses to communicate in standard ways with the world. (There's a separate container-centric view that we won't cover because of its similarity to EJBs.)
Component is a new CORBA type specifically defined to support multiple interfaces and navigation among them. The multiple interfaces of a CCM are termed facets. The CCM infrastructure takes care of all the navigation, generating both the additional IDL operations and the code that supports them. Clients can navigate from any of a component's facets to its main facet, where they can get a list of all supported facets - in many ways, a CORBA analog for IUnknown. Or, if a client already knows where it wants to go, it can navigate from any facet directly to any other one. Extending this concept is segmented persistence, in which the unit of activation/passivation is the facet and its associated code and data, instead of the entire component.
Attributes and Configuration
CCMs may be configured at installation. In a component marketplace this gives a single CCM product the flexibility to fit into multiple application assemblies with varying requirements (as long as they don't vary too much!). Configuration is accomplished by setting values of attributes (see Figure 1) at installation time. Once this is complete, a call to configuration_complete freezes the configuration and enables calls to the CCM's facets.
Receptacles (see Figure 1) are the client-side interfaces that a CCM uses to invoke operations on other CCMs, analogous to the ejb-link feature of EJBs. In CCM, when you can specify client-object couplings in your application configuration file, the system automatically feeds the component reference of its target to a receptacle at invocation time.
CCMs' Persistent State
Persistence of extended CCMs' state is handled by OMG's Persistent State Service. It's a lot more standardized than EJB's persistence, in which you configure container-managed persistence (either automatically or manually) via vendor-specific tools at deployment time, or hard-code database calls into the bean itself for bean-managed persistence. (For basic CCMs the persistence environment is the same as for EJBs.) The PSS lets you define your persistent state in either of two modes: transparent persistence, in which you declare persistent variables in your programming language code, or by using Persistent State Definition Language (PSDL), a superset of OMG IDL that combines the flexibility of bean-managed persistence with standards-based portability.
Another difference between EJBs and extended CCMs is event handling. Based on CORBA's Notification Service, event handling in CCM is totally distributed as all channels, endpoints, sources and sinks (see Figure 1) are either CORBA objects or clients. This lets you couple CCMs in one container with those in another, even across CCM application boundaries. Architecturally, it unifies messaging among components within a container with those in different containers, simplifying structure as applications grow larger. The Notification Service is very capable and flexible, with an elegant structured payload in addition to QoS controls and event typing and filtering. Since Java doesn't define a distributed event service, EJBs lack this capability.
While EJBs allow only one thread to enter a container at a time, extended CCMs allow components that are written thread-safe to execute in a multithreaded container. The setting - either single- or multithreaded - is made in the configuration files.
Many programmers (and their managers!) find the single-language Java environment confining despite its many delightful qualities. Others don't mind being confined to Java now, but know that this limitation will have undesirable consequences in the future. (Even Java applications will wear the "legacy" label someday!) For these people the CCM provides a way out - they can program in EJBs, and either integrate or switch to other languages now or anytime in the future.
We expect many others to look at the features of the extended CCM and adopt it soon after products become available. As we've shown here, the extended features provide the foundation for application architectures that would be much less elegant written any other way.
All of CORBA 3, including the CCM, is now OMG adopted technology. The CCM is currently undergoing its first maintenance revision; under its new procedure OMG waits for this first revision stage to complete before issuing a formal release with the incremented release number. This is scheduled for late 2000; products implementing the CCM are expected to hit the marketplace around the same time.
For more on EJBs check any of Jason Westra's articles in back issues of JDJ, including June and November 1999 (Vol. 4, issues 6, 11), and Rodrigues and Raj's article in August 1999 (Vol. 4, issue 8). For more on CORBA servants and the POA, see my CORBA Corner column in the December 1999 JDJ (Vol. 4, issue 12).
For access to all of OMG's specifications, surf to
http://www.omg.org/gettingstarted/specsandprods.htm. For specifications that
are part of CORBA 3, see
Jon Siegel, the Object Management Group's director of technology transfer, was an early practitioner of distributed computing and OO software development. Jon writes articles and presents tutorials and
seminars about CORBA. He can be contacted at: