2011-10-07 81 views
2

我需要在我的Web应用程序中安排一项任务。该任务需要使用在部署期间初始化的Servlet的成员字段。我使用了EJB @Schedule。但是,当任务被触发时,成员字段为空。我猜这是因为我必须将@Stateless注释添加到servlet中才能使@Schedule正常工作,而我的Servlet实际上需要保持其状态?EJB @Schedule问题

如果是,我该如何以简单有效的方式解决我的任务?使用GlassFish的3

这里是我的代码

@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 
} 

编辑

了Java EE教程快照说:

企业bean容器的定时器服务使得您为除有状态会话bean以外的所有类型的企业Bean安排定时通知

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


EDIT 2

该servlet是必要的启动的cometd贝叶服务:见here原因。 MyMemberField表示一个包装类的唯一实例,它关注与代理的API(这是一个交易应用程序)的交互。此包装类实例在所有会话和用户中必须是唯一的。我在Servlet的init()上初始化它。 该包装类向代理发送请求并接收异步答案。也许最好在Bayeux配置器之外定义这个类,但我不知道如何定义它。作为一个servlet?作为一个托管Bean? 最重要的是,我需要与调度程序一起工作才能将预定消息发送给代理。所以,计划任务应该知道代理的包装类实例。

回答

4

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

  1. 由Web容器管理的servlet。 webcontainer很可能会创建一个类的单个实例来处理所有请求。
  2. 由EJB容器管理的无状态会话bean。 EJB容器很可能会创建该类的多个实例并将它们池化以处理EJB请求。

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

我对如何解决问题的建议取决于实例字段中存储了什么数据。它是应用程序范围的初始化数据吗?如果是这样,那么我将创建一个单独的@Singleton类,并使用@PostConstruct来初始化实例数据,然后将@Schedule移动到该类。它是依赖于请求的数据吗?如果是这样,那么我会使用TimerService.createCalendarTimer并通过TimerConfig的info参数将数据传递给timer方法。另外,如果您不需要保证计时器在应用程序停止或JVM崩溃时“赶上”,那么您可能需要考虑使用非持久性计时器。

1

@bkail砸在头上。您正在混合使用Servlet和EJB概念。将它们分成两个独立的类。

@Singleton 
public class FooTask { 

    private Foo foo; 

    @PostConstruct 
    public void init() { 
     foo = new Foo(); 
     foo.initialize(); 
    } 

    @Schedule(dayOfWeek = "Mon-Fri", hour = "21", minute = "59", second = "55") 
    public void run() { 
     System.out.println(foo); 
     // ... 
    } 

    public Foo getFoo() { 
     return foo; 
    } 

} 

如果您希望能够对由于某种原因,每一个servlet请求访问foo,那么你应该把它注射在你的servlet @EJB

@WebServlet("/foo/*") 
public class FooServlet extends HttpServlet { 

    @EJB 
    private FooTask fooTask; 

    @Override 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     System.out.println(fooTask.getFoo()); 
     // ... 
    } 

}