Enterprise Beans

Figure 36-2 takes a closer look at the access paths between the clients, enterprise beans, and database tables. As you can see, the end-user clients (web and application clients) access only the session beans. Within the enterprise bean tier, the session beans are clients of the entity beans. On the back end of the application, the entity beans access the database tables that store the entity states.


Note: The source code for these enterprise beans is in the <INSTALL>/j2eetutorial14/examples/bank/src/com/sun/ebank/ejb/ directory.


Duke's Bank Enterprise Beans

Figure 36-2 Enterprise Beans

Session Beans

The Duke's Bank application has three session beans: AccountControllerBean, CustomerControllerBean, and TxControllerBean. (Tx stands for a business transaction, such as transferring funds.) These session beans provide a client's view of the application's business logic. Hidden from the clients are the server-side routines that implement the business logic, access databases, manage relationships, and perform error checking.

AccountControllerBean

The business methods of the AccountControllerBean session bean perform tasks that fall into the following categories: creating and removing entity beans, managing the account-customer relationship, and getting the account information.

The following methods create and remove entity beans:

These methods of the AccountControllerBean session bean call the create and remove methods of the AccountBean entity bean. The createAccount and removeAccount methods throw application exceptions to indicate invalid method arguments. The createAccount method throws an IllegalAccountTypeException if the type argument is neither Checking, Savings, Credit, nor Money Market. The createAccount method also verifies that the specified customer exists by invoking the findByPrimaryKey method of the CustomerBean entity bean. If the result of this verification is false, the createAccount method throws a CustomerNotFoundException.

The following methods manage the account-customer relationship:

The AccountBean and CustomerBean entity beans have a many-to-many relationship. A bank account can be jointly held by more than one customer, and a customer can have multiple accounts. Because the entity beans use bean-managed persistence, there are several ways to manage this relationship. For more information, see Mapping Table Relationships for Bean-Managed Persistence.

In the Duke's Bank application, the addCustomerToAccount and removeCustomerFromAccount methods of the AccountControllerBean session bean manage the account-customer relationship. The addCustomerToAccount method, for example, starts by verifying that the customer exists. To create the relationship, the addCustomerToAccount method inserts a row into the customer_account_xref database table. In this cross-reference table, each row contains the customerId and accountId of the related entities. To remove a relationship, the removeCustomerFromAccount method deletes a row from the customer_account_xref table. If a client calls the removeAccount method, then all rows for the specified accountId are removed from the customer_account_xref table.

The following methods get the account information:

The AccountControllerBean session bean has two get methods. The getAccountsOfCustomer method returns all of the accounts of a given customer by invoking the findByCustomerId method of the AccountBean entity bean. Instead of implementing a get method for every instance variable, the AccountControllerBean has a getDetails method that returns an object (AccountDetails) that encapsulates the entire state of an AccountBean bean. Because it can invoke a single method to retrieve the entire state, the client avoids the overhead associated with multiple remote calls.

CustomerControllerBean

Because it is the AccountControllerBean enterprise bean that manages the customer-account relationship, CustomerControllerBean is the simpler of these two session beans. A client creates a CustomerBean entity bean by invoking the createCustomer method of the CustomerControllerBean session bean. To remove a customer, the client calls the removeCustomer method, which not only invokes the remove method of CustomerBean but also deletes from the customer_account_xref table all rows that identify the customer.

The CustomerControllerBean session bean has two methods that return multiple customers: getCustomersOfAccount and getCustomersOfLastName. These methods call the corresponding finder methods--findbyAccountId and findByLastName--of CustomerBean.

TxControllerBean

The TxControllerBean session bean handles bank transactions. In addition to its get methods, getTxsOfAccount and getDetails, the TxControllerBean bean has several methods that change the balances of the bank accounts:

These methods access an AccountBean entity bean to verify the account type and to set the new balance. The withdraw and deposit methods are for standard accounts, whereas the makeCharge and makePayment methods are for accounts that include a line of credit. If the type method argument does not match the account, these methods throw an IllegalAccountTypeException. If a withdrawal were to result in a negative balance, the withdraw method throws an InsufficientFundsException. If a credit charge attempts to exceed the account's credit line, the makeCharge method throws an InsufficientCreditException.

The transferFunds method also checks the account type and new balance; if necessary, it throws the same exceptions as the withdraw and makeCharge methods. The transferFunds method subtracts from the balance of one AccountBean instance and adds the same amount to another instance. Because both of these steps must complete, the transferFunds method has a Required transaction attribute. If either step fails, the entire operation is rolled back and the balances remain unchanged.

Entity Beans

For each business entity represented in our simple bank, the Duke's Bank application has a matching entity bean:

The purpose of these beans is to provide an object view of these database tables: account, customer, and tx. For each column in a table, the corresponding entity bean has an instance variable. Because they use container-managed persistence, the entity beans contain no SQL statements that access the tables. The enterprise bean container manages all data in the underlying data source, including adding, updating, and deleting data from the database tables.

In addition, a helper entity bean, NextIdBean, is used to create account, customer, and transaction IDs. NextIdBean is the object representation of the next_id table. AccountControllerBean, CustomerControllerBean, and TxControllerBean use NextIdBean's getNextId method when creating new instances of the respective entity beans.

Unlike the session beans, the entity beans do not validate method parameters (except for the primary key parameter of ejbCreate). During the design phase, we decided that the session beans would check the parameters and throw the application exceptions, such as CustomerNotInAccountException and IllegalAccountTypeException. Consequently, if some other application were to include these entity beans, its session beans would also have to validate the method parameters.

Because the entity beans always run in the same Java VM as their clients the session beans, for improved performance the entity beans are coded with local interfaces.

Helper Classes

The EJB JAR files include several helper classes that are used by the enterprise beans. The source code for these classes is in the <INSTALL>/j2eetutorial14/examples/bank/src/com/sun/ebank/util/ directory. Table 36-1 briefly describes the helper classes.

Table 36-1 Helper Classes for the Application's Enterprise Beans 
Class Name
Description
AccountDetails
Encapsulates the state of an AccountBean instance. Returned by the getDetails methods of AccountControllerBean and AccountBean.
CodedNames
Defines the strings that are the logical names in the calls of the lookup method (for example, java:comp/env/ejb/account). The EJBGetter class references these strings.
CustomerDetails
Encapsulates the state of a CustomerBean instance. Returned by the getDetails methods of CustomerControllerBean and CustomerBean.
Debug
Has simple methods for printing a debugging message from an enterprise bean. These messages appear on the standard output of the Application Server when it's run with the --verbose option and in the server log.
DomainUtil
Contains validation methods: getAccountTypes, checkAccountType, and isCreditAccount.
EJBGetter
Has methods that locate (by invoking lookup) and return home interfaces (for example, getAccountControllerHome).
TxDetails
Encapsulates the state of a TxBean instance. Returned by the getDetails methods of TxControllerBean and TxBean.

Database Tables

A database table of the Duke's Bank application can be categorized by its purpose: representing business entities and holding the next primary key.

Tables Representing Business Entities

Figure 36-3 shows the relationships between the database tables. The customer and account tables have a many-to-many relationship: A customer can have several bank accounts, and each account can be owned by more than one customer. This many-to-many relationship is implemented by the cross-reference table named customer_account_xref. The account and tx tables have a one-to-many relationship: A bank account can have many transactions, but each transaction refers to a single account.

Duke's Bank Database Tables

Figure 36-3 Database Tables

Figure 36-3 uses several abbreviations. PK stands for primary key, the value that uniquely identifies a row in a table. FK is an abbreviation for foreign key, which is the primary key of the related table. Tx is short for transaction, such as a deposit or withdrawal.

Table That Holds the Next Primary Key

The next_id table has a column, bean_type, that stores the type of ID, and a column named id. The value of id is the next primary key that is passed to the create method of an entity bean. For example, before it creates a new AccountBean entity bean, the AccountControllerBean session bean must obtain a unique key by invoking the getNextId method of NextIdBean. The getNextId method reads the id from the next_id table, increments the id value in the table, and then returns the id.

Protecting the Enterprise Beans

In the J2EE platform, you protect an enterprise bean by specifying the security roles that can access its methods. In the Duke's Bank application, you define two roles--bankCustomer and bankAdmin--because two categories of operations are defined by the enterprise beans.

A user in the bankAdmin role will be allowed to perform administrative functions: creating or removing an account, adding a customer to or removing a customer from an account, setting a credit line, and setting an initial balance. A user in the bankCustomer role will be allowed to deposit, withdraw, and transfer funds, make charges and payments, and list the account's transactions. Notice that there is no overlap in functions that users in either role can perform.

The system restricts access to these functions to the appropriate role by setting method permissions on selected methods of the CustomerControllerBean, AccountControllerBean, and TxControllerBean enterprise beans. For example, by allowing only users in the bankAdmin role to access the createAccount method in the AccountControllerBean enterprise bean, you deny users in the bankCustomer role (or any other role) permission to create bank accounts.