An Enterprise JavaBean provides reusable, portable J2EE component. It comprises of methods that encapsulate business logic for instance: updating employee data in database can be business logic and it can be in EJBean. The business methods (in EJB) can be invoked by local and remote clients. As an EJBean developer, you have to only focus on business logic that has to be in the bean. Issues like transaction management, clustering, caching, messaging between applications and others are handled by the container.

You must be aware of Plain Old Java Objects (POJOs). EJBeans are developed as POJOs and annotations are used to tell the container how to manage the beans.


Features

Some worth mentioning features of EJBeans 3.0 are listed below:
No need of home and object interface.
No need of any component interface.
Made use of java annotations.
Simplifies APIs to make flexible for bean's environment.


EJB Context

By context we mean environment at runtime. It’s important for a bean to know its context like security principle, transaction context and so on. An API javax.ejb.EJBContext serves the purpose. EJBContext is categorized into SessionContext and MessageDrivenContext for the session beans and message driven beans respectively. There are two ways in which bean instances can access the EJBContext. You may use the dependency injection or you may use lookup() method of the EJBContext interface. Bean must use the JNDI API to access the environmental dependencies.


Types of EJBs

EJBeans comprises of three main types: Session, Entity, and Message-Driven. We use session bean to perform business task like checking credit history for a customer. Entity bean represents a business object that exists in the database. A Message-Driven bean is used to receive asynchronous JMS messages.


Session Beans

Actions or tasks of business process are represented by session beans. Session beans are classified into two: stateful or stateless.


Stateless Session Beans

Stateless session beans are those, who do not keep track of the information that is passed from one method call to another. Thus, they don’t have internal state and each invocation of a stateless business method is independent of its previous invocation. These beans are simple to manage for the container. For example: tax calculation is a business task and we can have a bean for that. It will simply calculate the tax for an employee. It can be a stateless session bean since each time we call it, we need it to calculate tax of a different employee which has nothing to do with the previous results.

The container maintains a pool of stateless session beans. When a client requests a stateless session bean, he gets an instance from the pool. A point to note is that stateless session beans can be shared. So, the container can manage many clients even with less number of stateless session beans.
A Java bean is specified as stateless session bean by simply adding the annotation @Stateless to the bean. An example of stateless session bean is presented below. It is a simple stateless session bean implementing the incrementValue() method of the CalculateEJB interface.

Java Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
import javax.ejb.Stateless.*;
 
@Stateless(name="CalculateEJB")
public class CalculateEJBBean
implements CalculateEJB
{
int value = 0;
public String incrementValue()
{
value++;
return "value incremented by 1";
}
}
Now let me present a more meaningful example of stateless session bean. First step is to define the remote interface. It’s a simple interface with an added annotation Remote.

Java Code:
1
2
3
4
5
6
7
8
9
10
import java.math.*;
import javax.ejb.Remote;
import java.lang.annotation.*;
@Remote
public interface CalculatorRemote {
 public float add(float x, float y);
 public float subtract(float x, float y);
 public float multiply(float x, float y);
 public float division(float x, float y);
}
The stateless session bean is presented below. It implements the four business methods (add, subtract, multiply, division) that are defined in the CalculatorRemote business interface.

Java Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.math.*;
import javax.ejb.Stateless;
import javax.ejb.Remote; 
 
@Stateless(name="CalculatorBean")
@Remote(CalculatorRemote.class
public class CalculatorBean implements CalculatorRemote{
  public float add(float x, float y){  
    return x + y;
   }
 
   public float subtract(float x, float y){
      return x - y;
   }
    public float multiply(float x, float y){
      return x * y;
   }
   public float division(float x, float y){
     return x / y;
   }
}
Note that, the @Stateless annotation decorating the enterprise bean class. This lets the container know that CalculatorBean is a stateless session bean.


Stateful Session Beans

If you need to maintain conversational state across method invocations, then use stateful session beans. As the name implies, these beans maintain the internal state. For instance: Online shopping is an example of stateful session bean. We need to maintain the state of the bean when the customer adds/removes items from the cart.

It is right to say that stateful session beans are transient. The reason is that the state does not survive session termination, system crash, or network failure. A client is assigned one stateful instance on request, and the state of the bean is maintained for that client by the container. To remove the instance of stateful session bean, write a method and add the annotation
@Remove to the method.

An example of stateful session bean is presented below:

Java Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Stateful(entityContext=INSTANCE)
public class AuctionFacadeImpl implements AuctionFacade {
private Item item;
private ItemDAO itemDAO;
@Inject public void setItemDAO(ItemDAO dao) {
this.itemDAO = dao;
}
public Item getItem(Long itemId) {
item = itemDAO.findById(itemId);
return item;
}
@Remove
public Bid bidForItem(User user, BigDecimal amount) {
return item.bid(user, amount);
}}
We used @Inject annotation in the above example. Its dependency injection. I will talk about this later.
Now is the time to present a complete example of stateful session bean. First we will define an interface.

Java Code:
1
2
3
4
5
6
7
8
9
10
11
12
public interface Calculator {
 
  public double calculate (int start, int end,
                  double growthrate, double saving);
 
  public ArrayList <Integer> getStarts ();
  public ArrayList <Integer> getEnds ();
  public ArrayList <Double> getGrowthrates ();
  public ArrayList <Double> getSavings ();
  public ArrayList <Double> getResults ();
 
}

The bean implementation follows:

Java Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Stateful
public class StatefulCalculator implements Calculator, Serializable {
 
  public ArrayList <Integer> starts = new ArrayList <Integer> ();
  public ArrayList <Integer> ends = new ArrayList <Integer> ();
  public ArrayList <Double> growthrates = new ArrayList <Double> ();
  public ArrayList <Double> savings = new ArrayList <Double> ();
  public ArrayList <Double> results = new ArrayList <Double> ();
 
  public double calculate (int start, int end,
                           double growthrate, double saving) {
     
    // calculate the result ...
     
    starts.add(Integer.valueOf(start));
    ends.add(Integer.valueOf(end));
    growthrates.add(Double.valueOf(growthrate));
    savings.add(Double.valueOf(saving));
    results.add(Double.valueOf(result));
 
    return result;
  }
 
  public ArrayList <Integer> getStarts () {
    return starts;
  }
 
  // Other getter methods for the attributes ...
}
JSP client is presented below. The StatefulCalculator bean stub is retrieved and associated with the HttpSession object.

Java Code:
1
2
3
4
5
6
7
8
9
10
11
Calculator cal = (Calculator) session.getAttribute("sfsb_cal");
if (cal == null) {
  try {
    InitialContext ctx = new InitialContext();
    cal = (Calculator) ctx.lookup(
            "EJB3Trail/StatefulCalculator/local");
    session.setAttribute ("sfsb_cal", cal);
  } catch (Exception e) {
    e.printStackTrace ();
  }
}

Dependency Injection

A bean may need some environmental entries before it is invoked. The container uses a mechanism called dependency injection to inject the required entries to the bean instance. These entries are put into the bean’s variables or methods. As a bean developer, it’s your duty to tell the container that which method or variables should be injected at runtime. This can be done using the deployment descriptor or annotations. Dependency injection annotations are: @Inject, @EJB, @Resource


Entity Bean

An entity bean represents business entities and manages persistent data. It can be uniquely identified by a primary key. A class is specified as an entity bean by including the @Entity annotation.

Entity beans represent persistent data from the database for example: a sales record from sales table, an employee record from employee table.
Container shares the entity beans 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. You can make fields of entity bean persistent by marking those fields with @Transient annotation. All the fields without @Transient won’t be persisted.

You may create entity beans which contain object/relational mappings and this is done using metadata annotations. Let me present an example to make this clear. 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").

Java Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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();
}
}
O/R Mapping Metadata as annotations

Table mappings: @Table, @SecondaryTable
Column mappings: @Column, @JoinColumn
Associations: @ManyToOne, @OneToOne, @OneToMany, @ManyToMany
Inheritance: @Inheritance, @DiscriminatorColumn
Identifier Version properties: @Id, @Version

An example follows:

Java Code:
1
2
3
4
5
6
7
8
9
10
11
12
...
@ManyToOne(fetch=LAZY)
@JoinColumn(name=“USER_ID”,
nullable=false,
updatable=false)
public User getUser() {
return user;
}
protected void setUser(User user) {
this.user = user;
}
...

Message-Driven Beans

Message-driven beans provide an easy method to implement asynchronous communication. MDBs were created to receive asynchronous JMS messages. An MDB allows J2EE applications to send asynchronous messages that can be later processed by the application. It’s good to know that the setup processes that are required for JMS queues and topics are handled by the container. A MDB has to implement the javax.jms.MessageListener interface and should be annotated with @MessageDriven.

An example is presented below. Its 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 simply prints the contents of the message.

Java Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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'")
}
)
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;
}
}

Client

Now let’s talk about EJB client which is an application that accesses the bean. It can be a stand-alone application, JSP, servlet, or another EJB.
The client will access the methods of an EJB through the remote or local interfaces. Which interface to use, depends where the client is residing. If the client resides in the same JVM as of the bean, then local interface has to be used. In the other case, use remote interface. These interfaces define the bean’s methods, and the implementation is provided by the bean class.
The container generates a proxy for the beans (remote or local object) when a client accesses a method of the bean class. These remote and local object delegates the requests to the corresponding bean instance, and returns the results to the client.

In order to invoke a bean's methods, a client finds the bean by using its name defined in the EJB deployment descriptor. In the example below, a simple bean client is presented which calls methods on a stateless session bean. It finds the bean named "Statelessejb" using the Context object.

Java Code:
1
2
3
4
5
6
7
8
9
10
11
12
import javax.naming.Context;
import javax.naming.InitialContext;
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

Enterprise java beans have become significantly easier with the EJB 3.0 specification. Using annotations really makes development easier and fun. We now use annotations to indicate the type of bean and the exposed methods. So everything is actually done using annotated POJOs and interfaces.