J2EE - Creating Clustered EJB Timer Services In Weblogic Server

The EJB timer service is an EJB-container provided service that allows you to create timers that schedule callbacks to occur when a timer object expires. Timer objects can be created for entity beans, message-driven beans, and stateless session beans. Timer objects expire at a specified time, after an elapsed period of time, or at specified intervals. For instance, you can use the timer service to send out notification when an EJB remains in a certain state for an elapsed period of time.

The WebLogic EJB timer service is intended to be used as a coarse-grained timer service. Rather than having a large number of timer objects performing the same task on a unique set of data, Oracle recommends using a small number of timers that perform bulk tasks on the data. For example, assume you have an EJB that represents an employee’s expense report. Each expense report must be approved by a manager before it can be processed. You could use one EJB timer to periodically inspect all pending expense reports and send an email to the corresponding manager to remind them to either approve or reject the reports that are waiting for their approval.

You can configure two types of EJB timer services: 
1) Clustered.
2) Local. 
Clustered EJB Timer Services:
Clustered EJB timer services provide the following advantages:
1)    Timers are accessible from any node in a cluster. For example, the javax.ejb.TimerService.getTimers() method returns a complete list of all stateless session or message-driven bean timers in a cluster that were created for the EJB. If you pass the primary key of the entity bean to the getTimers() method, a list of timers for that entity bean are returned.

2)   Automatic load balancing and failover.
3)   Clustered EJB timer services take advantage of the load balancing and failover capabilities of the Job Scheduler.
Local EJB Timer Services:
Local EJB timer services execute only on the server on which they are created and are visible only to the beans on that server. With a local EJB timer service, you do not have to configure a cluster, database, JDBC data source, or leasing service, as you do for clustered EJB timer services.
You cannot migrate a local EJB timer object from one server to another. 

Timer objects can only be migrated as part of an entire server. If a server that contains EJB timers goes down for any reason, you must restart the server or migrate the entire server in order for the timers to execute. 
Here in this article we concentrate on implementing Clustered EJB Timer Services.

Implementing Clustered EJB Timer Services: 1) Create the below Database Tables in Database.

 DROP TABLE WEBLOGIC_TIMERS;  
 CREATE TABLE WEBLOGIC_TIMERS (  
  TIMER_ID VARCHAR2(100) NOT NULL,  
  LISTENER BLOB NOT NULL,  
  START_TIME NUMBER NOT NULL,  
  INTERVAL NUMBER NOT NULL,  
  TIMER_MANAGER_NAME VARCHAR2(100) NOT NULL,  
  DOMAIN_NAME VARCHAR2(100) NOT NULL,  
  CLUSTER_NAME VARCHAR2(100) NOT NULL,  
  PRIMARY KEY (TIMER_ID, CLUSTER_NAME, DOMAIN_NAME)  
 );   
 DROP TABLE ACTIVE;  
 CREATE TABLE ACTIVE (  
  SERVER VARCHAR2(150) NOT NULL,  
  INSTANCE VARCHAR2(100) NOT NULL,  
  DOMAINNAME VARCHAR2(50) NOT NULL,  
  CLUSTERNAME VARCHAR2(50) NOT NULL,  
  TIMEOUT DATE,  
  PRIMARY KEY (SERVER, DOMAINNAME, CLUSTERNAME)  
 );   

2) In weblogic server create Domain, with two managed servers MG1 and MG2 both belongs to a cluster CL.

3) In weblogic server create a Datasource.

4) In WLS Admin Console, click on Cluster CL->Scheduling Tab -> For Data Source For Job Scheduler select the datasource created in step 3.

5) While creating EJB in addition to implementing Remote you should implement javax.ejb.TimedObject.

6) In EJB you have method createTimer()(business method) which creates the timer as shown below

 

  public TimerHandle createMyTimer()  
   throws EJBException  
  {  
   TimerService timerService = context.getTimerService();  
   Timer timer = timerService.createTimer(30000L, "created timer");  
   this.timerHandler = timer.getHandle();  
   return this.timerHandler;  
  }  

 

7) In weblogic-ejb-jar.xml the configuration should be as shown below for clustered EJB

 <wls:weblogic-ejb-jar xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-ejb-jar" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="">  
   <!--weblogic-version:12.1.1-->  
        <wls:weblogic-enterprise-bean>  
           <wls:ejb-name>SampleTimer</wls:ejb-name>  
           <wls:stateless-session-descriptor>  
                <wls:stateless-clustering>  
                     <wls:home-is-clusterable>true</wls:home-is-clusterable>  
                     <wls:home-load-algorithm>round-robin</wls:home-load-algorithm>  
                     <wls:stateless-bean-is-clusterable>true</wls:stateless-bean-is-clusterable>  
                     <wls:stateless-bean-load-algorithm>round-robin</wls:stateless-bean-load-algorithm>  
                </wls:stateless-clustering>  
           </wls:stateless-session-descriptor>  
           <wls:enable-call-by-reference>false</wls:enable-call-by-reference>  
           <wls:jndi-name>TimerEjbjndi</wls:jndi-name>  
      </wls:weblogic-enterprise-bean>  
      <wls:timer-implementation>Clustered</wls:timer-implementation>  
 </wls:weblogic-ejb-jar>  

When you are creating Clustered EJB Timers mentioning <wls:timer-implementation>Clustered</wls:timer-implementation> is mandatory.

Below is the Client Code you need to call the Timer EJB to create the Timer

 

 public class TestClient  
 {  
  static String user = "weblogic";  
  static String password = "weblogic1";  
  static String url = "t3://localhost:7003,localhost:7005";  
  public TimerRemote timerBean = null;  
  public static Context getInitialContext()  
   throws Exception  
  {  
   Properties properties = new Properties();  
   properties.put("java.naming.factory.initial", "weblogic.jndi.T3InitialContextFactory");  
   properties.put("java.naming.provider.url", url);  
   properties.put("java.naming.security.principal", user);  
   properties.put("java.naming.security.credentials", password);  
   return new InitialContext(properties);  
  }  
  public void call() {  
   try {  
    Context ctx = getInitialContext();  
    TimerHome tHome = (TimerHome)ctx.lookup("TimerEjbjndi");  
    this.timerBean = tHome.create();  
    this.timerBean.createMyTimer();  
    Thread.sleep(10000);  
    this.timerBean.getTimerHandleForTimer();  
    System.out.println("DONE");  
   }  
   catch (Exception e) {  
    e.printStackTrace();  
   }  
  }  
  public static void main(String[] args)  
  {  
   new TestClient().call();  
  }  
 }  

Once you call the this.timerBean.createMyTimer() in the client code, createMyTimer() business method gets called in the Timer EJB and once the EJB is timed out ejbTimeout(Timer timer) method in EJB timer gets called. You can write your business logic in ejbTimeout() method once the timer is expired.

Download the Project

Download the EAR

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today