|
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.
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.
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.
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:
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.
Implement the following properties:
Bean name: beanFactory
Interfaces: remote
Session type: stateless
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
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.
Select the EAR icon from the Gallery.
Choose File | New, and choose the Enterprise tab.
Select the EAR node to add it to the project.
Specify the name of the EAR file and node name. Keep the name the same as the project, SessionBean.
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.
Step three adds resource adapter archives to the EAR module.
Step four adds other archive nodes to the EAR file.
Step five adds all web modules to the EAR.
Step six adds other resources required for an EAR.
Right-click the SessionBean eargrp and select Make. This creates a SessionBean EAR and contains an application.xml descriptor.
Start the application server and select Deploy to deploy the 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 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.
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.
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.
Bean Type | Container Implemented | Developer Implemented |
---|---|---|
CMP | ejbActivate() | Specify abstract methods and abstract persistence schemas |
BMP | None | Business methods |
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.
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
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. |
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();
}
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.
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.
Bean Method | SQL Statement |
---|---|
ejbCreate | INSERT |
ejbFindByPrimaryKey | SELECT |
ejbFindByLastName | SELECT |
ejbFindInRange | SELECT |
ejbLoad | SELECT |
ejbRemove | DELETE |
ejbStore | UPDATE |
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;
}
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;
}
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.
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.
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.
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.");
}
}
|