【问题标题】:How to get the timer scheduled tasks done in EJB如何在 EJB 中完成计时器计划任务
【发布时间】:2016-03-25 21:41:10
【问题描述】:

我想要实现的功能:

  1. 安排时事通讯发送给客户
  2. 我有一个允许用户触发计划的 JSF 页面。一旦触发了新的日程安排,该日程安排信息将被添加到同一页面的进度部分。进度部分是一个表格,其中每一行代表一个时间表。每个时间表显示已发送的电子邮件数量。单击“刷新”按钮后,进度表会刷新以显示当前状态。

使用的相关技术

  • JSF
  • EJB

问题

我已经安排了电子邮件,但我不知道如何在 JSF 页面上检索状态

我的会话 bean 看起来像这样:

@Stateless
public class DefaultEmailScheduleService implements EmailScheduleService {

Queue<String> emailAddresses;

@Resource
TimerService timerService;

@EJB
EmailService emailService;

@PostConstruct
private void postConst() {

}

@Override
public void scheduleEmails(ScheduleExpression se, Collection<String> emailAddresses) {
    //set timer
    this.emailAddresses = new ConcurrentLinkedQueue<>(emailAddresses);
    TimerConfig timerConfig = new TimerConfig();
    timerConfig.setPersistent(false);
    Timer timer = timerService.createCalendarTimer(se, timerConfig);

    //TODO update newsletter/email history

}

@Timeout
public void send(Timer timer) {
    if(!emailAddresses.isEmpty()){
        Newsletter newsletter = new Newsletter();
        newsletter.setTo(emailAddresses.poll());
        newsletter.setSubject("Testing");
        newsletter.setContent("This is testing newsletter");
        emailService.send(newsletter);
        System.out.println(newsletter.getFrom() + " --- sent");
    }
    else {
        System.out.println("no more emails");
        timer.cancel();
    }
}


}

我的解决方案

到目前为止,我发现的有点骇人听闻的解决方案是,每次发送从队列轮询的 Newsletter 对象时,我都会将此 Newsletter 对象保存到应用程序范围的 bean(如一个单例),以便 JSF 页面可以检索发送的时事通讯。当队列为空时,我清理 Application bean 并更新数据库。但是,出于某种原因,我觉得这种方法有点味道。

非常感谢任何帮助。

【问题讨论】:

    标签: java jsf-2


    【解决方案1】:

    如果我对您的理解正确,您的 scheduleEmails() 方法正在创建一个 Timer 对象。如果您想在 UI 中为计划的计时器提供一些状态,您将要保存此对象,直到计时器到期或要取消它。

    编辑: 我想我现在对你的问题有了更好的处理。根据您是否可以让多个用户发送到不同的列表,这将影响您需要的 bean 范围的类型。除此之外,我认为您应该简化您的课程安排将引用这个新 bean 的计时器。此 bean 将跟踪仍需要发送多少电子邮件,并实际构建要发送的电子邮件。然后,您可以使用这个新 bean 来支持您的 UI 并向用户提供更新。

    如果你想让它对用户更敏感,你可以使用一些 JavaScript 通过 AJAX 定期轮询更新,或者你可以使用 web 套接字,以便服务器可以在应该更新时通知客户端。

    【讨论】:

    • 到目前为止我发现的有点骇人听闻的解决方案,我认为可行的是,每次发送从队列轮询的 Newsletter 对象时,我都会将此 Newsletter 对象保存到应用程序范围的 bean(如单例),以便 JSF 页面可以检索发送的时事通讯。当队列为空时,我清理 Application bean 并更新数据库。但是,出于某种原因,我觉得这种方法有点味道。
    • 好的,我想我误解了你的问题,听起来计时器除了可能有助于通知用户状态更新外,与你的问题没什么关系。因此,例如,如果您有 1000 个电子邮件收件人,而您每秒只能发送一封,那么完成发送给所有人需要 1000 秒。因此,在发送所有电子邮件的过程中,您希望用户看到大意是 1000 封电子邮件中有 203 封已发送?
    • 感谢您的回复。在我的程序中,计时器设置为每分钟,换句话说,send() 在计划开始后每分钟触发一次。一旦计划开始,我希望用户能够通过点击 Refresh 按钮来查看进度。进度类似于 1000 封电子邮件中的 234 封 封电子邮件已发送。它不必是实时的。只要我可以告诉用户点击 Refresh 时发生了什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-11
    • 2012-05-23
    • 1970-01-01
    • 2012-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多