TimerService 與 Timer 回呼


以下使用一個簡單的範例,示範如何在Stateless Session Bean上使用Timer服務,客戶端可以指定時間啟動Timer,排定在某個時間送訊息給Message-Driven Bean。

首先定義一個簡單的介面:
  • IMaintain.java
package onlyfun.caterpillar;

import java.util.Date;
import javax.ejb.Local;

@Local
public interface IMaintain {
public void scheduleMessage(Date expiration, String message);
}

在Stateless Session Bean實作部份,使用@Resource注入TimerService、ConnectionFactory與Destination:
  • MaintainBean.java
package onlyfun.caterpillar;

import java.util.Date;
import javax.annotation.Resource;
import java.util.logging.*;
import javax.ejb.*;
import javax.jms.*;

@Stateless
public class MaintainBean implements IMaintain {
@Resource(name="jms/HelloQueueFactory")
private ConnectionFactory connectionFactory;

@Resource(name="jms/HelloQueue")
private Destination queue;

@Resource
private TimerService timerService;

public void scheduleMessage(Date expiration, String message) {
timerService.createTimer(expiration, message);
}

@Timeout
public void sendMessage(Timer timer) {
try {
String message = (String) timer.getInfo();

Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(
false, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = session.createProducer(queue);
TextMessage textMessage = session.createTextMessage();
textMessage.setText(message);
producer.send(textMessage);

producer.close();
session.close();
connection.close();
} catch (JMSException ex) {
Logger.getLogger(
MaintainBean.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

如果您想要從EJBContext中取得TimerService,則可以如下:
...
@Resource
private SessionContext context;

public void scheduleMessage(Date expiration, String message) {
    TimerService timerService = context.getTimerService();
    timerService.createTimer(expiration, message);
}
....

若不使用@Timeout標註,則您要實作TimedObject介面,實作其void ejbTimeout(Timer timer)方法。

為了配合這個範例,改寫一下 第 一個 Message-Driven Bean 中的Message-Driven Bean範例:
  • HelloMessageBean.java
package onlyfun.caterpillar;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

@MessageDriven(mappedName = "jms/HelloQueue",
activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode",
propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue")
})
public class HelloMessageBean implements MessageListener {

public void onMessage(Message message) {
try {
TextMessage txtMessage = (TextMessage) message;
System.out.println(txtMessage.getText() + " processed....Orz");
} catch (JMSException ex) {
Logger.getLogger(HelloMessageBean.class.getName())
.log(Level.SEVERE, null, ex);
}
}
}

以下是個簡單的Servlet客戶端測試,排定在呼叫後的10秒鐘執行:
  • HelloServlet.java
package onlyfun.caterpillar;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import javax.ejb.EJB;

public class HelloServlet extends HttpServlet {
@EJB
private IMaintain maintain;

protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MILLISECOND, 10000);
maintain.scheduleMessage(calendar.getTime(), "save me....XD");
}

protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}

public String getServletInfo() {
return "Short description";
}
}