Skip to main content

Using Annotations on the Java EE 5.0 Platform

May 22, 2007

{cs.r.title}



One of the important objectives of Java EE 5 Platform is ease
of development. The new features are targeted to shift the
responsibility of writing the boilerplate code from the programmer
to the compiler or other tools. The resulting code is less likely
to be bug-prone.

One of these new ease-of-development features is the
metadata facility--annotations. Annotations provide a
mechanism for decorating Java classes, interfaces, fields, and
methods with metadata information. Annotations are considered an
alternative to the XML files required by the earlier versions of
Java EE. Annotations are also used for dependency injections of
resources, web services, and lifecycle notifications into a Java EE
5 platform application. Annotation features are provided as part of
JSR 175: A Metadata
Facility for the Java Programming Language.

In this article, we will first have a look at annotations and
annotation types. Then we go on to discuss in detail how
annotations support injecting dependencies into resources like data
sources, mail sources, environment entries, EJBs, web services,
and so on.

A Bird's Eye View of Annotations

An annotation is a modifier, like a meta-tag, that provides the
ability to associate additional data along with Java classes,
interfaces, constructors, methods, fields, parameters, and local
variables. An annotation type definition, which is used to
define an annotation, takes the form of an "at" sign (@)
followed by the interface keyword plus the annotation name. On
the other hand, an annotation, the meta-tag that you will
use in your code, takes the form of an "at" sign
followed by the annotation type.

An annotation type can be defined as:


public @interface SampleAnnotation {
        String displayMsg();
}

The annotation type defined above can be used as follows:


@SampleAnnotation(displayMsg = "This is a Sample Annotation")
public void someMethod() {
        .........
}

These annotations do not affect the semantics of the program
directly. Tools like the compiler and other development and
deployment tools would read and process these annotations to
generate additional resources that are required to be used along
with the Java program containing them.

Why Annotations?

In programming paradigm, there are two approaches: imperative
programming
and declarative programming. Imperative
programming specifies the algorithm to achieve a goal, whereas
declarative programming specifies the goal and leaves the
implementation of the algorithm to the support software. In other
words, "specifying how" describes imperative programming and
"specifying what is to be done, not how" describes declarative
programming.

The Java EE platform has always been very supportive for using a
declarative approach. Many of the APIs require boilerplate code,
using external files--deployment descriptors--to specify the
declarative information. For example, in an Enterprise JavaBean
(EJB), much of the information about the bean goes into the
deployment descriptor file.

It would be better and more convenient if the code that goes
into the deployment descriptor were to be maintained as part of the
program itself, but in a declarative way. This is where the actual
usage of annotations comes in: they allow us to move the
information into the source code and thus help in avoiding
unnecessary boilerplate code. Writing EJBs using the annotations in
EJB 3.0 is much easier compared to in earlier releases.

Annotations greatly simplify the developer's work--instead of
using an API or creating an additional deployment descriptor to
request the container to do something, the request for the
container can be put in the code directly.

The biggest advantage of annotations is that they significantly
reduce the amount of code a developer needs to write. Another
advantage is that they are very open and flexible in terms of the
functionality they offer, so that types of logic that were tedious
to write using earlier versions can be written easily using
annotations.

Using Annotations in Java EE 5 Applications

Usage of annotations in Java EE 5 applications introduces a
simpler, POJO-based model and eliminates much of the boilerplate
code that is required in earlier versions. Annotations make the
deployment descriptors optional. Deployment descriptors are
typically used when there is a need to overwrite the value
specified by the annotations. Also, the greatest advantage of the
annotation framework is that it is completely extensible, so future
versions of Java EE can expand the existing annotations and
introduce new ones.

Annotations in EJB 3.0

In the earlier versions of EJB, two interfaces, home and remote,
are defined for accessing the enterprise bean. They can be remote
or local depending on the way the client accesses the bean. Remote
beans are accessed via a network call and local beans are
accessed within the same JVM. These interfaces would normally inherit from the predefined set of interfaces like
EJBHome, EJBObject, etc. However, the new
EJB 3.0 specification simplifies things by adapting a POJO-based
model, through the use of annotations. There is no concept of home
or remote interface here; only one interface is defined, the
business interface. The business interface is a simple POJI (Plain
Old Java Interface) and the type of the business interface (remote
or local) is specified using annotations. All annotations required
for writing EJB are defined in the javax.ejb package,
which is defined in "http://jcp.org/en/jsr/detail?id=220">JSR 220: Enterprise JavaBeans
3.0 Specification
. The business interface is defined like
so:


package stockquote;

import javax.ejb.Remote;

@Remote
public interface StockQuote {
      public double getStockQuote(String Symbol);
}

Here the business interface is marked as a remote interface
using the annotation @Remote. The annotation
@Remote lets the container know that the bean
will be accessed by remote clients. If the container is to be
accessed locally, then the @Local annotation is used.
This is the default annotation. The usage of annotations reduces
lots of repeated code (like writing

throws
RemoteException
for every method) written as part of the
application.

The enterprise bean class is a POJO in EJB 3.0. The type of the
bean (stateless, stateful, message-driven bean) is specified using
metadata annotations instead of implementing the respective
interfaces. In EJB 3.0, to mark a bean as a stateless session bean,
the @Stateless annotation can be used.


@Stateless
public class StockQuoteBean implements stockquote.StockQuote {
    .........
}

The annotation @Stateless lets the container know
that the bean is a stateless session bean. A bean class can
implement both the remote and local interfaces. Again annotations
come to the rescue to specify both of the interfaces for the bean
class.


@Stateless
@Local ({StockQuoteLocal.java})
@Remote ({StockQuote.java})
public class StockQuoteBean implements StockQuoteLocal, StockQuote {
  ......
  ......
  ......
}

Similarly, to mark a stateful session bean, the
@Stateful annotation is used instead of implementing
the javax.ejb.SessionBean interface. To
mark a message-driven bean, the @MessageDriven
annotation is used in lieu of
javax.ejb.MessageDrivenBean. However, the message-driven bean has to implement javax.jms.MessageListener
to produce/consume messages.


@MessageDriven(mappedName = "jms/Queue")
public class SampleMessageBean implements MessageListener {
         .........
}

To configure a message-driven bean in its operational
environment, the @ActivationConfigProperty annotation
can be used.


@MessageDriven(activateConfig =
{@ActivationConfigProperty(propertyName="destinationType",
    propertyValue="javax.jms.Queue"),
 @ActivationConfigProperty(propertyName="destinationName",
    propertyValue="jms/Queue")
})
public class SampleMessageBean implements MessageListener {
        .........
}

In the earlier releases of the EJB specification, callbacks from
the container to the bean were supported by implementing the
methods of the javax.ejb.SessionBean and
javax.ejb.MessageDrivenBean interfaces. This model
unnecessarily adds clutter to the code when callbacks are not
needed (typically in the cases of stateless session beans and
message-driven beans). Annotations used in EJB3.0 remove the need
for skeletal implementations of the lifecycle methods, but still
provide a good support to make methods as callback methods.
The annotations @PostActivate and
@PrePassivate can be used to annotate a method as a
lifecycle event callback in the enterprise bean.

Annotations for the Java Persistence API

A huge set of annotations have been defined to support a new
Java Persistence API, offered as an alternative to entity beans.
These annotations are also defined as part of the EJB 3.0
specification. Annotations have been defined to represent entities,
references to entity managers, relationships, callback events,
queries, and object-relational mapping.

For example, the @PersistenceContext annotation can
be used to retrieve an entity manager instance, which is used to
manage a set of university entity instances.


   @PersistenceContext(unitName="university")
   private EntityManager em;

Kindly refer to the Java Persistence
API
, which is part of the EJB 3.0 specification, for more
details.

Annotations for Callbacks

Annotations are also defined for callback mechanisms. These
annotations are used to notify callbacks such as:

  • @PostConstruct: Can be used to annotate a method
    that can perform any initialization (after dependency
    injection).
  • @PreDestroy: Can be used to annotate a method
    that would be called when the instance is in the process of being
    removed by the container.

These annotations, defined in JSR 250: Common Annotations
for the Java Platform
, belong to the
javax.annotation package that is common to all
managed objects like servlets, EJBs, and the managed beans of JSF.
These annotations can be used to annotate any method as a lifecycle
callback event method.

Annotations for Transactions

Annotations can be used to specify the transaction management
types, instead of writing transaction-related XML tags in the
deployment descriptor. The annotation
@TransactionManagement specifies whether a bean uses
container-managed or bean-managed transactions. The type of
transaction is specified using
TransactionManagementType in the value element of the
annotation. The default type is container-managed transaction.

To specify the transaction attributes to all methods of a
business interface or to the individual methods of the bean class,
the @TransactionAttribute annotation can be used. This
annotation requires a single argument of the enumerated type
TransactionAttributeType, the values of which are
MANDATORY, REQUIRED,
REQUIRES_NEW, SUPPORTS,
NOT_SUPPORTED, and NEVER. If the
@TransactionAttribute annotation is not specified, the
default attribute REQUIRED will be applied. These
annotations are defined as part of EJB 3.0 specification available
in the javax.ejb package.


.........
@TransactionManagement
   (value=TransactionManagementType.CONTAINER)
public class StockQuoteImpl implements StockQuote{
   .........
   @TransactionAttribute(TransactionAttributeType.REQUIRED)
   public double getStockQuote(String symbol) {
      .........
   }
      .........
   }

Annotations for Security

Security for enterprise applications can be specified using the
deployment descriptors, using either the
declarative or programmatic model. Starting with the Java EE 5
platform, annotations can be used to specify security constraints
instead of using deployment descriptors.

To support the declarative security model, we have annotations
defined in JSR
250
to facilitate the usage of security annotations to all managed
components. The annotation @DeclareRoles is used to
declare security roles. This annotation provides support for
declaring more than one role. Other security related annotations,
including @RolesAllowed, @DenyAll, and
@PermitAll, give permission to the role to invoke the
methods.


@RolesAllowed("admin")
public class Department {
   public void setDeptId () {...}
   public void getDeptId () {...}
   ...
}
public class RegularCourse extends Course {
   @RolesAllowed("courseowner")
   public Course addCourse() {...}

   @RolesAllowed("admin")
   public void removeCourse() {...}
   ...
}

Using Annotations for Dependency Injection

Annotations serve multiple purposes. Some annotations provide an
alternative to XML deployment descriptors, while some annotations
allow components to request the container's help for doing certain
tasks that the components would otherwise have to perform
themselves. While we have already discussed the first type, we will
now look at this second type of annotation.

Most enterprise application components like servlets, JSPs, and
EJBs used in enterprise applications use external resources and
services such as data sources, mail sources, environment entries,
and EJB context. Prior to Java EE 5, applications had to
explicitly declare their dependency on these external resources in
the deployment descriptor files, and obtain a reference to these
resources using JNDI. Developers found it very difficult to
understand this model because of its complexities. To reduce the
complexity of this model, Java EE 5 introduced another important
concept called dependency injection.

Dependency injection is a mechanism in which a component's
dependencies are supplied by the container. The dependency on a
resource is marked using annotations or declared in the deployment
descriptor file. Dependency injection (aka "resource injection") is
nothing but the inverse of JNDI. Instead of the component
explicitly requesting a resource, now the Java EE 5.0 container
injects an instance of the resource when it's required. The
injection could be at the field level or at the method level
(typically on a setter method). The Java EE 5 platform defines
annotations to support a variety of injections.

Dependency injection can be applied to all resources that a
component needs. Dependency injection can be used in EJB
containers, web containers, and application clients. However,
resource injection can be requested only by components that are
managed by the container. To request injection of any type of
resource, a component uses the @Resource and
@Resources (for more than one resource) annotations.
These annotations are defined as part of "http://jcp.org/en/jsr/detail?id=250">JSR 250, in the
javax.annotation package. To request injection of an
EJB, the @EJB and @EJBs annotations are used,
defined in the javax.ejb package as part of "http://jcp.org/en/jsr/detail?id=220">JSR 220. To request
injection for web services, @WebServiceRef and
@WebServiceRefs annotations are used. Annotations for
web services are defined as part of "http://jcp.org/en/jsr/detail?id=224">JSR 224: Java API for XML-Based Web Services (JAX-WS) 2.0.

Resource injection can be requested by servlets, servlet
filters, event listeners, tag handlers, and managed beans of JSF in
the web tier, and EJB components, interceptors and message handlers
in the business tier. Resource injection can be requested only by
container-managed components (for example, it cannot be used in
JSPs, as they are not managed components). This is for two reasons:
one is for performance considerations (a container can restrict its
search of annotations only to the components it manages) and the
other is that container must have control over the creation of the
component to be able to transparently perform the injection into
the component.

The following resources can be injected using the
@Resource, @EJB, and
@WebServiceRef annotations:

Using @EJB

A client can obtain a session bean's business interface through
dependency injection using the @EJB annotation instead
of using JNDI lookups. Java EE application clients refer to
enterprise bean instances by annotating static fields with this
annotation. For example, the business interface
StockQuote of the bean can be obtained using:


.........
@EJB
StockQuote stockquote;
double amount = stockquote.getStockQuote("INFY");
.........

Using @WebServiceRef

The @WebServiceRef annotation provides a reference
to a web service. The reference to a web service can be declared
as:


.........
@WebServiceRef
(wsdlLocation =
"http://localhost:8080/stockquoteservice/stockquote?wsdl")
.........

Using @Resource

The @Resource annotation can be used to declare a
reference to any resource that is not annotated using the
@EJB and @WebServiceRef annotations.

This annotation allows dependencies to be injected directly into
the component, avoiding the need for JNDI lookups. The annotation
@Resource can decorate a class, a field, or a method.
The container will inject the resource referred to by
@Resource into the component either at runtime or when
the component is initializing, depending on whether field/method
injection or class injection is used. With field/method-based
injection, the container will inject the resource when the
application is initialized. For class-based injection, the resource
is looked up by the application at runtime.

The annotation

@Resource
(javax.annotation.Resource)
has the following elements:

  • name: The JNDI name of the resource.
  • type: The Java language type of the resource.
  • authenticationType: The authentication type to use for
    the resource.
  • shareable: Indicates whether the resource can be
    shared.
  • mappedName: A non-portable, implementation-specific
    name to which the resource should be mapped.
  • description: The description of the resource.

Let us look at how Java EE 5 platform has simplified the access
to resources using @Resource annotation.

Using @Resource for Data Source

The @Resource annotation can be used instead of
using JNDI API to inject a data source into a component that needs
to make a connection to a database. For example, if you have a
data source named StockQuoteDS, you can obtain a
reference to that data source as follows:


.........
@Resource
javax.sql.DataSource stockquoteDS;
public Object getStockTicker() {
   Connection con = stockquoteDS.getConnection();
   .........
}
.........

The @Resource annotation allows developers to skip
the boilerplate code that was previously required to get access to
a resource.

Using @Resource for EJB Context

The @Resource annotation can also be used to inject
the bean's context--SessionContext and
MessageDrivenContext--through a dependency
injection.


.........
@Resource
javax.ejb.SessionContext ctx;

@Resource
private javax.ejb.MessageDrivenContext mdbCtx;
.........

Using @Resource for JavaMail

The @Resource annotation can be used to inject an
instance of a JavaMail Session into the application. The
Session class represents a mail session, which
collects together properties and defaults used by the mail
APIs.


.........
@Resource
private javax.mail.Session session;
.........

Using @Resource for Transactions

The @Resource annotation can be used to inject a
UserTransaction into a component that is managing the
transactions on its own. The
javax.transaction.UserTransaction is an interface to
the underlying JTA transaction manager. After obtaining a reference
to the UserTransaction resource, a component can
invoke the begin, commit, and
rollback methods on the UserTransaction
object to mark the boundaries of the transaction.


.........
@Resource
UserTransaction utx;
.........
try {
   utx.begin();
   .........
   utx.commit();
} catch(Exception err) {
   .........
   utx.rollback();
   .........
}
.........

Using @Resource for Timer Service

Timed notifications can be scheduled for all types of enterprise
beans (except for stateful session beans) with the help of a timer
service provided by the enterprise bean container. EJB components
can access to the container-managed timer service using
javax.ejb.TimerService. The @Resource
annotation can be used to inject a TimerService into
an enterprise bean component.


.........
@Resource
javax.ejb.TimerService timerService;
.........
timerService.createTimer(100, "Sample");
.........

Using @Resource for JMS

The @Resource annotation can be used to inject JMS
resource factories, such as connection factories and JMS destinations
like Queue or Topic. The dependency of
the component on these resources can be specified using
@Resource annotation. The component can inject the
connection factory and the destination resources using
@Resource annotation as demonstrated below:


.........
@Resource(mappedName = "jms/ConnectionFactory")
private ConnectionFactory connectionFactory;

@Resource(mappedName = "jms/Queue")
private Queue simpleQueue;

@Resource(name="jms/StockTopic", type=javax.jms.Topic)
.........

Using @Resource for Environment Entries

Environment entries are configuration parameters used to
customize the enterprise bean's business logic. For example, in
your application, suppose that you want to give a discount on the
final amount for a user who had purchased items for more than
$1000. It doesn't make sense to hardcode this into the
application, because you might want to change the value of the
discount in the future. The annotation @Resource can
be used to inject simple environment entries into a field or a
method of the bean class as follows.


.........
@Resource
double maxDiscount = 0.2;

@Resource
double minDiscount = 0.05;
.........

Earlier, this was achieved using the XML tags in the deployment
descriptor. However, using the deployment descriptor is the best
suitable solution for using environment entries, as it doesn't make
sense to have annotations to specify them, because annotations are
part of application code.

Using @Resources for Declaring Multiple Resources

The annotation @Resources can be used to inject
multiple resources or used to group together multiple
@Resource declarations. The following code sample uses the
@Resources annotation to group two
@Resource declarations. One is a JMS message queue
connection factory and the other is a data source.


@Resources ({
@Resource(name="stockQueue", type=
        javax.jms.QueueConnectionFactory),
@Resource(name="sqDB", type=java.sql.DataSource)
})
public class StockMDB {
.........
}

Summary

In this article, we have discussed how metadata annotations and
dependency injection makes many kinds of development simpler.
Annotations provide extensible feature wherein one can extend the
existing annotations or write new sets of custom annotations.
Annotations enable tools to generate the required code from the
annotated source code.

Dependency injection makes it easier to develop enterprise
applications by greatly simplifying the complexities of JNDI. In
the Java EE 5 platform, dependency injection can be applied to all
resources that a component requires, effectively hiding the clutter
code required to look up resources.

Dependency injection can be injected using
@Resource, @EJB, and
@WebServiceRef annotations. Any type of resource that
is not annotated with @EJB and
@WebServiceRef can be injected using the
@Resource annotation. The annotation
@Resource can be used to inject a data source, EJB
context, Java Mail, transaction-related resources, security,
environment entries, and more.

Acknowledgment

The authors would like to sincerely acknowledge Dr. Sudeep Mallick,
senior technical architect, E-Commerce Research Labs, Infosys
Technologies Ltd., for reviewing this article and giving valuable
input.

Resources

  1. EJB 3.0
    specification final release
  2. JSR 175: A
    Metadata Facility for the Java Programming Language
  3. JSR 220: Enterprise JavaBeans 3.0
  4. JSR 250: Common Annotations for the Java Platform
  5. "Using Dependency
    Injection in Java EE 5.0
    "
  6. " "http://java.sun.com/developer/technicalArticles/J2EE/intro_ee5/">An
    Introduction to the Java EE 5 Platform
    "
  7. "http://jcp.org/aboutJava/communityprocess/mrel/jsr154/index.html">Final
    release of the Servlet 2.5 specification
  8. " "http://java.sun.com/developer/technicalArticles/J2EE/injection/index.html">
    Web Tier to Go With Java EE 5: A Look at Resource
    Injection
    "
  9. " "http://java.sun.com/developer/technicalArticles/releases/j2se15/">J2SE
    5.0 in a Nutshell
    "
  10. "http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html">
    Annotations
  11. " "http://www.onjava.com/pub/a/onjava/2004/04/21/declarative.html">Declarative
    Programming in Java
    "
  12. " "http://www.javaworld.com/javaworld/jw-01-2006/jw-0102-servlet.html">
    New Features Added to Servlet 2.5
    "

width="1" height="1" border="0" alt=" " />
Sangeetha S. works as a technical architect at the E-Commerce Research Labs at Infosys Technologies
Roberto Chinnici is a senior staff engineer at Sun Microsystems, Inc. where he works on the JavaTM Platform, Enterprise Edition, with particular focus on Web Services and Ease of Development.
Related Topics >> EJB   |