JavaBeat

  • Home
  • Java
    • Java 7
    • Java 8
    • Java EE
    • Servlets
  • Spring Framework
    • Spring Tutorials
    • Spring 4 Tutorials
    • Spring Boot
  • JSF Tutorials
  • Most Popular
    • Binary Search Tree Traversal
    • Spring Batch Tutorial
    • AngularJS + Spring MVC
    • Spring Data JPA Tutorial
    • Packaging and Deploying Node.js
  • About Us
    • Join Us (JBC)
  • Privacy

Introduction to Java Persistence API(JPA)

April 13, 2007 by Krishna Srinivasan Leave a Comment

Introduction

Java Persistence API (JPA) provides POJO (Plain Old Java Object) standard and object relational mapping (OR mapping) for data persistence among applications. Persistence, which deals with storing and retrieving of application data, can now be programmed with Java Persistence API starting from EJB 3.0 as a result of JSR 220. This API has borrowed many of the concepts and standards from leading persistence frameworks like Toplink (from Oracle) and Hibernate (from JBoss). One of the great benefits of JPA is that it is an independent API and can nicely integrate with J2EE as well as J2SE applications. [POJO – Plain Old Java Object is a term used to refer Java objects that do not extend or implement some specialized classes. Therefore, all normal Java objects are POJO’s only. The following classes are not POJO classes.

[code lang=”java”]class MyServlet extends HttpServlet {}
class MyRemote implements SessionBean {}[/code]

In the above cases, both MyServlet and MyRemote extends and implement specialized Servlet and Bean classes, therefore, these classes cannot be termed as POJO’s.

When we say that JPA follows the POJO standard, it follows that the entities (or the entity class) are very regular and normal Java classes, in the sense that they doesn’t need to extend or implement some specialized classes].


[OR Mapping – Object-Relation mapping is the process of the transformation of the data between the class objects and databases. Applications can depend on an OR-M like tool that greatly simplifies this work instead of manually coding the transformation process.]

About Persistence Entites

Persistent Data normally refers to permanent data in an application. The state of these data is made permanent by storing them in a persistent medium like database, files or a disk tape. In JPA terms, these persistent data are referred as entities. An entity refers to a logical collection of data that can be stored or retrieved as a whole. For example, in a banking application, Customer and BankAccount can be treated as entities. Customer name, customer address etc can be logically grouped together for representing a Customer entity. Similarly account number, total balance etc may be logically grouped under BankAccount entity.

Since entities form the heart of the JPA, they have some unique characteristics like persistability, identity and transactionability. The property of persistability deals with the storing and retrieving of entity from and to a persistent medium like database. Identity property is usually used to identity one unique entity among multiple entities (or multiple entity instances) in a database. All the CRUD operations (Create, Update and Delete) for entity objects will occur within a transactional context and it is one of the major characteristic for an entity object as the real state of an entity depends whether a transaction completes (commits/fails) or not.

Persistence API

All the classes, interfaces and annotations that make up the Java Persistence API are available in a single javax.persistence package. A brief look at the core objects and concepts within the package will be much useful before dealing with some sample code.

Entites

As mentioned previously, in JPA terms an entity refers to a persistent object which can be stored and retrieved from a persistent storage. In technical terms, this entity will correspond to a Java class.

Consider the following simple java class, named MobileEntity.

[code lang=”java”]class MobileEntity{

private String model;
private String manufacturer;
private Double price;
private String imeiNo;

…..
// Getters and Setters go here.
}[/code]

The above class represents a mobile object which has its own model, manufacturer, price and an imei number. Suppose, we wish to persist this mobile java class using JPA. The first step is to qualify this java class as an entity. This is done by marking the class with @Entity annotation. Marking a class with @Entity annotation will tell to the persistence engine that objects created from this class can use the support of JPA to make them persistent. After adding the @Entity annotation to the above class the code looks like this,

[code lang=”java”]@Entity
class MobileEntity{

private String model;
private String manufacturer;
private Double price;
private String imeiNo;

…..
// Getters and Setters go here.
}[/code]

[A persistence engine or a persistence provider is nothing but an implementation of the Java Persistence API. Java Persistence API is just a specification from Sun and not an implementation and vendors are free to implement their own persistent framework following the JPA specification. Thus, JPA provided a pluggable interface, where more and more implementations can easily be associated with it at run-time.]

Since an entity always has an identity associated with it, it is the job of the programmer to tell to the persistence engine, how uniquely to identity an entity object. This is simply done by marking a field (or a set of fields) with the @Id annotation. A field that is marked with @Id annotation will be treated as a primary key for the table by the persistent engine.

It is an error to ignore any one of the fields in an Entity class with @Id annotation, because the persistence engine won’t be in a position to identity unique entity objects without the help of primary keys. In our case, since no two mobile phones in the world share the same IMEI (International Mobile Equipment Identity), imeiNo is an ideal candidate to be marked with @Id annotation.

[code lang=”java”]@Id
private String imeiNo;[/code]

It is an error to give null values, to a primary key field, during that case, the persistence engine may throw any kind of database exception.

The following is the default values for table and column names when the persistence engine was Oracle’s Toplink during the deployment time.

  • Alias Name – MobileEntity (the unqualified (with-out the package name) name of the class).
  • Table Name – MOBILEENTITY
  • Column Names – [MODEL, MAUNFACTURER, PRICE and IMEINO] (These correspond to the variable names).

Customizing the Entity object

In most of the cases, the defaults that are created and provided by a persistence engine are sufficient. However, certain situations may demand for customization which includes factors like name collision, companies adopting standard naming conventions, etc., like that. In such a case, the entity class can greatly be customized with a huge set of annotations available in the javax.persistence package. Let us take a look one by one.

Changing the default table name

By default the table name corresponds to the unqualified name of the class. We can change this behavior with the help of @Entity annotation itself, like this.

[code lang=”java”]@Entity(name = "MOBILE_ENTITY")
public class MobileEntity{
……
}[/code]

Now, the table name becomes MOBILE_ENTITY and this should be the name that must be referred in query strings (Queries are discussed later). The value to the name property must be legal in the sense, it cannot accept any keywords that are found in the query language.

Customizing the Column behaviors

The default name of the columns, their size, whether they can accept null values or not etc., can be customized using the @Column annotation. Following is the sample code that illustrates this,

[code lang=”java”]@Column(name = "MOBILE_MODEL", nullable = true, length = 35)
private String model;

@Column(name = "MOBILE_MANUFACTURER" nullable = true, length = 100)
private String manufacturer;

@Id
@Column(name = "MOBILE_IMEI_NO", nullable = false)
private String imeiNo;[/code]

The name property, when specified will override the default column name (which is the same as that of the field name in the Entity class). The nullable property tells that whether the column can accept null values. Length property is only applicable if the type of the column is String (or VARCHAR). There are also properties like scale and precision which is applicable only when the type of the column is NUMBER.


[Note, multiple annotations can be legally applied to elements (like class, field, method etc.). In the above example the imeiNo has two annotations attached with it, namely @Id and @Column.]

Auto-generation of Primary Keys

A primary key for an entity which is usually annotated with @Id annotation can be given a value manually or we can depend on the persistence provider for the same. For this we have to use the @GeneratedValue annotation.

Consider the following example,

[code lang=”java”]@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String imeiNo;[/code]

Since the imeiNo is going to be the primary key for the mobile object, we have decorated the field with @GeneratedValue annotation, which delegates the burden of creating values from developers to the persistence engine. Also, there are 4 different methods (or strategies) for primary key generation, which are AUTO, IDENTITY, SEQUENCE and TABLE. The simplest one is the automatic primary key generation strategy which is represented as GenerationType.AUTO.


[GenerationType is an Enumeration (new feature in Java 5.0) and the four different strategies for primary key generation, namely AUTO, IDENTITY, TABLE and SEQUENCE are defined in that enumeration.]

EntityManager

This class follows the standard Manager Design pattern for managing entities. Managing an entity or a set of entities refers to the act of bring a set of Java objects under the control of EntityManager. Unless entities don’t have any explicit association with EntityManager they are just ordinary java objects (though their corresponding classes have been marked with @Entity annotation).

This EntityManager API provides services for persisting an entity, removing an entity, querying and deleting entities.

In a J2SE application, a reference to an entity manager (EntityManager) can be obtained using the entity manager factory (EntityManagerFactory) and the Persistence class. The persistence class is a helper class (or a bootstrap) used to create EntityManagerFactory objects. With EntityManagerFactory objects, references to EntityManager objects can be obtained. The following code illustrates the same,

[code lang=”java”]EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("PersistentUnitName");
EntityManager eManager = entityManagerFactory.createEntityManager();
[/code]


[An EntityManagerFactory can be configured with some set of properties with the help of Persistent Units. Notice that one of the arguments to createEntityManagerFactory() is the name of the persistent unit which is discussed in the later sections.]

In a J2EE application, the container will directly inject a reference to the EntityManager using dependency injection, so the code becomes as simple like this,

[code lang=”java”]
@Resource
private EntityManager entityManager;[/code]

Persistence Context

To be very precise, a persistent context manages a set of entities which in turn is managed by the EntityManager. A persistent context keeps track of the state (or the changes) that an entity object may undergo. And the EntityManager takes the support of this persistence context to commit or to undo the changes. As soon as an EntityManager object is created, it is implicitly associated with a persistence context for managing a set of entities.

Persistent Context comes in two flavors, one is the transaction-scoped persistent context and the other one is extended persistent context.

Transaction-Scoped Persistence Context: Imagine that a set of entities are managed by the persistence context. At this time, we say that the entities are bound to (or attached) to the persistent context. Changes may happen to these entities and these changes will occur within a transaction. Sometimes later when the transaction ends (commits or roll-back), the entities will unbind (detached) from the persistent context. As soon as the entities are detached from the persistence context, they are no longer being managed. Any changes that happen to these entities will not be persisted as they don’t have any association with the persistence context. Such kind of persistent context whose life-time is dependent on the life-time of the transaction (for a set of entities at that particular point of time) is termed as transaction-scoped persistent context.

All the transaction-scoped persistence context are configured by injecting @PersistentContext to EntityManager objects , like this,

[code lang=”java”]
@PersistenceContext(name="PersistentUnitName")
private EntityManager entityManager;
[/code]

[Note: There is no such public interface called PersitenceContext in the Java Persistence API. The EntityManager may implicitly depend on a virtual Persistence Context class for managing the entities. So, creating a transaction-scoped persistence context is nothing but creating an EntityManager object that has been configured with @PersistenceContext annotation.]

Extended Persistence Context: Unlike transaction-scoped persistence context, where the life-time of the persistence context will end as soon the transaction is completed, a persistence context may be configured to live even after a transaction completes. In such a case, all the entities that are managed by such a persistence context will still be in a manageable state only even after the transaction ends. They won’t be detached from the context. Such long-lived persistence context that will continue to exist even after the completion of a transaction is called extended persistence context.

All the extended persistence context objects are created and managed manually by the application code only (that is by the developers).

[As soon as an EntityManager object is created, an implicit Persistence context will be associated with it and it is soon kept open and prepared for managing a set of entities, meaning that the calling EntityManager.isOpen() method will always return true. Calling the EntityManager.clear() method will clear the current persistence context associated with the EntityManager and all the entities that have their associations will now be cleared and they become detached from the EntityManager. To release all the resources referenced by the EntityManager, call the close() method, After this method call, calling any of the methods will throw IllegalStateException.]

Entities and Transactions

All entities have the property of transactionability and their CRUD operations will take place within a transactional context. Transactions can be broadly classified into two types based on who actually owns (or manages) the transaction. They are JTA and Resource-local transaction.

In the case of a J2EE Application, the default transaction type is JTA (Java Transaction API), unless explicitly specified. A method can be simply annotated with @RequiresNew (or @Requires) in which case a new transaction will always started by the container and the transaction completes as soon as the method ends.

Whereas in a J2SE application, the transaction-type defaults to Resource-local, which means that the developer (or the application code) has to explicitly start and end a transaction. It means that the user has to explicitly start a transaction with the help of EntityManager object, and then have to commit it, if everything goes normal, else have to roll-back the transaction if some error occurs.

The following code shows this,

[code lang=”java”]
EntityTransaction userTransaction = entityManager.getTransaction();
try{
userTransaction.begin();

// Do something here.

// If everthing goes well, make a commit here.
userTransaction.commit();
}catch(Exception exception){
// Exception has occurred, roll-back the transaction.
userTransaction.rollback();
}
[/code]

Operations on Entity Objects

The following are the legal operations that can be performed on Entity objects with the help of EntityManager API. As seen previously, EntityManager are objects that manage one or more entity objects with the help of an implicit persistence context.

Persisting Entity Objects:

Entity objects are like regular java objects until they become managed and made persistent by the EntityManager. The following piece of code makes an entity to become persistent and managed.

[code lang=”java”]MobileEntity mobileObject = new MobileEntity();
mobileObject.set()… // Update the state values here.
entityManager.persist(mobileObject);[/code]

The persist(entityObject) methods makes the entity persistent in the underlying database and managed within the persistence context of the EntityManager, whether the persistence context is a transaction-scoped or an extended persistence context depends upon how actually the EntityManager was configured.

[What happens when a managed entity is again forced to become managed by calling the persist() method. Or what happens when the persist() method is called couple of times on the same entity object.

Whenever the persist() method is called, the persistence engine will check for the existence of that object with the help of its unique identifier (which is represented in the form of primary key). If any duplicate object is found, then a run-time exception, EntityExistsException will be thrown.]


Querying for Entities:

Developers can either depend on the EntityManager for simple search or Query objects for providing powerful search conditions for locating and querying entity objects.


Using EntityManager object:

Following are the two different methods available in EntityManager interface for querying entity objects and there are some major differences between the two.

Using the EntityManager.find() method:

The find() method takes the class name of the Entity object and the primary key value for locating a single entity object. If the object of interest cannot be located by the EntityManager, then this method will simply return null. The following code illustrates this,

[code lang=”java”]
MobileEntity mobile = entityManager.find(MobileEntity.class, "ABC-123");
If (mobile != null){ // mobile object may or may not be null.
// Process the object.
}
[/code]

One good thing about the find() method is that, the returned entity object soon becomes managed automatically within the persistence context of the EntityManager.


Using the EntityManager.getReference() method:

This method, like the EntityManager.find() method, takes the name of the entity class and the primary key as their arguments. But the difference is, unlike the find() method which will return null if the entity object is not found, this method will throw an exception EntityNotFFoundException. Another difference between this method and the find() method is that, the entity that is fetched by this method may be lazily loaded. That is, the state of the state of entity (like model, manufacturer, imeiNo may be lazily loaded during the first time it is actually accessed).

[code lang=”java”]
MobileEntity mobile = entityManager.getReference(
MobileEntity.class, "ABC-123");
// mobile object may not contain the actual state
//values for model, manufacturer
// and imei number, the states may be loaded during the first access.

String model = mobile.getModel();
// The persistence engine may fetch the model value for the mobile here
// at this particular point of time.
…..[/code]


Using the Query object:

Discussed later.


Deleting Entities:

To remove (delete) an entity object from the database, make a call to EntityManager.remove(entityObject) method. The entity object that is passed to the remove() must be a managed entity, else the operation will fail.

Also, making this call may or may-not remove the entity immediately from the database. The algorithm that achieves the same is implementation specific. Some implementation may only mark the entity as a removed entity after this method call, and the actual deletion of the entity object in the database may happen when a flush() operation (which is discussed later) is made.

After this method call, the entity will become detached from the persistence context and it is no longer a managed one.


Updating Entities:

The EntityManager.merge(entityObject) method will make a detached entity to get associated with the current persistence context of the EntityManager. Consider the following lines of code.

[code lang=”java”]
// Transaction has begin.
…..
MobileEntity mobile = entityManager.find(MobileEntity.class, "ABC-123");
…..
// Transaction ends.
mobile.set()…… // Updating the mobile object.
entityManager.merge(mobile);
[/code]

In the above piece of code, a mobile entity object is located with the EntityManager.find() method. This entity is now in a managed state. Assume that the transaction ends after some point of time and also the persistence context is a transaction-scoped persistence context. As soon as the transaction completes, the persistence context will go off, (since the persistence context is a transaction-scoped persistence context). So the entity object becomes detached from the persistence context. After this any modifications that are made to the mobile object won’t be knowledgeable to the EntityManager as the mobile object has already been detached from it.

Now, calling the merge() method, will make the mobile object becomes managed, and all the recent changes that are made to it will become visible to the current persistence context of the EntityManager.


Flushing and Refreshing:

The EntityManager.flush() will synchronize all the changes that are made to the persistent entities back to the underlying database, whereas the EntityManager.refresh() does the reverse. It will update the entity object with values taken from the database. Any new values that are set to the entity objects will be lost as a result of this method call.

For example, consider the following piece of code,

[code lang=”java”]MobileEntity mobile = …..
mobile.set(); // Update the state values for the mobile object.
….
entityManager.flush();
// Calling this flush method will synchronize the database with the values
// taken from the entity object.[/code]

Now consider this code,

[code lang=”java”]MobileEntity mobile = …
mobile.set(); // The state values for the mobile object is updated.
…..
entityManager.refresh();
// The refresh() method will refresh the entity object
//with the values taken from the database.
// All the updates that are done are lost.[/code]

Summary

also read:

  • The Query API in JPA (EJB 3.0)
  • Sample Application for Java Persistence API (JPA)

The above two links are continuous of this article with more features and the sample application for the JPA.This article began with the discussion of Java Persistent API and its advantages and what persistent entities are. Then the terminologies that are very specific to JPA like EntityManager, PersistenceContext have been discussed. The various features about the Query interface for locating Entity objects were explored in depth. Finally, it ended with Persistent Units and its relation with EntityManager objects along with a sample J2SE application.

Filed Under: Java EE Tagged With: EJB, JPA

EJB 3.0 Timer Services

March 28, 2007 by Krishna Srinivasan Leave a Comment

Starting from EJB 2.1, Timer Services are available for building J2EE Applications that depends on time based services. Time based services are mostly used in scheduling applications. Technically, these scheduling applications are called workflows.

also read:

  • Java EE Tutorials
  • EJB Interview Questions
  • EJB 3 Web Services
  • Annotation and Dependency Injection in EJB 3
  • Query API in EJB 3

A workflow defines a configurable sequence of activities or tasks that will take place at a particular point of time. Before EJB 2.1, one has to manually code for building and deploying time-based workflow systems. But, with the invent of EJB 3.0, thanks to Annotations and Dependency injections, life has become still more easier for creating such applications.

What are EJB 3.0 Timer Services?

Consider a reporting Application, that will send report in the form of mails, every Monday, or a Billing Service that sends credit or debit bills on the 1st of every month. These applications depend on time-based events. To be more precise, these applications should allow developers to schedule some business logic or process so that they can be executed at some regular intervals of time. This is the core concept behind EJB Timers.

EJB Timer Services are services that are provided by the container (or the Application Server) and developers can take advantage of the timer services by registering one or more enterprise beans for time-based notification.

Different Types of Timers:

EJB basically supports two forms of Timer objects:

  • Single Action Timer
  • Interval Timer

a) Single Action Timer

A single action timer (or a single interval timer) is a one which will expire only once (as opposed to interval timer, where multiple expirations are possible).

Accordingly EJB supports two different ways for constructing a single interval timer.

i) One is to create the timer in such a way that it will expire at a particular point of time which is specified as a Date

ii) The other possible way is make the timer to expire after certain period of time (say after 10 hours or 1 day) which is usually specified in milliseconds. After the timer expires, the enterprise bean will receive a kind of notification, i.e the container will call the ejbTimeout() method (or the method that is annotated with @Timeout annotation).

b) Interval Timer

Interval timer (or multiple action timer), as its name suggests will recur (or happen) at multiple intervals of time. That is, these kinds of timer will have multiple expirations at regular intervals of time.

Two different ways of constructing the Timers are available:

i) The first approach is to create a timer to have an initial expiration at some point of time (which is usually specified as a Date) and to have the subsequent expirations happen at a specified interval.

ii) The second approach is to construct the timer whose initial expiration will happen after an elapsed duration of time (in milliseconds) and to have the subsequent expirations happen after a specific interval. For every expirations of the Timer object, the container continues to call the ejbTimeout() method (or the method that is annotated with @Timeout annotation) until the bean explicitly calls the cancel() method.

Timer Services API

The Timer Services API is small and has only 4 interfaces packaged with it. It is expected that more API related to Timer Services will be added in the future EJB specification. The interfaces are:

  • TimerService
  • Timer
  • TimedObject
  • TimerHandle

a) TimerService

This interface provides support for creating timers (single-action or interval) as well as retrieving the existing timers (that are created by one or more enterprise beans) from the container. Enterprise beans can use this interface for creating single-action or interval timer objects.

i) For creating timers

    • Single-action Timers

The following two methods are available in the TimerService API for creating a single action timer:

      • Timer createTimer(long duration, Serializable info)
      • Timer createTimer(Date expiration, Serializable info)

Using the first method, a single action timer can be made to expire after a specified duration of time. The second method will be useful if the timer is needed to expire at a particular point of time. The second argument in both the versions will be useful, if application specific information has to be passed to the Timer objects, else it can be safely ignored by passing null.

    • Interval Timers

Following are the ways to create an interval based timer object.

      • Timer createTimer(long initialDuration, long intervalDuration, Serializable info)
      • Timer createTimer(Date initialExpiration, long intervalDuration, Serializable info)

Interval timers have options to specify the initial expiration in the form of milliseconds or as a Date object and the subsequent expirations can be expressed in milliseconds. In the first version, the initial expiration for the Timer object will happen after the initialDuration has elapsed and subsequent expirations will happen at the specified intervalDuration. The second version supports in specifying the initial time of expiration as a Date object and the rest of the information is the same as that of the first version. Similar to single action timers, these timers also allows the enterprise beans to pass application specific information.

ii) For iterating over the existing timers

Collection getTimers() – This method will return a collection of timers that were already created by other enterprise beans that may be in different parts of the system.

b) Time

This interface holds information about the timer objects that was previously created by enterprise beans.

    • Serializable getInfo ()

Returns the application specific object that was passed previously by the enterprise beans while creating timer objects. The object must implement the Serializable interface.

    • Date getNextTimeout()

Returns the time (as a Date object) that tells when the next expiration is going to happen for this timer object.

    • long getTimeRemaining()

Returns the number of remaining milliseconds that is left before the next expiration happens for this timer.

    • TimerHandle getHandle()

Returns an instance of TimerHandle object which at a later time can be used to reconstruct the Timer object.

    • void cancel()

Cancels the timer object. After cancellation, enterprise beans that have already registered for getting time-based notification (through the ejbTimeout() method) will no longer receive events.

c) TimedObject

Enterprise beans can implement this interface to receive time-based notifications (or callbacks) on Timer objects. The ejbTimeout() method will be invoked by the container whenever the timer expires.

For a single action timer, the ejbTimeout() will be called only once, whereas for an interval timer, this callback method may be called multiple times.

void ejbTimeout(java.ejb.Timer timer)

This method is called by the EJB Container when the timer object has expired.

There are two possible ways for implementing a call back method:

  • One way is to make the enterprise bean implement the TimedObject interface and to give an implementation for the ejbTimeout(Timer timer) method. For example,
    [code lang=”java”]@Stateless
    @Remote
    class MyBeanImpl implements MyBean, TimedObject{
    Public void ejbTimedout(Timer timer){
    .
    .

    }

    }[/code]

  • The other way is to annotate a method that is defined within the enterprise bean class with the @Timeout annotation. In this case, there is no need for the enterprise bean to implement the TimedOut interface. The return type of this method must be void and it should accept only one argument of type Timer.
    [code lang=”java”]@Stateless
    @Remote
    class MyBeanImpl implements MyBean{
    @Timeout
    public void myTimedOutMethod(Timer timer){
    ….
    }
    }[/code]

d) TimerHandle

This interface is implemented by the container so that enterprise beans at a later point can use this handle to reconstruct the timer object. TimerHandle extends the Serializable interface. So, the clients may serialize the handle. Because of this, TimerHandle are local objects, hence it is illegal to pass this object as an argument to remote interfaces.

Timer getTimer()

Obtains a reference to the Timer object.

Timer Operations

The following summarizes the various timer operations that may happen once a timer object is created:

  • Creation
  • Cancellation
  • Expiration

Creating Timer Objects

Timer objects are usually created by one or more enterprise beans. Only stateless session beans and message-driven beans can create timer objects. The reason why stateful session beans cannot create timer objects is not clear in the specification. So, as of now, creating timer objects within stateful session beans will result in IllegalStateException. However, it is expected that the future specifications may also mandate stateful session beans to support timers.

Here is the sequence of steps to be followed for creating a Timer object.

a) Get a reference to the EJBContext object (for session beans it is SessionContext and for message-driven beans, MessageDrivenContext is used).

b) Obtain a reference to the TimerService using the context object.

c) Create single action or multiple Timer objects using the TimerService object.

a) Getting a Reference to the Context object

With the new EJB 3.0 way, getting a reference to the Context object with the help of Annotation and Dependency Injection has become easy. Following is a sample code to get a reference to the SessionContext (in the case of session beans) and MessageDrivenContext (in the case of message driven beans).

[code lang=”java”]@Resource
Private SessionContext sessionCtx;
@Resource
Private MessageDrivenContext messageDrivenCtx;[/code]

When the container creates an instance of enterprise beans, it will process all the annotations that are listed and then perform a dependency injection. So, the result is that sessionCtx reference and the messageDrivenCtx will be populated with an instance of type SessionContext and MessageDrivenContext respectively.

b) Getting a Reference to TimerService:

Getting a reference to the TimerService object is relatively simple, just a call to Context.getTimerService() will do that, like this

[code lang=”java”]TimerService timerService = sessionCtx.getTimerService();
TimerService timerService = messageDrivenCtx.getTimerService();[/code]

c) Creating Timer objects:

As discussed earlier, timers are of two kinds. Single-action and Interval timer, Depending on the requirement, create any of the two variations of the timer objects. Given below are some samples for creating different timer objects with different configurations.

i) A timer object that will expire after 10 seconds from now.

[code lang=”java”]
Calendar now = Calendar.getInstance();
Timer timer = timerService.createTimer(now.getTimeInMillis()
+ (10 * 1000), null);[/code]

ii) This timer object will expire on the 1st of March 2007.

[code lang=”java”]
Calendar firstMarch2007 = new GregorianCalendar(2007,
Calendar.MARCH, 1);
Timer timer = timerService.createTimer(firstMarch2007, null);
[/code]

iii) Here, the timer object initially expires after 1 week of time and subsequent expirations will happen after two weeks of time.

[code lang=”java”]
long oneWeek = (7 * 24 * 60 * 60 * 1000);
Timer timer = timerService.createTimer(oneWeek,
(oneWeek * 2), null);
[/code]

iv) Here, the timer has an initial expiration that happens on the 1st of March 2007 and subsequent expirations will happen after one week of time.

[code lang=”java”]
Calendar firstMarch2007 = new GregorianCalendar(2007,
Calendar.MARCH, 1);
long oneWeek = (7 * 24 * 60 * 60 * 1000);
Timer timer = timerService.createTimer(firstMarch2007,
oneWeek, null);
[/code]

Canceling the Timer

Following are the three possible ways where a timer object can be made to cancel:


i) By explicitly calling the cancel method:

When the enterprise beans decides that they no longer want to receive any kind of notifications (via. ejbTimeout (Timer) method), then can call the cancel method in the Timer object. Upon invoking this method, the enterprise beans that have previously registered for getting notifications will no longer will receive callbacks(i.e the ejbTimeout() method wont be called anymore) from the container.

[code lang=”java”]Timer timer = timerService.createTimer(…);
.
.
.
timer.cancel();[/code]


ii) When the timer object expires naturally:

Timer expiration is applicable only for single action timers (as interval timer will never expire, the only way to stop from further functioning is to explicitly call the cancel() method). Expiration for single action timers happen when the time (mentioned in the form of milliseconds) has elapsed, or the time (mentioned in the form of a Date object) duration is over.

Timer Expiration

Timer expirations can happen in any of the three cases:

  • The given date (and time) has arrived.
  • The period of time (that is given in the form of milliseconds) has elapsed.
  • The recurring interval has expired (in the case of interval timer).

Persistence

Timers are persistent objects. To be precise, they are permanent objects. Whenever an enterprise bean creates an instance of a Timer object by using the TimerService, the TimerService will persist the Timer object by storing it in a database. Even if the server is abruptly terminated or it goes off, the timers will still be available and will become active once the server come backs to it normal state.

Timers and Transactions

Creating and canceling timers objects are made within a transactional context. So, if the transaction rolls back after creating a timer object, then the timer object creation is also rollbacked. Similarly, if the cancel method is called and the transaction is rolled back subsequently, the cancellation of the timer object is also rolled back.

Sample Implementation

Given below is a sample implementation that shows how an enterprise bean can use the facilities provided by the EJB Timer Services. Though, it is not a real time application, it may still provide the basic concepts that are back grounding the EJB Timer Services.

i) Scenario

This application is all about an employee who is giving status update to his manager at regular intervals. Though, the figures (startDate, endDate and the interval duration) and the status information may not mimic the real data, it may still provide a valuable way for writing a simple timer based application.

ii) Identified Objects

a) Worker:

Since Employee and Manager are really workers in a company, the purpose of this Worker class is to serve as a base class for the Employee and Manager class. It contains the common properties/attributes like name and id with its associated behavior.

b) Employee:

This class represents an employee object apart from inheriting the properties like name and id from its base class Worker, it contains a static method getStatusString() that randomly returns some status update message.

c) Manager:

Manager class that extends Worker class, apart from inheriting the common functionality, provides methods like reportStatus(Employee, status) that will accumulate the employee and his/her status information. It also has a printEmpStatusInfo() method, that will print all the status information of the employees for a particular duration of time.

d) StatusInfo:

StatusInfo is an information holder class that holds information about the employee and the manager objects and also the low-level information like the startDate, endDate, intervalDuration that will be used by the Bean for creating timer objects and publishing status information.

e) StatusUpdateBean:

The Local and the Remote Interfaces are represented by StatusUpdateLocal and StatusUpdateRemote respectively and the bean implementation is given by StatusUpdateBean. The remote interface has a method called setUpStatusInfo(StatusInfo) which is the only visible method as far as the client is concerned. Before invoking this method, the client (whether a stand-alone client, or a servlet ..), has to populate the StatusInfo object with relevant information like creating some test data representing the manager/employee objects, startDate/endDate/duration that represents when the employee has started giving status update to his manger, till what time he has to keep giving his updates, and the interval duration between the status updates.

f) Client:

The client gets a reference to the Remote interface through dependency injection (or through a JNDI lookup), populates the StatusInfo object with some test objects before calling the setUpStatusInfo(StatusInfo) method.

How it works

Once the setUpStatusInfo(StatusInfo) method is called, the Bean creates an instance of the Timer object using the TimerService factory interface which is obtained through the SessionContext object (via. Dependency Injection).

[code lang=”java”]
// Populates the SessionContext object using dependency injection.
@Resource
private SessionContext sessionContext;
// Obtain a reference to the TimerService object
TimerService timerService = sessionContext.getTimerService();
// Creates a timer object using the relevant information taken
//from the StatusInfo object.
// The following code creates a interval timer object with the
//specified startDate and with the duration
// as its interval.
Calendar startDate = statusInfo.getStartDate();
long duration = statusInfo.getNextInterval();
Timer timer = timerService.createTimer(startDate.getTime(),
duration, null);
[/code]

Timedout Method

One can easily figure out that the updateStatus(Timer) is the timedout method for this enterprise bean as it is annotated with the @Timeout annotation. Within the method, the manager and the employee objects are obtained from the StatusInfo object and some dummy status is published to the manager object by calling the reportStatus(Employee, status) method. The manager objects keeps on storing the status against the employee object in a map. The method will be called infinitely if the timer object is not cancelled, since it is an interval timer. The timer is cancelled by checking whether the current time has crossed beyond the end time. If that’s the case, the timer object is cancelled and the status information for the employees is printed in the console.

[code lang=”java”]
Code snippet …
@Timeout
public void updateStatus(Timer timer){
Manager manager = statusInfo.getManager();
List employees = statusInfo.getEmployees();
for(int i=0; i
System.out.println("Updating the Status Information..");
manager.reportStatus(employees.get(i),
Employee.getStatusString());
}
Calendar now = new GregorianCalendar();
if(now.after(statusInfo.getEndDate())){
manager.printEmpStatusInfo();
timer.cancel();
}
}
[/code]

Conclusion

Developers can take the advantage of the EJB Timer Services for building robust scheduling applications. One thing to remember is that, to be honest, developers are not encouraged to depend on Timer Services for building real-time applications (mission critical applications), as the expiration may not happen accurately at all times because of certain factors like the network latency, underlying implementation etc. Though, the timer services API is not exhaustive, it is believed that more and new functionalities will be added in the next specification of the EJB.

Frequently asked Questions on Timer Services

Q: a) What are Timer Services:
A: EJB Timer Services are container provided services for building scheduling (time-based) applications

Q: b) What are the two different types of Timers and how they are useful?
A: Timer comes in two forms. One is the single action timer and the other is interval timer. The former can be used in applications wherein which some logic has to be executed only once at a particular point of time (or after a specific duration) while the latter can be used to execute repeated logic at regular intervals.

Q: c) What is the use of @Timeout() annotation in EJB 3.0?
A: @Timeout() annotation when applied to a method will indicate that the method is a callback method for timer expirations and the container will call this method automatically whenever the timer object expires.

Q: d) How to pass application specific information to timer objects?
A: The createTimer() method (for both a single action and an interval timer) has an argument called info of type Serializable. This argument can be used to pass application specific information to timer objects (say, creditCardNumber and expiryDate in the case of Credit Card Processing System).

Q: e) What necessary steps are involved for creating a timer object?
A: Since timer services are container managed, we have to depend on the context object (EJBContext to be more specific) to make use of it. For a session bean, it is a SessionContext object and for a message driven bean, a MessageDrivenContext is used. Then, using the Context object, obtain a reference to the TimerService object. This TimerService factory object can then be used to create timers with different configurations.

Q: f) What different situations are there to make a timer object to expire?
A: A timer object can expire when the following conditions are met.

  1. When the enterprise bean, explicitly calls the cancel() method, (in this case, the ejbTimeout(Timer) callback method will never be called.
  2. When the duration that is mentioned during the creation of the timer object has expired, or the specified time (mentioned in the form of a Date object) has reached.
  3. The interval duration has elapsed in the case of an interval timer (in which case, multiple expirations may be possible)

.

Filed Under: Java EE Tagged With: EJB, EJB 3

  • « Previous Page
  • 1
  • …
  • 19
  • 20
  • 21

Follow Us

  • Facebook
  • Pinterest

As a participant in the Amazon Services LLC Associates Program, this site may earn from qualifying purchases. We may also earn commissions on purchases from other retail websites.

JavaBeat

FEATURED TUTORIALS

Answered: Using Java to Convert Int to String

The Java 6.0 Compiler API

Introductiion to Jakarta Struts

Copyright © by JavaBeat · All rights reserved