Tuesday, September 4, 2007

Introduction to Enterprise JavaBeans

Introduction to Enterprise JavaBeans




Introduction to Enterprise JavaBeans 3.0


by Lynn Munsinger



The EJB 3.0 specification makes it easier than ever to develop Enterprise
JavaBeans, perhaps encouraging you to consider developing EJBs for the first
time. If that is the case, congratulations, you have successfully avoided the
many pitfalls of EJB developers before you, and can enjoy the ease of EJB 3.0
development. But before you start development, you might want to know what Enterprise
JavaBeans are and what purpose they serve. This article explains the basics
of EJBs and how you can utilize them in a J2EE application.


What is an EJB?

An Enterprise JavaBean (EJB) is a reusable, portable J2EE component. EJBs consist
of methods that encapsulate business logic. For example, an EJB may have business
logic that contains a method to update customer data in a database. A variety
of remote and local clients can invoke this method. Additionally, EJBs run inside
a container, allowing the developer to focus on the business logic contained
in the bean without having to worry about complicated and error-prone issues
such as transaction support, security, and remote object access. EJBs are developed
as POJOs, or Plain Old Java Objects, and developers can use metadata
annotations to specify to the container how these beans are to be managed.


Types of EJBs

EJBs consist of three main types: Session, Entity, and Message-Driven. A Session
bean performs a distinct, de-coupled task, such as checking credit history for
a customer. An Entity bean is a complex business entity which represents a business
object that exists in the database. A Message-Driven bean is used to receive
asynchronous JMS messages. Let's examine these types further:


Session Beans

Session beans generally represent actions in the business process such as
"process order." Session beans are classified based on the maintenance
of the conversation state, either stateful or stateless.




Stateless session beans do not have an internal state. They do not keep track
of the information that is passed from one method call to another. Thus, each
invocation of a stateless business method is independent of its previous invocation;
for example, calculating taxes or shipping charges. When a method to calculate
tax charges is invoked with a certain taxable value, the tax value is calculated
and returned to the calling method, without the necessity to store the caller's
internal state for future invocation. Because they do not maintain state, these
beans are simple to manage for the container. When the client requests a stateless
bean instance, it may receive an instance from the pool of stateless session
bean instances that are maintained by the container. Also, because stateless
session beans can be shared, the container can maintain a lesser number of instances
to serve a large number of clients. To specify that a Java Bean is to be deployed
and managed as a stateless session bean, simply add the annotation @Stateless
to the bean.


A stateful session bean maintains a conversational state across method invocations;
for example, an online shopping cart of a customer. When the customer starts
online shopping, the customer's details are retrieved from the database. The
same details are available for the other methods that are invoked when the customer
adds or removes items from the cart, places the order, and so on. Yet, stateful
session beans are transient because the state does not survive session termination,
system crash, or network failure. When a client requests a stateful session
bean instance, that client is assigned one stateful instance, and the state
of the bean is maintained for that client. To specify to the container that
a stateful session bean instance should be removed upon the completion of a
certain method, add the annotation @Remove to the method.


Session Bean Example









import javax.ejb.Stateless.*;


/**

* A simple stateless session bean implementing the incrementValue()
method of the * CalculateEJB interface.

*/



@Stateless(name="CalculateEJB")


public class CalculateEJBBean

implements CalculateEJB

{

int value = 0;

public String incrementValue()

{


value++;

return "value incremented by 1";

}

}



 


Entity Beans

An entity bean is an object that manages persistent data, potentially uses
several dependent Java objects, and can be uniquely identified by a primary
key. Specify that a class is an entity bean by including the @Entity
annotation. Entity beans represent persistent data from the database, such as
a row in a customer table, or an employee record in an employee table. Entity
beans are also sharable across multiple clients. For example, an employee entity
bean can be used by various clients to calculate the annual salary of an employee
or to update the employee address. Specific fields of the entity bean object
can be made persistent. All fields in the entity bean not marked with the @Transient
annotation are considered persistent. A key feature of EJB 3.0 is the ability
to create Entity beans which contain object/relational mappings using metadata
annotations. For example, to specify that an Entity bean's empId field is mapped
to the EMPNO attribute of the Employees table, annotate the table name using
@Table(name="Employees") and the field using @Column(name="EMPNO"),
as shown in the example below. Additionally, a special feature of EJB 3.0 is
that you can easily test Entity beans during development, as running Entity
beans outside a container is now possible using the Oracle Application Server
Entity Test Harness.



Entity Bean Example








import javax.persistence.*;

import java.util.ArrayList;

import java.util.Collection;


@Entity


@Table(name = "EMPLOYEES")

public class Employee implements java.io.Serializable

{

private int empId;

private String eName;


private double sal;



@Id

@Column(name="EMPNO", primaryKey=true)

public int getEmpId()

{


return empId;

}


public void setEmpId(int empId)

{

this.empId = empId;

}



public String getEname()

{

return eName;

}


public void setEname(String eName)


{

this.eName = eName;

}



public double getSal()

{


return sal;

}




public void setSal(double sal)

{

this.sal = sal;


}



public String toString()

{

StringBuffer buf = new StringBuffer();

buf.append("Class:")


.append(this.getClass().getName()).append(" :: ").append("
empId:").append(getEmpId()).append(" ename:").append(getEname()).append("sal:").append(getSal());

return buf.toString();


}

}



 


Message-Driven Beans

Message-driven beans (MDBs) provide an easier method to implement asynchronous
communication than by using straight Java Message Services (JMS). MDBs were
created to receive asynchronous JMS messages. The container handles most of
the setup processes that are required for JMS queues and topics. It sends all
the messages to the interested MDB. An MDB allows J2EE applications to send
asynchronous messages that can then be processed by the application. To specify
that a bean is an MDB, implement the javax.jms.MessageListener
interface and annotate the bean with @MessageDriven.



Message Driven Bean Example








import javax.ejb.MessageDriven;

import javax.ejb.ActivationConfigProperty;

import javax.ejb.Inject;


import javax.jms.*;

import java.util.*;

import javax.ejb.TimedObject;

import javax.ejb.Timer;

import javax.ejb.TimerService;

@MessageDriven(


activationConfig = {

@ActivationConfigProperty(propertyName="connectionFactoryJndiName",
propertyValue="jms/TopicConnectionFactory"),

@ActivationConfigProperty(propertyName="destinationName",
propertyValue="jms/myTopic"),


@ActivationConfigProperty(propertyName="destinationType",
propertyValue="javax.jms.Topic"),

@ActivationConfigProperty(propertyName="messageSelector",
propertyValue="RECIPIENT = 'MDB'")


}


)


/**

* A simple Message-Driven Bean that listens to the configured JMS Queue
or Topic and gets notified via an * invocation of it's onMessage() method
when a message has been posted to the Queue or Topic. The bean

*
prints the contents of the message.

*/


public class MessageLogger implements MessageListener, TimedObject


{


@Inject javax.ejb.MessageDrivenContext mc;



public void onMessage(Message message)

{

System.out.println("onMessage() - " + message);


try

{

String subject = message.getStringProperty("subject");

String inmessage = message.getStringProperty("message");

System.out.println("Message received\n\tDate: " + new java.util.Date()
+ "\n\tSubject: " + subject + "\n\tMessage: " +
inmessage + "\n");


System.out.println("Creating Timer a single event timer");

TimerService ts = mc.getTimerService();

Timer timer = ts.createTimer(30000, subject);

System.out.println("Timer created by MDB at: " + new Date(System.currentTimeMillis())
+" with info: "+subject);


}

catch (Throwable ex)

{

ex.printStackTrace();

}

}




public void ejbTimeout(Timer timer)

{

System.out.println("EJB 3.0: Timer with MDB");

System.out.println("ejbTimeout() called at: "
+ new Date(System.currentTimeMillis()));


return;

}


}


 



Utilizing EJBs

An EJB client is the application that accesses the bean. It does not necessarily
reside on the client tier, but can be a stand-alone application, JSP, servlet,
or another EJB. The client accesses the methods of an EJB through the remote
or local interfaces of the bean, depending on whether the client resides in
the same or a different JVM than the bean. These interfaces define the methods
of the bean, while the bean class actually implements the methods. When a client
accesses a method of the bean class, the container generates a proxy for the
bean, called the remote or local object. The remote or local object receives
the request, delegates it to the corresponding bean instance, and returns the
results to the client. To invoke a bean's methods, a client finds the bean by
using its name defined in the EJB deployment descriptor. In the following example,
the client finds the bean named "Statelessejb" using the Context object.


EJB Client Example









import javax.naming.Context;

import javax.naming.InitialContext;


/**

* A simple bean client which calls methods on a stateless session bean.

*/


public class CalculateejbClient


{

public static void main(String [] args)

{

Context context = new InitialContext();


CalculateEJB myejb =

(CalculateEJB)context.lookup("java:comp/env/ejb/CalculateEJB");


myejb.incrementValue();

}

}


 




Summary

Developing Enterprise JavaBeans is significantly easier with the EJB 3.0 specification.
The specification uses metadata annotations to define the type of bean and the
methods exposed to the client. Thus, whether you are creating a session bean
for executing a specific task or mapping a table to an entity bean for updating
data, you can do so using plain Java objects and interfaces, and expose methods
for clients by using annotations within the business methods. Now that you have
an understanding of the basics of EJBs, refer to OTN's EJB
3.0 Resources Page
for more information.