Inheritance


Inheritance plays a large role in object-oriented programming. Its primary purpose is in the reuse of existing code and in the polymorphism of objects. Thus as with the component paradigm, in this topic we also meet the aspect of reuse. While the Enterprise JavaBeans specification 1.0 does not touch on the topic of inheritance at all, in version 1.1 there is a paragraph in the appendix devoted to it. There it is mentioned that the concept of inheritance is not defined for components. Nonetheless, the bean developer is allowed to use the standard mechanisms of the Java language, namely, the inheritance of interfaces and classes. The same holds for versions 2.0 and 2.1 of the EJB specification. However, there it is mentioned that component inheritance is a topic that will be dealt with in one of the next versions of the EJB specification (see [21]).

If one considers the significant aspects of a component (see Chapter 2), then the question presents itself as to what benefit inheritance of components might offer. Components are self-contained building blocks that offer a particular functionality and whose behavior should be externally configurable only within certain limits. Components hide their internal workings and present themselves to the outside world only through their interfaces (a black box). A framework, for example, is typically a white box approach; that is, one can examine it and see its architecture and participating classes, and it is necessary, in fact, to customize it to achieve a useful functionality from the framework. It is general practice in the implementation of a component to make use of the class and interface inheritance. However, what does inheritance look like when applied to the components themselves (or in our case, to Enterprise Beans)?

We shall discuss this issue using the bank account example. Say we have a checking account, savings account, and foreign currency account. All three types have the same properties (all possess an account number and account state), and they all have a certain functionality in common (one can query the current state, make deposits and withdrawals, etc.).

Figure 9-10 shows the class Bankaccount, which offers the basic functionality. The derived classes change the existing functionality as required (for example, one cannot exceed a certain limit in withdrawals from the checking account). The derived classes extend the basis class with additional properties (such as an interest credit in the savings account, a service charge in the checking account) and include additional functions (such as an interest calculation at the end of an interest period). Thus Bankaccount is a collective term for foreign currency, checking, and savings accounts. If Figure 9-10 where to show the fundamental structures of a framework for bank applications, then the class Bankaccount would surely be an abstract class. No bank offers only a generic bank account. A customer always has specialized accounts, such as a checking account. Thus an instance of type Bankaccount is useless, since the class Bankaccount simply offers the basic functionality, which taken by itself is of little practical interest. It is only when a bank account is specialized to an account such as a checking account that the code in the class Bankaccount can be usefully deployed.

click to expand
Figure 9-10: Inheritance in the bank account example.

Let us transpose this discussion to Enterprise JavaBeans and components. Does it make sense to model an Enterprise Bean (component) of type Bankaccount with the goal of modeling a basis for specialized derivations? A component that models a collective notion? Such a component would then have to be an abstract component, since there would be no sense in using it at run time. What would the deployment descriptor of an abstract component look like? A complicating factor is that the notion of component inheritance is not well defined. Nor, moreover, is there consensus about what component inheritance should look like.

Since in the specification of Enterprise JavaBeans component inheritance is expressly not supported, there cannot be a useful inheritance at the Enterprise Bean level. The reason for this is to be found in the create and find methods of the home interface of an Enterprise Bean. If there were an (abstract) Enterprise Bean Bankaccount, one could not use its create method to generate a Savingsaccount bean. In this case the bank account cannot serve as a factory to generate derived classes. But what purpose does a create method of an abstract component serve, if not for the generation of derived components?

The problem with the find methods is similar. Let us suppose that the home interface of the bank account bean possesses a find method that returns all accounts with a negative balance. If one calls this method, one can be certain that the set of results contains only checking and foreign currency accounts. Savings accounts cannot have a negative balance, and the bank does not offer any accounts of type Bankaccount. A list is to be created to notify the owners of the overdrawn accounts returned by this find method. With the checking accounts an overdraft charge is to be computed. The EJB container, which is responsible for the instantiation of Enterprise Beans and their remote interface implementations, would then generate instances of type Bankaccount, since the find method was called on the home interface of the bank account bean. No instances of type checking account or foreign currency account would be generated, since it knows nothing about inheritance relations. There is also no way to provide it with this knowledge. To call a method on an element of the set of results would be dangerous, since the specialized functionality of the derived Enterprise Bean types is unavailable. Particular methods like the calculation of the overdraft fee are completely unavailable. A type casting would lead to an exception, since the EJB container has actually generated nothing but Bankaccount instances. Polymorphism would be possible only if the EJB container knew about the inheritance relation. It would then generate the actual types of Enterprise Beans and their remote interface implementations, which then would appear to the client in the result set as all of type Bankaccount. The client would then be able to execute a type casting or to determine the actual type of the account with the help of the instanceof operator.

In a certain sense, an Enterprise Bean can be polymorphic. An interface Bankaccount could serve as the basis for the remote interface of special Enterprise Bean types. Then savings, checking, or foreign currency accounts could be treated together as bank accounts. For purposes of reusability an abstract class Bankaccount could be modeled from which the Enterprise Bean classes of the other account types inherit. Such a process is specifically approved by the specification. To model an Enterprise Bean Bankaccount from which the specialized Enterprise Beans inherit would be sensible only if actual accounts could be used polymorphically over their find and create methods. But as already mentioned, there is no support for this in the specification.

An alternative to inheritance with components is the development of configurable components. In the example that we have described, a (concrete) Enterprise Bean Bankaccount could be developed that contained, according to its configuration, a savings account, checking account, or foreign currency account. Through the development of configurable components a certain sort of polymorphism can be achieved. This polymorphism does not, however, refer to the type of the component, but to the configuration values of the particular instance. To implement such a component, a framework can be set up that is built on class inheritance. Figure 9-11 represents such an architecture schematically.

click to expand
Figure 9-11: Architecture of a configurable component.

The class Bankaccount is an abstract base class that provides the methods of the remote interface of the Enterprise Bean Bankaccount. Derived from this are the concrete classes Savingsaccount, Checkingaccount, and Currencyaccount. When the bank account bean is initialized in one of the methods of the Enterprise Bean interface, it reads its configuration, for example, from the bean environment. It relays its configuration to an instance of the class AccountFactory, which selects a bank account implementation that is suitable for the configuration (savings, checking, or foreign currency). The AccountFactory class generates an instance and initializes it according to the configuration. This mechanism could also be provided with the necessary information using the persistent data of the particular account instead of the configuration data from the environment. The Enterprise Bean Bankaccount contains a reference to the instance of the particular account generated by the account factory. All calls to the methods of the remote interface are then delegated to this instance.

Through such an architecture the component remains clearly structured and easily extendible. It is assumed that a reasonable collection of methods of the remote interface can be defined for the various types. Through this process component inheritance can be gotten around quite elegantly. The component preserves its black-box character, while internally it uses a framework (white box) to achieve the requisite flexibility. The find and create methods of the home interface are fully usable. Polymorphism arises not through the type of the component, but through the values bound to a particular instance. The behavior of the component is determined corresponding to these instance-oriented values. The client could determine the actual type of a bank account through, say, a method getAccountType of the remote interface instead of with the instanceof operator. Particular methods of the remote interface could, moreover, be callable only for particular account types. The particular methods could demonstrate this, for example, through throwing an exception of type IllegalOperationException. However, from the documentation of the component it must be clear for which account types these methods may be called.

Configurable components that use class and interface inheritance internally in connection with a framework for necessary flexibility are an alternative to component inheritance that should be taken seriously. Complete support for inheritance in the component model of Enterprise JavaBeans would significantly increase their complexity. The container would have to be notified of the inheritance relation, in that the inheritance structure would have to be described declaratively in the deployment descriptor. In the case of entity beans, the persistence brings additional complexity. Component inheritance would also have an effect on the persistence manager. It, too, would have to know about the inheritance relation in order to be able to set the affected tables in proper relation to one another. Furthermore, it would have to enable the formulation of search requests for polymorphic components. The additional run-time overhead in the use of finder methods in the EJB container would detract from performance. For each element of the result set, the actual type would have to be determined. There remains the question of whether such additional complexity is justified by the increased usefulness.

Finally, we would like to point out the implementations of inheritance in the component model in [6] and [33], as well as the implementations of bean inheritance in [10].




Enterprise JavaBeans 2.1
Enterprise JavaBeans 2.1
ISBN: 1590590880
EAN: 2147483647
Year: 2006
Pages: 103

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net