2011-10-07 80 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()); 
     // ... 
    } 

}