Examining How EJB Systems Function


This part of the chapter presents some examples using the concepts discussed so far. First, we can add some information to the earlier table showing the basic characteristics of EJBs. Table 3-1 displays the elements of EJBs by type.

Table 3-1: EJB Elements by Bean Type

EJB Element

Session Bean

Entity Bean

Message-Driven Bean

Interfaces

Yes

Yes

No

EJB classes

Yes

Yes

Yes

Deployment descriptor

Yes

Yes

Yes

Primary key class

No

Yes

No

Helper classes (optional)

Yes

Yes

Yes

Borland’s Enterprise server was used to construct the stateless session bean in the example that follows. Table 3-2 provides a list of components within the J2EE architectural blueprint for this server.

Table 3-2: Borland Enterprise Server Components

Component

Description

Web server

Its services include a version of Apache.

Messaging service

The SonicMQ Message Broker is a core service.

Web container

Tomcat facilitates running JSPs and servlets.

EJB container

The container hosts EJB components and provides core services for low-level tasks such as memory allocation, pooling, etc.

Transaction services

The server manages transactions both internally and externally.

Session services

The server contains session information stored either within JDataStore or another valid JDBC repository.

Naming service

The JNDI supports lookup services.

RMI-IIOP

Remote Method Invocation supports interaction with remote objects.

JDBC

The Java Database Connectivity interface is used to connect to a relational database or a nonrelational database.

EJB

Enterprise JavaBeans represent a specification for creating enterprise components, as well as managing remote and local Java components.

JMS

JMS is a messaging service supporting both synchronous and asynchronous beans.

JavaMail

JavaMail provides the API for SNMP mail systems.

JCA

Java Connectors represent an interface to connect with disparate systems.

The Enterprise JavaBeans component has a well-defined interface. All Enterprise JavaBeans exist and are managed and executed within the container. An EJB component is either an implementation of an interface or extends the EJB class.

The Enterprise container serves as home for all EJB components. It provides the core services for all beans.

Constructing a Session Bean

As you know, stateful session beans represent components dedicated to a single client. They maintain state for a single client only. Inactive bean class instances can be passivated. In contrast, stateless session beans do not maintain state. Therefore, they can be pooled for use by many clients. For example, the sample application in this section retrieves the temperature for a given zip code. Within the IDE, create a new project named SampleSessionBean:

  1. Once the default settings are defined (path and class path, etc.), select an EJB module. This module provides an EJB designer within which the developer can create a new Enterprise JavaBean.

  2. Implement the following properties:

    • Bean name: beanFactory

    • Interfaces: remote

    • Session type: stateless

  3. Once these tasks have been fulfilled, right-click on the new session bean and add the following method as defined here:

    • Method name: getCurrentTemp

    • Return type: int

    • Input parameters: Java.lang.String zipcode

    • Interfaces: remote

  4. Once these tasks are completed, the following interfaces are generated by the container, a great convenience for bean developers:

    • BeanFactory.java

    • BeanFactoryBean.java

    • BeanFactory.Home.java

Let’s examine the three interfaces before implementing the session bean.

Here is the code for BeanFactory.java:

//BeanFactory.java
package com.dps.com.session;

import javax.ejb.*;
import java.util.*;
import java.rmi.*;

public interface BeanFactory extends javax.ejb.EJBHome{
public BeanFactory create() throws CreateException, RemoteException;
}

The BeanFactory.java file contains the contract that will be implemented by the BeanFactoryBean.java file. The interface extends javax.ejb.Home. In addition, the method create() is obligated to throw CreateException and RemoteException.

The BeanFactoryBean.java is the class in which the implementation represents the business logic. Here is code for this class:

/**BeanFactoryBean.java – the getCurrentTemp method
is implemented in this class*/
package com.dps.com.session;

import javax.ejb.*;
import java.util.*;

public class BeanFactoryBean.java implements SessionBean {
SessionContext sessionContext;
public void ejbCreate() throws CreateException { }
public void ejbRemove() { }
public void ejbActivate() { }
public void ejbPassivate() { }
public void setSessionContext(SessionContext sessionContext) {
this.sessionContext = sessionContext;
}
public int getCurrentTemp(java.lang.String zipcode) { }
}
}

Finally, here is the BeanFactoryHome.java interface. This interface is used to create, find, and remove instances for the bean class.

//BeanFactoryHome.java interface
package com.dps.com.session;

import javax.ejb.*;
import java.util.*;
import java.rmi.*;
import samplesessionbean.*;

public interface BeanFactoryHome extends javax.ejb.EJBHome {
public BeanFactory create() throws CreateException, RemoteException;
}

The interfaces have been created for the bean implementation. Now, let’s write the implementation for the business logic:

public int getCurrentTemp(java.lang.String zipcode) {
int currentTemp;
Random rnd = new Random(System.currentTimeMillis());
currentTemp = rnd.nextInt(115);
return currentTemp;
}

The implementation is complete. The next step involves preparing to deploy the bean. Each created EJB must have a deployment descriptor, which describes the configuration and type to the container. The container subsequently examines the descriptor in order to manage the bean. Here is the deployment descriptor for our interface:

<?xml version="1.0" encoding="UTF-8"?>
<!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>
<display-name>BeanFactory</display-name>
<ejb-name>BeanFactory</ejb-name>
<home>com.dps.com.session.BeanFactoryHome</home>
<remote>com.dps.com.session.BeanFactory</remote>
<ejb-class>com.dps.com.session.beanFactoryBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>BeanFactory</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>

The deployment descriptor contains specific information about the beanFactoryBean. It begins with the XML declaration detailing the version and encoding:

<?xml version="1.0" encoding="UTF-8"?>

The next line contains the DTD declaration and includes the official organization that defined this DTD:

<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//
DTD Enterprise JavaBeans 2.0//EN"
"http://java.sun.com/dtd/ejb-jar_2_0.dtd">

The <remote> and <home> tags inform the container about the interfaces for BeanFactory. The <ejb-class> tells the container about the implementation class. The final import tag, <session-type>, tells the container that the bean is either stateless or stateful. In our case, the bean is a stateless session bean.

It is easy to test the bean. Simply generate the file based on the framework generated by the container. Here is the code:

package samplesessionbean;

import com.dps.com.session.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;

public class BeanFactoryTestClient1 extends Object {
private static final String
ERROR_NULL_REMOTE = "Remote interface reference is null.
It must be created by calling one of the
Home interface methods first.";
private static final int MAX_OUTPUT_LINE_LENGTH = 100;
private boolean logging = true;
private BeanFactoryHome BeanFactoryHomeObject = null;
private BeanFactory BeanFactoryObject = null;

//Construct the EJB test client
public BeanFacto ryTestClient1() {
initialize();
}

public void initialize() {
long startTime = 0;
if (logging) {
log("Initializing bean access.");
startTime = System.currentTimeMillis();
}

try {
//get naming context

Context context = new InitialContext();

//look up jndi name
Object ref = context.lookup("BeanFactory");
//look up jndi name and cast to Home interface
BeanFactoryHomeObject = (beanFactoryHome)
PortableRemoteObject.narrow
(ref, BeanFactoryHome.class);
if (logging) {
long endTime = System.currentTimeMillis();
log("Succeeded initializing local bean access
through Local Home interface.");
log("Execution time: " + (endTime - startTime) + " ms.");
}
}
catch(Exception e) {
if (logging) {
log("Failed initializing bean access.");
}
e.printStackTrace();
}
}

/** Methods that use Home interface methods
to generate a Remote interface reference*/


public BeanFactory create() {
long startTime = 0;
if (logging) {
log("Calling create()");
startTime = System.currentTimeMillis();
}
try {
BeanFactoryObject = BeanFactoryHomeObject.create();
if (logging) {
long endTime = System.currentTimeMillis();
log("Succeeded: create()");
log("Execution time: " + (endTime - startTime) + " ms.");
}
}
catch(Exception e) {
if (logging) {
log("Failed: create()");
}
e.printStackTrace();
}


if (logging) {
log("Return value from create(): " + BeanFactoryObject + ".");
}
return BeanFactoryObject;
}

// Methods that use Remote interface methods
to access data through the //bean


public BeanFactory create() {
BeanFactory returnValue = null;

if (BeanFactoryObject == null) {
System.out.println("Error in create(): " + ERROR_NULL_REMOTE);
return returnValue;
}

long startTime = 0;
if (logging) {
log("Calling create()");
startTime = System.currentTimeMillis();
}

try {
returnValue = BeanFactoryObject.create();
if (logging) {
long endTime = System.currentTimeMillis();
log("Succeeded: create()");
log("Execution time: " + (endTime - startTime) + " ms.");
}
}
catch(Exception e) {
if (logging) {
log("Failed: create()");
}
e.printStackTrace();
}

if (logging) {
log("Return value from create(): " + returnValue + ".");
}
return returnValue;
}

public void executeRemoteCallsWithDefaultArguments() {
if (BeanFactoryObject == null) {
System.out.println(
"Error in executeRemoteCallsWithDefaultArguments(): " +
ERROR_NULL_REMOTE);
return ;
}
create();
}

// Utility Methods
private void log(String message) {
if (message == null) {
System.out.println("-- null");
return ;
}
if (message.length() > MAX_OUTPUT_LINE_LENGTH) {
System.out.println("-- "
+ message.substring(0, MAX_OUTPUT_LINE_LENGTH) + " ...");
}
else {
System.out.println("-- " + message);
}
}
//Main method

public static void main(String[] args) {
beanFactoryTestClient1 client = new BeanFactoryTestClient1();
// Use the client object to call one of the Home interface wrappers
// above, to create a Remote interface reference to the bean.
// If the return value is of the Remote interface type, you can use it
// to access the remote interface methods. You can also just use the
// client object to call the Remote interface wrappers.
}
}

Voila! The session bean works! Now, create an EAR file.

  1. Select the EAR icon from the Gallery.

  2. Choose File | New, and choose the Enterprise tab.

  3. Select the EAR node to add it to the project.

  4. Specify the name of the EAR file and node name. Keep the name the same as the project, SessionBean.

  5. Use the EAR Wizard’s six-step guide to complete the process. Step two is the selection of the SessionBeanSample EJB module included in the project.

  6. Step three adds resource adapter archives to the EAR module.

  7. Step four adds other archive nodes to the EAR file.

  8. Step five adds all web modules to the EAR.

  9. Step six adds other resources required for an EAR.

  10. Right-click the SessionBean eargrp and select Make. This creates a SessionBean EAR and contains an application.xml descriptor.

  11. Start the application server and select Deploy to deploy the bean.

Developing a Stateful Session Bean

When writing a stateful session bean, the client is not required to change code in order to use a stateful bean. The only change is how the developer utilizes the bean. Referring to the getCurrentTemp method, rather than passing in the zip code, it is easy to use a mutator function and subsequently call the method as follows:

Package sessionbean;
import java.rmi.*;
import javax.ejb.*;
import javax.naming.*;
class FactoryClient {
public static void main(String([] args) {
try{
InitialContext ctx = new InitialContext();
Object objRef = ctx.lookup("BeanFactory");
beanFactory factoryHome = beanFactoryHome(javax.rmi.PortableRemoteObject.narrow(objRef,
beanFactory Home.class);
beanFactory factory=factoryHome.create();
factory.setZipcode("12354");
System.out.println("Current Temperature is:");
System.out.println(factory.currentTemp());
}
catch (RemoteException ex) {
System.err.println("Remote Exception:" + ex");
}catch (CreateException ex) {
System.err.println("CreateException:" + ex);
}catch (NamingException ex) {
System.err.println("NamingException:" + ex);
}catch (ClassCastException ex) {
System.err.println("Cast Exception:" + ex);
}
}
}

The code underscores how easy it is to use a stateful session bean.

Developing Entity Beans

Developing entity beans consists of a specific task: representing an entity of data from a specified data source. Carrying this thought one step further, an entity of data represents a record in a database. How does the entity bean communicate with the relational data store? It is achieved by interacting with data through an interface rather than sending updates, deletes, inserts, or retrieving data directly to the repository. This technique is called persistence.

Persistence is managed in the following ways:

  • Serialization allows Java objects to suspend the working process of an object from memory, convert it to a byte stream, and persist it to storage.

    Note

    Although object serialization is useful for providing data persistence for small individual objects, it is not appropriate for persisting large objects.

  • Object/relation mapping represents a fast, efficient way of persisting objects. For example, a customer record usually consists of a first and last name, street address, city, state, zip code, and a contact name. These objects are individually mapped to a relational database. This task is achieved manually through the services of a sophisticated mapping tool.

  • An object database management system (ODBMS) stores data directly using the object database API. Utilizing this method eliminates the need for object/ relational mapping.

Entity Bean Characteristics

An entity bean represents an in-memory view of persisted data. The following list provides entity bean characteristics:

  • Entity beans survive container failures. Both container and entity bean instance work in tandem to synchronize the in-memory data with the database. In essence, entity beans remain in memory until they are explicitly removed.

  • Entity beans are ideal for modeling persistent business data such as books, business reports, or employee records.

  • Entity beans are identified by primary keys.

  • Entity beans are sharable by multiple clients, achieved through a process called pooling. Pooling provides efficiency to an entity bean’s application.

  • Entity beans are transactional, meaning transactions are implemented through the use of deployment descriptors.

Entity Bean Types

Recall the two types of entity beans—container-managed persistent beans and bean-managed persistent beans. The CMP entity bean encapsulates the persistent data and business logic. The entity bean instance is directly responsible for creating, managing, synchronizing, and removing the state of the persistent data. BMP entity beans require developers to provide the mechanism for managing object persistence. This includes writing the code to provide data access. With CMP, the container bears the responsibility for generating the necessary code for data access and management. The bean developer must specify the container-managed persistence fields and methods in addition to declaring an abstract persistent schema in the deployment descriptor. The container provides a deployment tool that uses the deployment descriptor and CMP bean class to manage persistence and the life cycle for a CMP entity bean instance.

Let’s compare the entity bean types. Table 3-3 provides the entity bean characteristics.

Table 3-3: Comparing CMP and BMP Entity Bean Characteristics

Bean Type

Container Implemented

Developer Implemented

CMP

ejbActivate()
ejbPassivate()
ejbLoad()
ejbStore()
Abstract get and set methods

Specify abstract methods and abstract persistence schemas
Business logic methods

BMP

None

Business methods
ejbActivate()
ejbPassivate()
ejbLoad()
ejbStore()
ejbRemove()

Note

The bean developer is responsible for implementing an ejbCreate() method and an ejbPostCreate() method that correspond with each create() method signature within the home interface.

Four basic operations exist for manipulating data:

  • Create

  • Read

  • Update

  • Delete

Create relates to ejbCreate() and ejbPostCreate(). Reading is implemented using ejbLoad(). Update refers to ejbStore(), and delete refers to ejbRemove().

An entity bean uses ejbActivate() as a notification mechanism when the entity bean’s instance has been related to a primary key class. ejbPassivate() is called to inform the entity that the primary key is being disassociated from the primary key class and is now available to another entity bean instance.

Creating a CMP Entity Bean

The process of building a CMP bean requires implementing the following steps:

  • Defining the home interface

  • Declaring the appropriate finder methods

  • Implementing the component interface

  • Defining the bean implementation class

  • Constructing the deployment descriptor

  • Deploying the bean

Defining the Home Interface for a CMP Bean

Notice how the home interface is similar to the home interface for a session bean. Its primary tasks are to create an instance, locate existing interfaces, and/or remove an instance. The same is true for the entity bean. Here is the code for building an Employee bean:

//Employee CMP bean
import javax.ejb.*;
import java.util.*;

public interface EmployeeHome extends javax.ejb.EJBLocalHome {
public Employee create(Short empNo) throws CreateException;
public Employee findByPrimaryKey(long empNo) throws FinderException;
}

Note

The findByPrimaryKey is mandatory for all entity beans. Finder methods perform more than one task. In addition to returning a single instance, they also return a collection of instances.

import javax.ejb.*;
import java.util.*;
import java.math.*;

public interface EmployeeHome extends javax.ejb.EJBLocalHome{
public Employee create(Short empNo) throws CreateException;
public Collection findSalaryRange(BigDecimal low, BigDecimal high)
throws FinderException;
public Employee findByPrimaryKey(long empNo) throws FinderException;
}

Note

The findSalaryRange() returns a java.lang.Collection. This collection represents instances of the primary key only.

Constructing the Component Interface

The component interface defines mutator methods for accessing and manipulating the bean’s data.

import javax.ejb.*;
import java.util.*;
import java.sql.*;
import java.math.*;
public interface Employee extends javax.ejb.EJBLocalObject{
public Short getEmpNo();
public void setFirstName(String firstName);
public String getFirstName();
public void setLastName(String lastName);
public String getLastName();
public void setPhoneNo(String phoneNo);
public String getPhoneNo();
public void setSalary(BigDecimal salary);
public BigDecimal getSalary();
public void setFullName(String fullName);
public String getFullName();
}

Implementing the CMP Bean

The CMP EmployeeBean class provides the implementations required for the container to manage the persistence.

abstract public class EmployeeBean implements EntityBean {
EntityContext entityContext;
public java.lang.Short ejbCreate(java.lang.Short empNo)
throws CreateException {
setEmpNo(empNo);
return null;
public void ejbPostCreate(java.lang.Short empNo) throws CreateException {}
public void ejbRemove() throws RemoteException{ }
public abstract void setEmpNo(java.lang.Short empNo);
public abstract void setFirstName(java.lang.String firstName);
public abstract void setLastName(java.lang.String lastName);
public abstract void setPhoneNo(java.lang.String phoneNo);
public abstract void setSalary(java.math.BigDecimal salary);
public abstract void setFullName(java.lang.String fullName);
public abstract java.lang.Short getEmpNo);
public abstract java.lang.String getFirstName();
public abstract java.lang.String getLastName();
public abstract java.lang.String getPhoneNo();
public abstract java.lang.String BigDecimal getSalary();
public abstract java.lang.String getFullName();
public void ejbLoad(){ }
public void ejbActivate() { }
public void ejbPassivate() { }
public void unsetEntityContext() {this.entityContext = null;
}
public void setEntityContext (EntityContext) {
this.entityContext = entityContext;
}
}

The client invokes the create() method of the entity bean’s home interface. The anatomy of a descriptor is examined in detail in Chapter 4 along with a discussion on RMI-IIOP and creating JAR files.

Developing a BMP Bean

Bean-managed persistence requires implementing a specific interface. This interface maps to a relational database. Table 3-4 demonstrates how SQL statements relate to bean methods.

Table 3-4: SQL Statements Map to Bean Methods

Bean Method

SQL Statement

ejbCreate

INSERT

ejbFindByPrimaryKey

SELECT

ejbFindByLastName

SELECT

ejbFindInRange

SELECT

ejbLoad

SELECT

ejbRemove

DELETE

ejbStore

UPDATE

Defining the Home Interface for a BMP Bean

The home interface is essentially the same as the CMP’s Employee home interface. The package is added to the code as follows:

package entitybeansample;

import javax.ejb.*;
import java.util.*;
public interface EmployeeBMPHome extends javax.ejbLocalHome {
public EmployeeBMP create (Short empNo) throws EJBLocalHome {
public EmployeeBMP findByPrimaryKey(Short empNo) throws FinderException;
}

Defining the Remote Interface for a BMP Bean

This interface should also look identical to the CMP bean’s remote interface.

public interface EmployeeBMPRemote extends javax.ejb.EJBObject{
public Short getEmpNo()throws RemoteException;
public void setFirstName(String firstName) throws RemoteException;
public String getFirstName() throws RemoteException;
public void setLastName(String lastName) throws RemoteException;
public String getLastName()throws RemoteException;
public void setPhoneNo(String phoneNo) throws RemoteException;
public String getPhoneNo()throws RemoteException;
public void setSalary(BigDecimal salary) throws RemoteException;
public BigDecimal getSalary()throws RemoteException;
public void setFullName(String fullName) throws RemoteException;
public String getFullName()throws RemoteException;
}

Implementing the BMP Bean

This section details the exceptions for the javax.ebj package. It is always important to deal with error-handling in Java, or for that matter, any programming language. Note the following exceptions:

  • ejbCreate throws the CreateException Invalid input parameter.

  • ejbFindByPrimaryKey throws the ObjectNotFoundException A database row for the entity cannot be found.

  • ejbRemove throws the RemoveException The entity bean cannot be deleted from the database.

  • ejbLoad throws the NoSuchEntityException The database row to be loaded cannot be located.

  • ejbStore throws the NoSuchEntityException The row to be updated cannot be found.

  • All methods throw the EJBException A system failure has occurred.

Next, the bean interface generated by the EJB designer wizards needs to be implemented. Here is the example code:

package entitybeansample;
import java.sql.*;
import javax.naming.*;
import javax.sql.*;

public class EmployeeBMPBean implements EntityBean {
EntityContext entityContext;
java.lang.Short empNo;
java.lang.String firstName;
java.lang.String lastName;
java.lang.String phoneNo;
java.math.BigDecimal salary;
java.lang.String fullName;
public java.lang.Short
ejbCreate(java.lang.Short empNo) throws CreateException {
setEmpNo(empNo);
Connection con = null;
try{
InitialContext initial = new InitialContext();
Datasource ds = (Datasource)initial.lookup
("java:comp/env/jdbc/EmployeeDate");
con = ds.getConnection();
PreparedStatement ps = con.prepareStatement("INSERT INTO employee (empNo)"
+ "values(?)");
ps.setShort(1,empNo.shortValue());
ps.executeUpdate();
return empNo;
}
catch (SQLException ex) {
ex.printStackTrace();
}catch (NamingException ex) {
ex.printStackTrace();
throw new CreateException();
}finally{
if(con!= null){
try {
con.close();
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
}
return null;
}
public void ejbPostCreate(java.lang.Short empNo) throws CreateException{
}
public void ejbRemove() throws RemoveException {
connection con = null;
try {
InitialContext initial = new InitialContext();
DataSource ds = (DataSource)initial.lookup(
"java:comp/env/jdbc/EmployeeData");
con = ds.getConnection();
PreparedStatement ps = con.prepareStatement("DELETE" + "FROM EMPLOYEE
WHERE empNo = ?");
ps.setShort(1,getEmpNo().shortValue());
ps.executeUpdate():
}
catch(SQLException ex) {
ex.printStackTrace();
throw new RemoveException();
} finally{
if (con !=null){
try{
con.close();
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}
public void setEmpNo(java.lang.Short empNo){
this.empNo = empNo;
}
public void setFirstName(java.lang.String firstName){
this.firstName = firstName;
}
public void setLastName(java.lang.String lastName(){
this.lastName = lastName();
}
public void setPhoneNo(java.lang.String phoneNo(){
this.phoneNo = phoneNo();
}
public void setSalary(java.math.BigDecimal salary(){
this.salary = salary();
}
public void setFullName(java.lang.String fullName(){
this.fullName = fullName();
}
public java.lang.Short getEmpNo(){
return empNo;
}
public java.lang.String getFirstName(){
return firstName;
}
public java.lang.String getLastName(){
return lastName;
}
public java.lang.String getPhoneNo(){
return phoneNo;
}
public java.math.BigDecimal getSalary(){
return salary;
}
public java.lang.String getFullName(){
return fullName;
}
public java.lang.Short ejbFindByPrimaryKey(java.lang.Short empNo)
throws FinderException {
Connection con = null;
try {
connection con = null;
try {
InitialContext initial = new InitialContext();
DataSource ds = (DataSource)initial.lookup(
"java:comp/env/jdbc/EmployeeData");
con = ds.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT id FROM EMPLOYEE
WHERE empNo = ?");
ps.setShort(1,getEmpNo().shortValue());
ResultSet rs = ps.executeQuery();
if(rs.next()){
throw new ObjectNotFoundException();
}
return empNo;
}
catch(SQLException ex) {
ex.printStackTrace();
throw new RemoveException();
} finally{
if (con !=null){
try{
con.close();
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}
public void ejbLoad(){
Connection con = null;
InitialContext = new InitialContext();
DataSource ds =(DataSource)initial.lookup(
"java:comp/env/jdbc/EmployeeData");
con = ds.getConnection();
PreparedStatement ps = con.prepareStatement(
"SELECT EmpNo, DeptNo,FirstName," + "FullName,
LastName,PhoneNo,Salary " + "FROM
EMPLOYEE WHERE empNo = ?");
ps.setShort(1,getEmpNo.shortValue());
ResultSet rs = ps.executeQuery();
if(rs.next()){
throw new EJBException("Object not located");
}
setFirstName(rs.getString(3));
setFullName(rs.getString(4));
setLastName((rs.getString(5));
setPhoneNo(rs.getString(6));
setSalary(rs.getBigDecimal(7));
}
catch(SQLException ex) {
ex.printStackTrace();
throw new RemoveException();
} finally{
if (con !=null){
try{
con.close();
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}
public void ejbStore(){
Connection con = null;
InitialContext = new InitialContext();
DataSource ds =(DataSource)initial.lookup(
"java:comp/env/jdbc/EmployeeData");
con = ds.getConnection();
PreparedStatement ps = con.prepareStatement(
"UPDATE employee " + FirstName = ?, FullName = ?,
LastName = ?," + PhoneNo = ?, Salary = ? WHERE empNo = ?");
ps.setString(2,getFirstName());
ps.setString(3,getFirstName());
ps.setString(4,getFullName());
ps.setString(5,getLastName());
ps.setString(6,getPhoneNo());
ps.setBigDecimal(7,getSalary());
ps.setShort(8,empNo.shortValue());
ps.executeUpdate());
}
catch(SQLException ex) {
ex.printStackTrace();
} (NamingException ex){
ex.printStackTrace();
new RemoveException();
} finally{
if (con !=null){
try{
con.close();
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}

public void ejbActivate(){
}
public void ejbPassivate(){
}
public void unSetEntityContext(){
this.entityContext = null;
}
public void setEntityContext(EntityContext entityContext){
this.entityContext = entityContext;
}
}

The deployment descriptor is slightly different from the CMP bean. (See the discussion of descriptors in Chapter 4.) Deploying the BMP entity bean is no different from deploying a CMP entity bean. Just as before, the home interface creates, finds, and removes entity instances. The client test would be easy to write. Try one as an exercise.

Considering Message-Driven Beans

Message-driven beans provide a convenient methodology for implementing an onMessage(), which in turn implements an appropriate response to a message received. The container manages the services required to implement and wrap the Java Message Service (JMS). In essence, a client may initiate a message from a web page, or another bean.

An MDB represents a message consumer that implements business logic. Also, an MDB is similar to a stateless session bean. A single instance can be shared by multiple clients. Here is how an MDB functions:

  • A message producer writes a message and sends it to a specific topic (more about this in a moment).

  • A message consumer subscribes to a specified topic to receive messages.

  • The message is delivered from the topic to interested subscribers.

Point-to-Point Compared with Publish/Subscribe

The point-to-point technology is employed when only a single consumer receives a message. The technique used here is as follows:

  • A message producer sends a message to a specified queue.

  • Each queue has a unique name within the container’s naming service.

  • Subsequently, the message is received by the queue, and the identified queue forwards the message to a single registered client.

The publish/subscribe business model is typically used for general broadcasts. The message server defines a topic. A subject is created for managing messages. Then, a message is created by a producer and sent to a specified topic. The topic receives the message and then delivers the message to all registered subscribers.

Creating MDBs

Here is the basic procedure and some rules for creating MDBs:

  • Create a class that implements the javax.ejb.MessageDrivenBean interface.

  • Implement the javax.jms.MessageListener interface.

  • Create a public constructor with an empty constructor.

  • Implement the ejbCreate() method with no arguments.

  • Declare the method as public.

  • The return type must be void.

  • The procedure must declare any application exceptions.

The javax.ejb.MessagedrivenBean has only two methods, and they must be implemented:

  • void ejbRemove() throws EJBException

  • void setMessageDrivenContext(MessageDrivenContext messageDrivenContext) throws EJBException

The listener interface implements the method for processing incoming messages. See the following code:

package javax.jms.*;
public abstract interface MessageListener {
void onMessage(Message message);
}

The message-driven bean’s onMessage() method executes all business logic for the EJB. Here is the interface for message-driven beans:

package javax.ejb;
public abstract interface MessageDrivenBean extends EnterpriseBean {
void ejbRemove() throws EJBException;
void setMessageDrivenContext(MessageDrivenContext messageDrivenContext)
throws EJBException;
}

Note

Remember that the message-driven bean does not contain either a remote/local home interface or a remote/local interface. MDB developers must ensure that all message processing is asynchronous.

The following code displays the message-driven bean source for implementing EmployeeMDBBean.java:

package messagebean;
import java.text.*;
import java.util.*;
import javax.ejb.*;
import javax.jms.*;
import javax.naming.*'

public class EmployeeMDBBean implements MessageDrivenBean, MessageListener {
private transient MessageDrivenContext mds = null;
private Context context;
public EmployeeMDBBean() { }

public void setMessageDrivenContext(MessageDrivenContext mdc)
{
this.mdc = mdc;
}
public void ejbCreate() { }
public void onMessage(Message inMessage) {
try{
if(inMessage instanceof MapMessage){
MapMessage map = (MapMessage)inMessage){
System.out.Println("Urgent Message");
System.out.Println("Name: " + map.getString("name"));

sendNote(map.getstring("Email"));
}else {
System.out.println("Incorrect message type");
}
}
catch Exception ex) {
ex,printStackTrace();
}
}

private void sendNote(String recipient){
try{
Context initial = new InitialContext();
javax.mail.Session session = (javax.mail.Session)
initial.lookup("java:comp/env/MailSession");
javax.mail.Message msg = new javax.mail.internet.MimeMessage(session);
msg.setRecipients(javax.mail.MessageRecipientType.TO,
javax.mail.internet.InternetAddress.parse(recipient,false));
msg.setSubject("Just for your Information");

DateFormat dateFormatter = DateFormat.getDateTimeInstance
(DateFormat.LONG, DateFormat.SHORT);
Date timestamp = new Date();

String messageText = "This message is urgent" + '\n' + "your friend";
msg.settext(messageText);
msg.setSentDate(timestamp);
javax.mail.Transport.send(msg);
}
catch (Exception ex){
throw new EJBException(ex.getMessage());
}
}
public void ejbRemove() {
System.out.println("EmployeeMDBBean.ejb.Remove() called.");
}
}




.NET & J2EE Interoperability
Microsoft .NET and J2EE Interoperability Toolkit (Pro-Developer)
ISBN: 0735619220
EAN: 2147483647
Year: 2004
Pages: 101
Authors: Simon Guest

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