本文介绍了EJB @Schedule问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在我的Web应用程序中安排一个任务。任务需要使用在部署期间初始化的 Servlet 的成员字段。我使用了 EJB @Schedule 。但是当任务被触发时,成员字段为空。我猜,原因在于我不得不向servlet添加 @Stateless 注释,以使 @Schedule 工作,我的Servlet需要保留其状态吗?



如果是的话,我如何以简单有效的方式启动我的任务?使用GlassFish 3



这是我的代码的快照

  @无状态//<  - 错误? 
public class myServlet extends GenericServlet {
private MemberField myMemberField = new MemberField();

@Override
public void init()throws ServletException {
myMemberField.initialize();
}
@Schedule(dayOfWeek =Mon-Fri,hour =21,minute =59,second =55)
public void myTask(){
System.out.println(myMemberField.toString());
}
//其他东西
}






编辑



Java EE教程说:

所以我的结论是,这种方式不适合在 Servlet 中使用。






编辑2



Servlet是启动CometD Bayeux服务所必需的:请参阅为什么。 MyMemberField表示一个封装类的唯一实例,它关心与代理API的交互(这是一个交易应用程序)。这个包装类实例在所有会话和用户中必须是唯一的。我在Servlet的 init()中初始化它。
这个包装类将请求发送给代理并接收异步答案。也许最好在Bayeux配置器之外定义这个类,但是我不知道如何定义它。作为一个servlet?作为托管Bean?
在上面,我需要使用调度程序来发送定时消息给代理。所以,计划的任务应该知道代理的包装类实例。

解决方案

当你注释一个servlet @Stateless时,你有创建了两个JavaEE组件:


  1. 由Web容器管理的servlet。 webcontainer很有可能创建一个类的单个实例来为所有请求提供服务。

  2. 由EJB容器管理的无状态会话bean。 EJB容器很可能会创建该类的多个实例,并将它们进行汇总以处理EJB请求。

当servlet处理初始请求时,servlet中的实例字段被初始化。当@Schedule运行时,EJB的实例字段被初始化为不同的东西。



我关于如何解决问题的建议取决于实例中存储的数据领域。是应用程序范围的初始化数据吗?如果是这样,那么我将使用@PostConstruct创建一个单独的@Singleton类,初始化实例数据,然后将@Schedule移动到该类。这是依赖于请求的数据吗?如果是这样,那么我将使用TimerService.createCalendarTimer,并通过TimerConfig的info参数将数据传递给timer方法。



另外,如果你不需要保证计时器在应用程序停止或JVM崩溃时赶上,那么您可能需要考虑使用非持久定时器。


I need to schedule a task in my web application. The task needs to use a member field of the Servlet that is initialized during deployment. I have used the EJB @Schedule. However when the task is fired, the member field is null. I guess that the cause lies in the fact that I had to add the @Stateless annotation to the servlet in order to make the @Schedule work, and my Servlet needs to preserve its state indeed?

If yes, how can I fire my task in a simple and efficace way? Using GlassFish 3

Here is a snapshot of my code

@Stateless  // <-- Wrong ??
public class myServlet extends GenericServlet {
    private MemberField myMemberField = new MemberField();

    @Override
    public void init() throws ServletException {
        myMemberField.initialize();
    }
    @Schedule(dayOfWeek = "Mon-Fri", hour = "21", minute = "59", second = "55")
    public void myTask() {
        System.out.println(myMemberField.toString());
    }
    // other stuff
}


EDIT

The Java EE Tutorial says:

So my conclusion is that this way is not suitable for being used in a Servlet.


EDIT 2

The servlet is necessary for starting the CometD Bayeux service: see here why. MyMemberField represents the unique instance of a wrapper class that cares of the interaction with the API of the broker (this is a trading application). This wrapper class instance must be unique across all sessions and users. I initialize it on init() of the Servlet.This wrapper class sends requests to the broker and receives asynchronous answers. Maybe it's better to define this class outside the Bayeux configurator, but I don't know how to define it. As a servlet? As a Managed Bean?On top on it, I need to work with a scheduler in order to send scheduled messages to the broker. So, the scheduled task should be aware of the broker's wrapper class instance.

解决方案

When you annotate a servlet @Stateless, you have created two JavaEE components:

  1. A servlet managed by the webcontainer. The webcontainer will most likely create a single instance of the class to service all requests.
  2. A stateless session bean managed by the EJB container. The EJB container will most likely create several instances of the class and pool them to handle EJB requests.

When the servlet handles the initial request, the instance field in the servlet is initialized. When the @Schedule runs, the instance field of the EJB is initialized to something different.

My recommendation for how to resolve the problem depends on what data is stored in the instance field. Is it application-wide initialization data? If so, then I would create a separate @Singleton class with an @PostConstruct that initializes the instance data, and then move the @Schedule to that class. Is it request-dependent data? If so, then I would use TimerService.createCalendarTimer and pass the data to the timer method via the info parameter of the TimerConfig.

As an aside, if you don't need a guarantee that the timer will "catch up" while the application is stopped or if the JVM crashes, then you might want to consider using a non-persistent timer.

这篇关于EJB @Schedule问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-26 21:48