承接第一篇,已定義 EJB 業務方法與 Quartz Servlet。本文完成自動啟動、打包部署、容器執行緒配置與驗證。
在 web.xml 註冊兩個 Servlet,並設定 load-on-startup 確保容器啟動時初始化:
<servlet>
<servlet-name>QuartzInitializer</servlet-name>
<servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>QuartzServlet</servlet-name>
<servlet-class>howto.quartz.servlet.QuartzServlet</servlet-class>
<init-param>
<param-name>cronExpr</param-name>
<param-value>0 0/30 * * * ?</param-value> <!-- 每 30 分鐘 -->
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
QuartzServlet 需透過 JNDI 查找 EJB,故需在 web.xml 宣告 ejb-ref:
<ejb-ref>
<ejb-ref-name>ejb/TestEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>howto.quartz.ejb.TestEJBHome</home>
<remote>howto.quartz.ejb.TestEJB</remote>
</ejb-ref>
quartz.jar、commons-logging.jar、commons-pool.jar 於 WEB-INF/lib;quartz.properties 置於 WEB-INF/classes。TestEJB 實作與介面。quartz-app.ear 部署至 J2EE 容器(文中以 OC4J 為例)。Quartz 使用自身執行緒池,非容器管理執行緒。OC4J 需以 -userThreads 參數啟動:
java -jar oc4j.jar -userThreads
其他容器請參閱對應文件啟用「非受管執行緒」或「使用者執行緒」選項。
server.xml:
<application name="quartz" path="../applications/quartz-app.ear" auto-start="true"/>
http-web-site.xml:
<web-app application="quartz" name="quartz-web" load-on-startup="true" root="/quartz"/>
部署完成後,EJB 的 yourMethod() 將依 Cron 運算式(每 30 分鐘)自動被觸發執行。
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 共享資料庫鎖定。quartz.properties 調優:threadPool.threadCount、jobStore.misfireThreshold。RuntimeException,Quartz 預設會重試,建議冪等設計。