Friday, March 15, 2013

Java EE 6 - Part 6 - Writing EJB TimerService and Interceptors

Project: EJB31-Common


package helloworld.beans;

import javax.ejb.Remote;
import javax.ejb.Timer;

/**
 * Interface to manage the EJB timer service.
 *
 * @author rwatsh
 */
@Remote
public interface AutomaticManagerBeanRemote {
    public void manageTimer(int interval, int threshold);

    void monitorAutomaticTimer(Timer timer);
}

Project:EJB31-ejb


package helloworld.beans;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;

/**
 * Bean implementation for controlling the timer service EJB.
 *
 * @author rwatsh
 */
@Stateless
public class AutomaticManagerBean implements AutomaticManagerBeanRemote {
    @EJB
    private AutomaticSayHelloBean automaticSayHelloBean;
    @Resource
    private TimerService timerService;
    private int threshold;
 
    @Override
    public void manageTimer(int interval, int threshold) {
        this.threshold= threshold;
        int currentCount = automaticSayHelloBean.getNotificationCount();
        if (currentCount >= threshold){
            automaticSayHelloBean.cancelTimer();
        } else {
            timerService.createIntervalTimer(interval, interval, null);
        }
    }
 
 

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")

    @Override
    @Timeout
    public void monitorAutomaticTimer(Timer timer) {      
        int currentCount = automaticSayHelloBean.getNotificationCount();
        if (currentCount >= threshold) {
            automaticSayHelloBean.cancelTimer();
            timer.cancel();
        }
    }

}
-------------------------
package helloworld.beans;

import helloworld.interceptors.PMInterceptor;
import helloworld.vo.GreetingRequest;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.LocalBean;
import javax.ejb.Schedule;
import javax.ejb.Startup;
import javax.ejb.Timer;
import javax.interceptor.Interceptors;

/**
 * This is a stateless bean using EJB timer service.
 *
 * @author rwatsh
 */
@Singleton
@LocalBean
@Startup
public class AutomaticSayHelloBean {

    @EJB
    private SingletonHelloWorldBean singletonHelloWorldBean;
    private int timerNotifications;
    private boolean cancelTimer = false;

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")
    /**
     * Using schedule will cause a timer notification to occur every 5 seconds.
     */
    @Interceptors(PMInterceptor.class)
    @Schedule(second = "*/5", minute = "*", hour = "*")
    public void sayHello(Timer timer) {
        if (!cancelTimer) {
            GreetingRequest request = singletonHelloWorldBean.sayHello();
            System.out.println("AutomaticSayHelloBean.sayHello:- " + request);
            timerNotifications++;
        } else {
            timer.cancel();
            System.out.println("AutomaticSayHelloBean.sayHello: canceled timer");
        }
    }

    public int getNotificationCount() {
        return timerNotifications;
    }

    public void cancelTimer() {
        this.cancelTimer = true;
    }
}

---------------------
package helloworld.interceptors;

import javax.interceptor.AroundTimeout;
import javax.interceptor.InvocationContext;

/**
 * Interceptor to monitor invocations of a method.
 *
 * @author rwatsh
 */
public class PMInterceptor {

    private long numberOfInvocations;

    @AroundTimeout
    public Object monitorInvocations(InvocationContext ic) throws Exception {
        try {
            Object returnValue = ic.proceed();
            numberOfInvocations++;
            System.out.println("PMInterceptor.monitorInvocations: invocation count -" + numberOfInvocations);
            return returnValue;
        } catch (Exception ex) {
            System.err.println("PMInterceptor.monitorInvocations: error occurred -" + ex);
        }
        return null;
    }
}
------------------------
Project: EJB31-app-client

package ejb31;

import helloworld.beans.AutomaticManagerBeanRemote;
import javax.ejb.EJB;

/**
 * Test the automatic timer bean through its session facade
 * AutomaticManagerBean.
 *
 * @author rwatsh
 */
public class MaMApp {

    @EJB
    private static AutomaticManagerBeanRemote automaticManagerBean;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        automaticManagerBean.manageTimer(1000 * 60, 50);
        System.out.println("MaMApp.main: started management process");
    }
}

Output:
INFO: TimeBasedHelloWorldBean.postConstruct
INFO: SingletonHelloWorldBean.postConstruct
INFO: AutomaticSayHelloBean.sayHello:- helloworld.vo.GreetingRequest [requestTime=3/15/13 10:49 AM, greeting=Good Morning]
INFO: PMInterceptor.monitorInvocations: invocation count -1
INFO: AutomaticSayHelloBean.sayHello:- helloworld.vo.GreetingRequest [requestTime=3/15/13 10:49 AM, greeting=Good Morning]
INFO: PMInterceptor.monitorInvocations: invocation count -2
INFO: AutomaticSayHelloBean.sayHello:- helloworld.vo.GreetingRequest [requestTime=3/15/13 10:49 AM, greeting=Good Morning]
INFO: PMInterceptor.monitorInvocations: invocation count -3
.....
INFO: helloworld.beans.SingletonHelloWorldBean: @PreDestroy

No comments:

Book notes: Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems, by Martin Kleppmann

My notes from the excellent book on how software has evolved to handle data from hierarchical databases to the NoSQL -  https://www.goodrea...