Showing posts with label ejb examples. Show all posts
Showing posts with label ejb examples. Show all posts

Saturday, 24 December 2011

Running the SavingsAccountEJB Example

Setting Up the Database

The instructions that follow explain how to use the SavingsAccountEJB example with a Cloudscape database. The Cloudscape software is included with the J2EE SDK download bundle.
  1. From the command-line prompt, run the Cloudscape database server by typing cloudscape -start. (When you are ready to shut down the server, type cloudscape -stop.)
  2. Create the savingsaccount database table.
    1. Go to the j2eetutorial/examples directory
    2. Type ant create-savingsaccount-table.
You may also run this example with databases other than Cloudscape. (See the Release Notes of the J2EE SDK for a list of supported databases.) If you are using one of these other databases, you may run the j2eetutorial/examples/sql/savingsaccount.sql script to create the savingsaccount table.

Deploying the Application

  1. In deploytool, open the j2eetutorial/examples/ears/SavingsAccountApp.ear file (FileOpen).
  2. Deploy the SavingsAccountApp application (ToolsDeploy). In the Introduction dialog box, make sure that you select the Return Client JAR checkbox.

Running the Client

  1. In a terminal window, go to the j2eetutorial/examples/ears directory.
  2. Set the APPCPATH environment variable to SavingsAccountAppClient.jar.
  3. Type the following command on a single line:
    runclient -client SavingsAccountApp.ear -name
          SavingsAccountClient -textauth
     
    
  4. At the login prompts, enter guest for the user name and guest123 for the password.
  5. The client should display the following lines:
    balance = 68.25
       balance = 32.55
       456: 44.77
       730: 19.54
       268: 100.07
       836: 32.55
       456: 44.77
       4.00
       7.00

Remote Interface

The remote interface extends javax.ejb.EJBObject and defines the business methods that a remote client may invoke. Here is the SavingsAccount remote interface:
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
import java.math.BigDecimal;

public interface SavingsAccount extends EJBObject {
    
    public void debit(BigDecimal amount)
        throws InsufficientBalanceException, RemoteException;

    public void credit(BigDecimal amount)
        throws RemoteException;
 
    public String getFirstName()
        throws RemoteException;

    public String getLastName()
        throws RemoteException;
   
    public BigDecimal getBalance()
        throws RemoteException;
}
 
The requirements for the method definitions in a remote interface are the same for both session and entity beans:
  • Each method in the remote interface must match a method in the enterprise bean class.
  • The signatures of the methods in the remote interface must be identical to the signatures of the corresponding methods in the enterprise bean class.
  • The arguments and return values must be valid RMI types.
  • The throws clause must include java.rmi.RemoteException.
A local interface has the same requirements, with the following exceptions:
  • The arguments and return values are not required to be valid RMI types.
  • The throws clause does not include java.rmi.RemoteException.

Database Calls

Table 5-1 summarizes the database access calls in the SavingsAccountBean class. The business methods of the SavingsAccountBean class are absent from the preceding table because they do not access the database. Instead, these business methods update the instance variables, which are written to the database when the EJB container calls ejbStore. Another developer might have chosen to access the database in the business methods of the SavingsAccountBean class. This choice is one of those design decisions that depend on the specific needs of your application.
Before accessing a database, you must connect to it.
Table 5-1 SQL Statements in SavingsAccountBean 
MethodSQL Statement
ejbCreateINSERT
ejbFindByPrimaryKeySELECT
ejbFindByLastNameSELECT
ejbFindInRangeSELECT
ejbLoadSELECT
ejbRemoveDELETE
ejbStoreUPDATE

Home Methods

A home method contains the business logic that applies to all entity beans of a particular class. In contrast, the logic in a business method applies to a single entity bean, an instance with a unique identity. During a home method invocation, the instance has neither a unique identity nor a state that represents a business object. Consequently, a home method must not access the bean's persistence state (instance variables). (For container-managed persistence, a home method also must not access relationships.)
Typically, a home method locates a collection of bean instances and invokes business methods as it iterates through the collection. This approach is taken by theejbHomeChargeForLowBalance method of the SavingsAccountBean class. The ejbHomeChargeForLowBalance method applies a service charge to all savings accounts with balances less than a specified amount. The method locates these accounts by invoking the findInRange method. As it iterates through the collection of SavingsAccount instances, theejbHomeChargeForLowBalance method checks the balance and invokes the debit business method. Here is the source code of the ejbHomeChargeForLowBalance method:
public void ejbHomeChargeForLowBalance(
    BigDecimal minimumBalance, BigDecimal charge) 
    throws InsufficientBalanceException {

   try {
       SavingsAccountHome home =
       (SavingsAccountHome)context.getEJBHome();
       Collection c = home.findInRange(new BigDecimal("0.00"),
           minimumBalance.subtract(new BigDecimal("0.01")));

       Iterator i = c.iterator();

       while (i.hasNext()) {
          SavingsAccount account = (SavingsAccount)i.next();
          if (account.getBalance().compareTo(charge) == 1) {
             account.debit(charge);
          }
       }

   } catch (Exception ex) {
       throw new EJBException("ejbHomeChargeForLowBalance: " 
           + ex.getMessage());
   } 
} 
 
The home interface defines a corresponding method named chargeForLowBalance. Since the interface provides the client view, the SavingsAccountClientprogram invokes the home method as follows:
SavingsAccountHome home;
...
home.chargeForLowBalance(new BigDecimal("10.00"), 
   new BigDecimal("1.00"));
 
In the entity bean class, the implementation of a home method must adhere to these rules:
  • A home method name must start with the prefix ejbHome.
  • The access control modifier must be public.
  • The method modifier cannot be static.
The throws clause may include exceptions that are specific to your application; it must not throw the java.rmi.RemoteException.

ejbLoad and ejbStore Methods

If the EJB container needs to synchronize the instance variables of an entity bean with the corresponding values stored in a database, it invokes the ejbLoad and ejbStore methods. TheejbLoad method refreshes the instance variables from the database, and the ejbStore method writes the variables to the database. The client may not call ejbLoad and ejbStore.
If a business method is associated with a transaction, the container invokes ejbLoad before the business method executes. Immediately after the business method executes, the container callsejbStore. Because the container invokes ejbLoad and ejbStore, you do not have to refresh and store the instance variables in your business methods. The SavingsAccountBean class relies on the container to synchronize the instance variables with the database. Therefore, the business methods of SavingsAccountBean should be associated with transactions.
If the ejbLoad and ejbStore methods cannot locate an entity in the underlying database, they should throw the javax.ejb.NoSuchEntityException. This exception is a subclass ofEJBException. Because EJBException is a subclass of RuntimeException, you do not have to include it in the throws clause. When NoSuchEntityException is thrown, the EJB container wraps it in a RemoteException before returning it to the client.
In the SavingsAccountBean class, ejbLoad invokes the loadRow method, which issues a SQL SELECT statement and assigns the retrieved data to the instance variables. The ejbStoremethod calls the storeRow method, which stores the instance variables in the database with a SQL UPDATE statement. Here is the code for the ejbLoad and ejbStore methods:
public void ejbLoad() {

   try {
      loadRow();
   } catch (Exception ex) {
      throw new EJBException("ejbLoad: " + 
         ex.getMessage());
   }
}

public void ejbStore() {

   try {
      storeRow();
   } catch (Exception ex) {
      throw new EJBException("ejbStore: " + 
         ex.getMessage());
   }
}

ejbRemove Method

A client deletes an entity bean by invoking the remove method. This invocation causes the EJB container to call the ejbRemove method, which deletes the entity state from the database. In theSavingsAccountBean class, the ejbRemove method invokes a private method named deleteRow, which issues a SQL DELETE statement. The ejbRemove method is short:
public void ejbRemove() {
    try {
        deleteRow(id);
    catch (Exception ex) {
        throw new EJBException("ejbRemove: " +
        ex.getMessage());
    }
}
 
If the ejbRemove method encounters a system problem, it should throw the javax.ejb.EJBException. If it encounters an application error, it should throw a javax.ejb.RemoveException. 
An entity bean may also be removed directly by a database deletion. For example, if a SQL script deletes a row that contains an entity bean state, then that entity bean is removed.

ejbPostCreate Method

For each ejbCreate method, you must write an ejbPostCreate method in the entity bean class. The EJB container invokes ejbPostCreate immediately after it calls ejbCreate. Unlike theejbCreate method, the ejbPostCreate method can invoke the getPrimaryKey and getEJBObject methods of the EntityContext interface. For more information on the getEJBObjectmethod. Often, your ejbPostCreate methods will be empty.
The signature of an ejbPostCreate method must meet the following requirements:
  • The number and types of arguments must match a corresponding ejbCreate method.
  • The access control modifier must be public.
  • The method modifier cannot be final or static.
  • The return type must be void.
The throws clause may include the javax.ejb.CreateException and exceptions that are specific to your application.