Developing an EJB with BMT

Today we'll develop an EJB with BMT through an example adapted from our university registration system. We'll also demonstrate the use of servlets as controllers in the Web tier, and use a JavaBean object to transfer data between the EJB tier and the Web tier.

The following are the main steps required in developing an EJB component with BMT:

1.
In the EJB's deployment descriptor, the bean developer sets the transaction type in the <transaction-type> tag to the value Bean to specify a bean-managed demarcation.

2.
The client application uses JNDI to obtain an object reference to the UserTransaction object to establish a transaction context.

3.
The client application begins a transaction using the begin() method of the UserTransaction object, and issues a request to the EJB through the EJB container. All operations on the EJB execute within the scope of a transaction. If a call to any of these operations raises an exception (either explicitly or as a result of a communication failure), the exception can be caught and the transaction can be rolled back using the rollback() method of the UserTransaction object. If no exceptions occur, the client application commits the current transaction using the commit() method. This method ends the transaction and starts the processing of the operation. The transaction is committed only if all the participants in the transaction agree to commit.

4.
The commit() method causes the EJB container to call the transaction manager to complete the transaction.

5.
The transaction manager is responsible for coordinating with the resource managers to update any databases.

Developing the Bean's Remote Interface

For our example, you implement the Student EJB as a stateful session bean, where you define all business methods in the Student remote interface. Listing 18.1 shows the remote interface Student.java.

Listing 18.1. The Remote Interface Student.java
package day18;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
import java.sql.SQLException;

public interface Student extends EJBObject
{
  public void setupDB() throws RemoteException;
  public StudentInfo getStudent (String id)
       throws RemoteException, SQLException;
  public void addStudent (StudentInfo Student)
       throws RemoteException, SQLException;
  public void updateStudent (StudentInfo Student)
       throws RemoteException, SQLException;
  public void deleteStudent (String id)
       throws RemoteException, SQLException;
}

The remote interface uses the StudentInfo JavaBean class as a helper class to transfer data between the EJB tier and the Web tier.

Developing the Bean's Home Interface

The home interface StudentHome defines the life cycle methods of the EJB (see Listing 18.2). The home interface is stored in the StudentHome.java file.

Listing 18.2. The Home Interface StudentHome.java
package day18;
import javax.ejb.EJBHome;
import javax.ejb.CreateException;
import java.rmi.RemoteException;
public interface StudentHome extends EJBHome
{
  public Student create () throws RemoteException, CreateException;
}

Developing the Bean's Class

The bean class implements all the methods in both the remote and home interfaces. Listing 18.3 displays the code to implement all business methods and life cycle methods.

Listing 18.3. The Bean Class StudentBean.java
package day18;
import java.io.*;
import javax.ejb.*;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import java.rmi.RemoteException;
import javax.transaction.*;

public class StudentBean implements SessionBean{
  SessionContext ctx;
  DataSource ds = null;
  String id     = null;
  String fname = null;
  String lname = null;
  String address   = null;

  public void setupDB()
       throws RemoteException
  {
     System.out.println("Settingup Database...");
      try {
        InitialContext ctx = new InitialContext();
        ds = (DataSource)ctx.lookup("java:comp/env/jdbc/styejbDB");
     }catch (Exception ex) {
         ex.printStackTrace();
     }
   }

  public StudentInfo getStudent(String id)
       throws RemoteException, SQLException
  {
    try {
       String sql = "SELECT * " +
          "FROM STUDENTS " +
          "WHERE STUDENT_ID ='";
      Connection conn = ds.getConnection();
      System.out.println("Conntected to DB...");
      Statement stmt = conn.createStatement();
      ResultSet rs = stmt.executeQuery(sql+id+"'");
      System.out.println("Getting Result...");
      while(rs.next()){
        id = rs.getString(1);
        fname = rs.getString(2);
        lname = rs.getString(3);
        address = rs.getString(4);
       }
      conn.close();
       System.out.println("Returning Student Info...");
       return (new StudentInfo (id, fname, lname, address));

      }catch (java.sql.SQLException e) {
         throw new RemoteException("SQL failed: " + e.getMessage());
     }catch (Exception ex) {
         ex.printStackTrace();
     }
     return null;
  }

  public void addStudent(StudentInfo st)
       throws RemoteException, SQLException
  {
     UserTransaction ut = ctx.getUserTransaction ();
      try {
       System.out.println("addStudent: Starting new transaction...");
   ut.begin ();

   String sql = "INSERT INTO STUDENTS VALUES(" + st.id +
                ",'" + st.fname  +
                "', '" + st.lname  +
                "', '" + st.address + "')";
       Connection conn = ds.getConnection();
       Statement stmt = conn.createStatement();
   stmt.executeUpdate(sql);
   ut.commit ();
   stmt.close();
       conn.close();
   System.out.println("addStudent: transaction committed...");
      }catch (java.sql.SQLException e) {
         try{
          System.out.println("addStudent: transaction rolled back...");
           ut.rollback();
         } catch (SystemException ex) {
           throw new RemoteException("Rollback failed: " + ex.getMessage());
          }

      }catch (Exception e) {
        try{
           ut.rollback();
         } catch (SystemException ex) {
           throw new RemoteException("Rollback failed: " + ex.getMessage());
         }
     }
  }

  public void updateStudent(StudentInfo st)
       throws RemoteException, SQLException
  {
     UserTransaction ut = ctx.getUserTransaction ();
      try {
       System.out.println("updateStudent: Starting new transaction...");
   ut.begin ();

   String sql = "UPDATE STUDENTS SET FNAME  ='" + st.fname  +
                "', LNAME ='" + st.lname  +
                "', ADDRESS ='" + st.address    +
         "' WHERE STUDENT_ID=";
       Connection conn = ds.getConnection();
       Statement stmt = conn.createStatement();
   stmt.executeUpdate(sql+st.id);
   ut.commit ();
   stmt.close();
       conn.close();
   System.out.println("updateStudent: transaction committed...");
      }catch (java.sql.SQLException e) {
         try{
          System.out.println("updateStudent: transaction rolled back...");
             ut.rollback();
           } catch (SystemException ex) {
             throw new RemoteException("Rollback failed: " + ex.getMessage());
       }

      }catch (Exception e) {
          try{
             ut.rollback();
           } catch (SystemException ex) {
             throw new RemoteException("Rollback failed: " + ex.getMessage());
           }
       }
  }

    public void deleteStudent(String id)
    throws RemoteException, SQLException
    {
       UserTransaction ut = ctx.getUserTransaction ();
   try {
         System.out.println("deleteStudent: Starting new transaction...");
     ut.begin ();
     String sql = "DELETE FROM STUDENTS WHERE STUDENT_ID=";
     Connection conn = ds.getConnection();
      Statement stmt = conn.createStatement();
     stmt.executeUpdate(sql+id);
     ut.commit ();
     stmt.close();
      conn.close();
     System.out.println("deleteStudent: transaction committed...");
   }catch (java.sql.SQLException e) {
           try{
          System.out.println("deleteStudent: transaction rolled back...");
             ut.rollback();
           } catch (SystemException ex) {
             throw new RemoteException("Rollback failed: " + ex.getMessage());
       }
   }catch (Exception e) {
          try{
             ut.rollback();
           } catch (SystemException ex) {
             throw new RemoteException("Rollback failed: " + ex.getMessage());
           }
       }
  }
  public void ejbCreate () throws RemoteException, CreateException {}
  public void ejbRemove() {}
  public void setSessionContext (SessionContext ctx) {this.ctx = ctx;}
  public void ejbActivate () {}
  public void ejbPassivate () {}
}

In the preceding code, the EJB obtains the transaction context from the EJBContext maintained by the container, and uses it across all methods of the bean.

Developing Helper Classes

The helper class StudentInfo implemented as a JavaBean, which is used as a data container (data bean) to transfer data between the EJB tier and the Web tier, as shown in Listing 18.4.

Listing 18.4. Helper Class StudentInfo.java
package day18;

public class StudentInfo implements java.io.Serializable {
  public String fname = null;
  public String lname = null;
  public String id = null;
  public String address = null;
  public StudentInfo (String ID, String fname, String lname, String address){
    this.fname = fname;
    this.lname = lname;
    this.id = ID;
    this.address = address;
  }
}

Packaging the Beans into a JAR File

The deployment descriptor for the Student EJB is listed in the following code (see Listing 18.5). The EJB developer sets the <session> tag with the <transaction-type> to Bean so that the EJB will manage its own state. There is no mechanism for an application assembler to affect enterprise beans with bean-managed transaction demarcation. The application assembler must not define transaction attributes for an enterprise bean with bean-managed transaction demarcation.

Listing 18.5. Standard Deployment Descriptor ejb-jar.xml
<?xml version="1.0"?>
<!DOCTYPE ejb-jar PUBLIC
'-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN'
'http://java.sun.com/dtd/ejb-jar_2_0.dtd'>
<ejb-jar>
   <enterprise-beans>
      <session>
         <ejb-name>Student</ejb-name>
         <home>day18.StudentHome</home>
         <remote>day18.Student</remote>
         <ejb-class>day18.StudentBean</ejb-class>
         <session-type>Stateful</session-type>
         <transaction-type>Bean</transaction-type>
         <resource-env-ref>
							<resource-env-ref-name>jdbc/styejbDB</resource-env-ref-name>
							<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
							</resource-env-ref>
      </session>
   </enterprise-beans>
</ejb-jar>

Listing 18.6 displays the vendor-specific weblogic-ejb-jar.xml, which is required when you deploy this component in WebLogic Server.

Listing 18.6. Standard Deployment Descriptor weblogic-ejb-jar.xml
<?xml version="1.0"?>
<!DOCTYPE weblogic-ejb-jar PUBLIC
'-//BEA Systems, Inc.//DTD WebLogic 6.0.0 EJB//EN'
'http://www.bea.com/servers/wls600/dtd/weblogic-ejb-jar.dtd'>

<weblogic-ejb-jar>
  <weblogic-enterprise-bean>
    <ejb-name>Student</ejb-name>
       <reference-descriptor>
         <resource-env-description>
							<res-env-ref-name>jdbc/styejbDB</res-env-ref-name>
							<jndi-name>jdbc.styejbDB</jndi-name>
							</resource-env-description>
        </reference-descriptor>
    <jndi-name>day18/MyStudentHome</jndi-name>
  </weblogic-enterprise-bean>
</weblogic-ejb-jar>

Developing the Testing Client

To test the Student EJB, you need to develop the client application. The client code delegates the Student session bean to update data in the database. The Student EJB performs these tasks through a bean-managed transaction demarcation. Listing 18.7 provides the code you need to use for the client.

Listing 18.7. Client for Testing Code Client.java
package day18;
import javax.naming.Context;
import java.rmi.*;
import javax.naming.InitialContext;
import java.util.Hashtable;

public class Client {
  public final static String id = "100";
  public static StudentInfo info = null;
  public static void main (String[] argv) {
   System.out.print("
Day 18: Demonstration the use of BMT
");
   try{
    // get handle to the Student object
    System.out.println ("Connecting to a Student EJB..");
    Context ctx = new InitialContext();
    Object obj = ctx.lookup("day18/MyStudentHome");
    StudentHome studentHome = (StudentHome)
         javax.rmi.PortableRemoteObject.narrow(obj, StudentHome.class);
    Student student = (Student) studentHome.create ();
    student.setupDB();
    try{
      System.out.println ("Try deleting student with id="+id);
      student.deleteStudent(id);
     }catch (Exception e){
            System.out.println("Record does not exist...");
     }
    System.out.println ("Try adding a new student");
    info = new StudentInfo(id, "Snow", "White", "161 MAIN ST, ELK GROVE, CA");
    student.addStudent(info);
    System.out.println ("Requesting the student info...");
    info = student.getStudent(id);
    System.out.println ("Student Info = " +
                               info.id + ", " +
                               info.fname + ", " +
                               info.lname + ", " +
                               info.address);
    // Modify student info
    info.id = id;
    info.fname = "John";
    info.lname = "Doe";
    info.address="111 CASPER DR, SACRAMENTO, CA";
    // Update student in the database
    System.out.println ("Updating the student info...");
    student.updateStudent (info);
    info = student.getStudent (id);
    System.out.println ("Student Info = " +
                                  info.id + ", " +
                                  info.fname + ", " +
                                  info.lname + ", " +
                               info.address);
   }catch ( Exception e){
            System.out.println("Student transaction failed...");
         e.printStackTrace();
  }
 }
}

Deploying and Running the Student EJB

Before deploying the Student EJB, you must first build the example. Build scripts are provided for both WebLogic Server and the JBoss server. The following are the steps required to build and deploy the Student EJB with BMT in any of the servers.

1.
Configure both the JDBC DataSource and connection pool as described on Day 9.

2.
Build the example for the appropriate application server. From the directory day18, run the build script. This creates a subdirectory named build that contains all the compiled code. The following is an example for WebLogic:

c:>cd c:styejb
c:styejb>setEnvWebLogic.bat
c:styejb>cd day18
c:styejbday18>buildWebLogic.bat
								

3.
To run the example, use the appropriate script for each server. Set up the environment for the client in a new command window, and then use the run script in the day18 directory:

c:styejb>setEnvWebLogic.bat
c:styejb>cd day18
c:styejbday18> runClientWebLogic.bat
								

Similarly, to set the environment, build and deploy the code, and then run the client in the JBoss server, you must use the scripts setEnvJboss.bat, buildJBoss.bat, and runClientJboss.bat, respectively.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.83.96