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.
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:
12345678910111213import
javax.ejb.Stateless.*;
@Stateless
(name=
"CalculateEJB"
)
public
class
CalculateEJBBean
implements
CalculateEJB
{
int
value =
0
;
public
String incrementValue()
{
value++;
return
"value incremented by 1"
;
}
}
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:
12345678910import
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);
}
Note that, the @Stateless annotation decorating the enterprise bean class. This lets the container know that CalculatorBean is a stateless session bean.Java Code:
123456789101112131415161718192021import
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;
}
}
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:
We used @Inject annotation in the above example. Its dependency injection. I will talk about this later.Java Code:
123456789101112131415@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);
}}
Now is the time to present a complete example of stateful session bean. First we will define an interface.
Java Code:
123456789101112public
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:
JSP client is presented below. The StatefulCalculator bean stub is retrieved and associated with the HttpSession object.Java Code:
1234567891011121314151617181920212223242526272829@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 ...
}
Java Code:
1234567891011Calculator 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").
O/R Mapping Metadata as annotationsJava Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748import
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();
}
}
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:
123456789101112...
@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:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546import
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:
123456789101112import
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.
Wednesday, August 8, 2012
Enterprise JavaBean 3.0
Label:
Pemrograman
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment
Udah di baca kan.... kritik dan sarannya saya persilahkan ^_^..jangan lupa isi Buku tamunya juga ya...