October 2004
Enterprise JavaBeans (EJB) was introduced for building distributed components.
When it arrived it came with a promise to solve all issues and complexities
of CORBA. EJB being the heart of J2EE went through several major revisions and
got fattened with many features. Early on, most of the developers fell in love
with EJB and used EJB in their application even it did not make any sense. “Blame
it on EJB” has been the attitude for many developers when their projects
did not scale well and they used EJB.
Development of EJB was never easier and it became more complex with every release
of EJB specification. EJB has been compared with an elephant due to its complexity
and heavy weight nature. Many developers feel EJB is like an extra layer of
sugar syrup on a doughnut. In an age where low carb and Atkins diet is craze,
the EJB expert committee has no option but to produce a low carb incarnation
of EJB thus simplifying the development of EJB. EJB 3.0 expert committee released
a sample picture of the lightweight model during JavaOne 2004 when it announced
release of first public draft of EJB
3.0 Specification.
At the first glimpse the new model for EJB looks pretty and in this article
we will discuss how EJB 3.0 is trying to dress up in a smaller size pretty outfit
to make it appealing for developers. In a follow up article we will discuss
how EJB 3.0 is simplifying the persistence model.
Cleaning up the Dirty Laundry
Let us look at the complexities in the current EJB model before we dive down
discussing the details what EJB 3.0 is bringing on to the table.
- The current EJB model requires creation of several component interfaces
and implementation of several unnecessary callback methods.
- The component interfaces require implementation of EJBObject
or EJBLocalObject and handling of many unnecessary exceptions
is required.
- The EJB deployment descriptor is complex and error prone.
- The container managed persistence being based on the EJB model is again
overly complex to develop and manage. There are several basic features missing
such as a standard way to define a primary key using database sequence and
EJBQL is very limited.
- EJB components do not look like its Object Oriented as it has restrictions
for using inheritance and polymorphisms.
- One major drawback of EJBs is that you cannot test EJB modules outside an
EJB container and debugging an EJB inside the container is a nightmare for
developers.
- If you used EJB you know the complexities of looking up and invocation
of EJB. It appears that you have to know minute details of JNDI to just use
an EJB in your application.
Simplifying Developers view
If you developed an EJB with the latest specification you realize how difficult
is develop a simple EJB like HelloWorld EJB. You need at least two interfaces,
a bean class and a deployment descriptor. Most of the developers wondered why
do I need all these. IDEs like Oracle
JDeveloper, Eclipse
and XDoclet
made the life simple for developers for doing these mundane tasks however still
it was the responsibility of developer to compile these classes and package
the deployment descriptor before the EJB can be deployed in your container of
choice.
EJB 3.0 is trying to address the complexities by:
- Removing need of interfaces and deployment descriptors and these may be
generated by the container using metadata annotations
- Use regular Java classes as EJBs and regular business interfaces for EJBs
Metadata Annotations
EJB 3.0 depends heavily on metadata annotations. Metadata annotation being
standardized under JSR
175 and will be part of J2SE
5.0. Annotation is a kind of attribute oriented programming and similar
to XDoclet. However unlike XDoclet that requires pre-compilation, annotations
are compiled into the classes (depending upon what the @Retention is set to)
by the Java compiler at compile-time. In developer’s point of view, annotations
are modifiers like public and can be used in classes, fields, methods, parameters,
local variables, constructors, enumerations and packages.You can use annotations
in your Java code by specifying attributes that can be used for either generating
code, documenting code or providing special services such as enhanced business-level
security or special business logic during runtime. The goal of J2EE 1.5 (5.0)
is to simplify development using annotations and hence it will come up with
its set of annotations. Annotations are marked with @ as follows:
@Author("Debu Panda")
@Bean
public class MySessionBean
The goal of EJB 3.0 is to simplify development and hence use metadata annotations
to generate several artifacts like interfaces and use annotations instead of
deployment descriptors.
Using POJOs and POJIs
In canonical terms, JavaBeans and interfaces often referred as Plain Old Java
Objects (POJOs) and Plain Old Java Interfaces (POJIs) respectively. The EJB
class and interface will now resemble POJO and POJI respectively. The requirement
of the unnecessary artifacts like home interface is being removed.
The developer has to either implement one of the EJB interfaces (SessionBean,
EntityBean or MessageDrivenBean)
in javax.ejb
package or use annotation in the bean implementation class. You can either
use Stateless,
Stateful, MessageDriven or Entity
to annotate your bean class. For example, if you define a stateless EJB as HelloWorld
you define the EJB as follows:
@Remote
@Stateless public class HelloWorldBean {
public String sayHello(String s)
{ System.out.println("Hello: "+s; }
}
The interfaces for EJBs either remote or local do not have to implement EJBObject
or EJBLocalObject.
You have to either supply the business interface for your EJB and implement
that interface in your bean class or have it generated during the deployment.
Interfaces are optional for Entity beans however required for SessionBean
and MessageDrivenDriven.
If you do not implement an interface for your session bean, a bean interface
will be generated for you. The type of generated interface either local or remote
is dependent on the annotation you used in the bean class. If you look at the
above code example, it is very clear that @Remote
is used to generate a remote interface for the HelloWorld
bean. If needed, you may have both remote and local interfaces for your EJB.
From the above example, it is very clear that the developer do not have to
a lot of mundane tasks such as defining interfaces and implementing callback
methods.
The name of the generated interface is derived from the name of the bean implementation
class. Generated interfaces are well and good for developers. However, I do
not see any benefit of generating interfaces as most IDE like Oracle JDeveloper
generates these on fly.
This is not clear from the draft what is client side requirement for EJB lookup
and it is not clear, how do we get hold of these interfaces those are required
to invoke this EJB? I will recommend against using a generated interface for
few reasons:
- The name of generated interface will be derived from the bean name
- You may not be willing to expose some methods in the EJB in the interface
and the generated interface may expose all methods by default.
- You need the interface at the client side to invoke the EJB.
Removing need for Callback methods
EJB 2.1 and prior releases required implementation of several lifecycle methods
such as ejbPassivate, ejbActivate, ejbLoad, ejbStore,
etc. for every EJB even if you do not need those. For example, ejbPassivate
is not required for a stateless session bean still you require to implement
that method in your bean class. As EJB 3.0 now resembles regular Java classes
implementation of these lifecycle methods have been made optional. If you implement
any callback method in the EJB then container will invoke that method.
The only exception is the ejbRemove
method in Stateful Session bean where you can use Remove
annotation to annotate a Stateful session bean business method. If you use of
this annotation it will hint the container to remove the Stateful session bean
instance after the completion (normal or abnormal) of the annotated method.
For example, you can specify the following to remove a Stateful Session Bean
instance after checkOut method is executed.
@Stateful public class Cart {
...
...
@Remove public void checkOut() {
...
}
}
Annotations vs. deployment descriptors
As we discussed earlier deployment descriptors will no longer be required
for EJBs and annotations will be used instead. The default values for each attribute
in the deployment descriptor will be chosen and developers do not have to specify
these attributes unless they want a value other than the default value. These
can be specified using annotations in the bean class itself. The EJB 3.0 specification
is defining a set of metadata annotations for use by developers such as bean
type, type of interfaces, resource references, transaction attributes, security,
etc. For example, if we want to resource reference for a particular EJB then
we will define as follows:
@Resource(name="jdbc/OracleDS", resourceType="javax.sql.DataSource")
J2EE vendors such as Oracle, BEA, IBM will add annotations for attributes in
their vendor specific deployment descriptors and developers will use these to
avoid using deployment descriptors. This looks very attractive for developers
as the nasty XML descriptors they hated most gets out of their way but this
introduces few problems and we need to be careful before embracing annotations.
- This defeats the goal of portability of applications because if an EJB
uses a vendor specific deployment descriptor this cannot be just changed without
having to recompiling/repackaging the EJBs.
- The deployment descriptors provided a holistic view of EJB modules to the
assembler/deployer (ejb-jar) without having to look at individual the EJBs
and they tweaked these as per the deployment requirement and if descriptors
are not available or not generated until the end of deployment this could
be a nightmare for them.
- Deployment descriptors were used by the tools to identify the EJBs in an
EJB module and were very useful when you try to migrate from one container
to another.
EJB 3.0 spec also proposes a way to override the annotations in the deployment
descriptors. However details of overriding annotations is missing in the specification.
There is no doubt that getting rid of deployment descriptors will make the
life easier for new developers but this may become a management nightmare if
not used carefully.
Simplifying Container Managed Persistence
CMP entity bean is getting a major overhaul in EJB 3.0 to make it compelling
for developers. Persistence frameworks like OracleAS
TopLink, open source Hibernate
have become darling of developing persistence framework for J2EE applications
that has disliked Entity beans for its complexity and heavyweight in nature.
EJB 3.0 is adopting a lightweight persistence model like TopLink and Hibernate
to simplify the container managed persistence and this sounds compelling for
developers. Let us do a quick look on the plans for entity beans and we will
discuss about the details of the persistence improvement in another article.
Entity beans are being reincarnated as POJOs and there will be no component
interfaces required for entity beans. Entity beans will now look as pure objects
as this will also support inheritance and polymorphism.
Following is the source code for an entity bean:
@Entity public class Employee{
private Long empNo;
private String empName;
private Address address;
private Hashmap projects = new Hashmap();
private Double salary;
@Id(generate=SEQUENCE) public Long getEmpNo() {
return empNo;
}
protected void setEmpNo(Long empNo) {
this.empNo = empNo;
}
public String getEmpName() {
return EmpName;
}
public void setEmpName(String EmpName){
this.EmpName = EmpName;
}
@Dependent public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Set getProjects() {
return projects;
}
public void setProjects(Set projects) {
this.projects = projects;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
....
}
If you look at the code, you will find that the bean class is a concrete class
and not an abstract class the current entity bean.
There are several improvements are being made for the query capabilities in
EJB QL and support of SQL queries in the entity beans. A new EntityManager API
similar to Hibernate and a simplified version of TopLink’ Session API
is being proposed to manipulation of entity beans i.e. creation, removal, finding
of entity beans.
We will closely examine the details of the proposed CMP entity beans in a
followup article.
Simplifying Client View for EJBs
Using EJBs i.e. to lookup and invoke is very complex even if EJB is collocated
in the application. J2EE 1.4 and EJB 3.0 spec is working on to simplify the
client’s view of EJBs.
If you want to use an EJB presently you have to define the ejb-ref or ejb-local-ref
in the deployment descriptor, lookup the EJB and then invoke. If we want to
invoke our HelloWorld EJB, following is the simplest way you can invoke an EJB
with the current implementation.
First define the EJB references in the deployment descriptor as follows:
<ejb-ref>
<ejb-ref-name>HelloWorldEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>hello.HelloWorldHome</home>
<remote> hello.HelloWorld</remote>
</ejb-ref>
Then lookup the EJB as follows. You have to explicitly handle exceptions for
EJB lookup and creation of a bean instance.
try
{
Context context = new InitialContext();
HelloWorldHome helloHome =
(HelloWorld)PortableRemoteObject.narrow(context.lookup
("java:comp/env/ejb/HelloWorldEJB"), HelloWorldHome.class);
HelloWorld hello = helloHome.create();
....
}
catch(RemoteException e)
{
System.err.println("System/communication error: " + e.getMessage());
}
catch(NamingException e)
{
System.err.println("Communication error: " + e.getMessage());
}
catch(CreateException e)
{
System.err.println("Error creating EJB instance: " + e.getMessage());
}
As an alternative to environment variables, EJB 3.0 proposes a way to use setter
injection to lookup and invoke EJBs.
Following is way our HelloWorldEJB can be looked up in another EJB by using
setter injection.
@Inject private void setSessionContext(SessionContext ctx)
{
this.ctx = ctx
}
...
myHello = (HelloWorld)ctx.lookup("java:comp/env/ejb/HelloWorldEJB");
If you look at the code above carefully the setSessionContext
method is annotated with @Inject to specify that
dependency injection be used for this method. The injected methods will be invoked
by the container to set the EJBContext before any business method be called
on that EJB.
Another direct example to inject the HelloWorld session bean would be to simply
have @EJB public HelloWorld myHello and
this would cause myHello to be injected with an instance of the HelloWorld bean.
You can use dependency injection to lookup any type of environment and resource
references such as DataSource, JMS, Mail, Web Service, etc.
Testability Usability Outside Container
A major concern for the current EJB developers is not only development of
EJBs is complex but also testing is a nightmare. An EJB container is required
is to develop and test the EJBs and the developers have to be familiar with
the final deployment platform to perform testing. This may not be a major issue
for many enterprise developers but is an issue for ISVs who work on supporting
multiple vendors and they have to maintain multiple environments to do the testing
of their EJBs. The EJB 3.0 spec promises to provide the ability to test outside
the container but this is currently missing in the draft specification.
Conclusion
Although there are a lot of missing information about packaging, assembly
and gory details of APIs, the proposals made in EJB 3.0 drafts looks very promising
for enterprise java developers. These will certainly help remove the complexities
from developers view by passing those to the container vendors. It is to be
seen how the container vendors implement these and make EJB 3.0 a compelling
option to develop enterprise applications.
References and further reading
Author Bio
Debu Panda is a principal product manager of Oracle Application Server development
team, where he focuses his efforts on the EJB container and Transaction Manager.
He has more than 13 years of experience in the IT industry and has published
articles in several magazines and has presented at many technology conferences.
His J2EE-focused weblog can be found at http://radio.weblogs.com/0135826/.
PRINTER FRIENDLY VERSION
|