Quartzジョブを手動で起動する方法(JSF 2の例)

Quartzでは、以下のパターンで手動でジョブをトリガできます:

JobKey jobKey = new JobKey(jobName, jobGroup);
scheduler.triggerJob(jobKey);//trigger a job by jobkey

このチュートリアルでは、JSF 2 Webアプリケーションを表示し、 `dataTable`にすべてのQuartzジョブを表示し、ユーザーがリンクをクリックして手動でジョブを起動できるようにします。

使用されたツール:

  1. JSF 2.1.11

  2. クォーツ2.1.5

  3. Eclipse 4.2

  4. Maven 3

  5. Tomcat 6と7でテスト済み

1.プロジェクトディレクトリ

最終プロジェクトディレクトリ。

最終プロジェクトディレクトリ、title = "プロジェクトディレクトリ"、width = 480、height = 439

プロジェクトの依存関係

このチュートリアルのすべての依存関係

File:pom.xml

<project ...>

        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>2.1.11</version>
        </dependency>
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>2.1.11</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
        </dependency>

        <!-- solve method not found error in tomcat -->
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>el-impl</artifactId>
            <version>2.2</version>
        </dependency>

        <dependency>
            <groupId>com.sun.el</groupId>
            <artifactId>el-ri</artifactId>
            <version>1.0</version>
        </dependency>

        <!-- Quartz scheduler framework -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.1.5</version>
        </dependency>

        <dependency>
            <groupId>javax.transaction</groupId>
            <artifactId>jta</artifactId>
            <version>1.1</version>
        </dependency>

    </dependencies>

</project>

3.クォーツジョブ

2つのジョブを作成し、リスナーを介して 'web.xml’にJSFと統合します。

package com.mkyong.jobs;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class JobA implements Job {

    @Override
    public void execute(JobExecutionContext context)
        throws JobExecutionException {
        System.out.println("Job A is runing");

    }

}
package com.mkyong.jobs;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class JobB implements Job {

    @Override
    public void execute(JobExecutionContext context)
        throws JobExecutionException {
        System.out.println("Job B is runing");

    }

}

ファイル:quartz.properties

org.quartz.scheduler.instanceName = MyScheduler
org.quartz.threadPool.threadCount = 3
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
org.quartz.plugin.jobInitializer.class =org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames = quartz-config.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound = true

ファイル:quartz.config

<?xml version="1.0" encoding="UTF-8"?>
<job-scheduling-data
    xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData
    http://www.quartz-scheduler.org/xml/job__scheduling__data__1__8.xsd"
    version="1.8">

    <schedule>
        <job>
            <name>JobA</name>
            <group>GroupDummy</group>
            <description>This is Job A</description>
            <job-class>com.mkyong.jobs.JobA</job-class>
        </job>

        <trigger>
            <cron>
                <name>dummyTriggerNameA</name>
                <job-name>JobA</job-name>
                <job-group>GroupDummy</job-group>
                <!-- It will run every 30 seconds -->
                <cron-expression>0/30 **  **  **  **  ?</cron-expression>
            </cron>
        </trigger>
    </schedule>

    <schedule>
        <job>
            <name>JobB</name>
            <group>GroupDummy</group>
            <description>This is Job B</description>
            <job-class>com.mkyong.jobs.JobB</job-class>
        </job>

        <trigger>
            <cron>
                <name>dummyTriggerNameB</name>
                <job-name>JobB</job-name>
                <job-group>GroupDummy</job-group>
                <!-- It will run every 30 seconds -->
                <cron-expression>0/30 **  **  **  **  ?</cron-expression>
            </cron>
        </trigger>
    </schedule>
</job-scheduling-data>

File:web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app__2__5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app__2__5.xsd"
    id="WebApp__ID" version="2.5">

    <display-name>JavaServerFaces</display-name>

    <!-- Change to "Production" when you are ready to deploy -->
    <context-param>
        <param-name>javax.faces.PROJECT__STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>

    <!-- Welcome page -->
    <welcome-file-list>
        <welcome-file>faces/welcome.xhtml</welcome-file>
    </welcome-file-list>

    <!-- JSF mapping -->
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Map these files with JSF -->
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/** </url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>** .jsf</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>** .faces</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>** .xhtml</url-pattern>
    </servlet-mapping>

    <listener>
        <listener-class>
            org.quartz.ee.servlet.QuartzInitializerListener
        </listener-class>
    </listener>

</web-app>

4. JSF Bean

後で `dataTable`のデータを提供するJSF beanです。コンストラクタで、既存のすべてのジョブを取得してListに追加し、それを返します。

package com.mkyong.scheduler;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;

import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.ee.servlet.QuartzInitializerListener;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;

@ManagedBean(name = "scheduler")
@SessionScoped
public class SchedulerBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private Scheduler scheduler;

    private List<QuartzJob> quartzJobList = new ArrayList<QuartzJob>();

    public SchedulerBean() throws SchedulerException {

      ServletContext servletContext = (ServletContext) FacesContext
        .getCurrentInstance().getExternalContext().getContext();

     //Get QuartzInitializerListener
      StdSchedulerFactory stdSchedulerFactory = (StdSchedulerFactory) servletContext
        .getAttribute(QuartzInitializerListener.QUARTZ__FACTORY__KEY);

      scheduler = stdSchedulerFactory.getScheduler();

     //loop jobs by group
      for (String groupName : scheduler.getJobGroupNames()) {

       //get jobkey
        for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher
            .jobGroupEquals(groupName))) {

            String jobName = jobKey.getName();
            String jobGroup = jobKey.getGroup();

           //get job's trigger
            List<Trigger> triggers = (List<Trigger>) scheduler
                .getTriggersOfJob(jobKey);
            Date nextFireTime = triggers.get(0).getNextFireTime();

            quartzJobList.add(new QuartzJob(jobName, jobGroup, nextFireTime));

        }

      }

    }

   //trigger a job
    public void fireNow(String jobName, String jobGroup)
        throws SchedulerException {

        JobKey jobKey = new JobKey(jobName, jobGroup);
        scheduler.triggerJob(jobKey);

    }

    public List<QuartzJob> getQuartzJobList() {

        return quartzJobList;

    }

    public static class QuartzJob {

        private static final long serialVersionUID = 1L;

        String jobName;
        String jobGroup;
        Date nextFireTime;

        public QuartzJob(String jobName, String jobGroup, Date nextFireTime) {

            this.jobName = jobName;
            this.jobGroup = jobGroup;
            this.nextFireTime = nextFireTime;
        }

        public String getJobName() {
            return jobName;
        }

        public void setJobName(String jobName) {
            this.jobName = jobName;
        }

        public String getJobGroup() {
            return jobGroup;
        }

        public void setJobGroup(String jobGroup) {
            this.jobGroup = jobGroup;
        }

        public Date getNextFireTime() {
            return nextFireTime;
        }

        public void setNextFireTime(Date nextFireTime) {
            this.nextFireTime = nextFireTime;
        }

    }

}

5. JSFページ

Webページで、EL##scheduler.quartzJobListを介して既存のすべてのジョブを取得し、 `dataTable`コンポーネントを介して表示します。 「fireNow」リンクをクリックすると、指定したジョブがただちに起動されます。

File:welcome.xhtml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
    <h:outputStylesheet library="css" name="table-style.css"/>
</h:head>
<h:body>

  <h1>All Quartz Jobs</h1>
  <h:form>
    <h:dataTable value="#{scheduler.quartzJobList}" var="quartz"
        styleClass="quartz-table" headerClass="quartz-table-header"
        rowClasses="quartz-table-odd-row,quartz-table-even-row">

        <h:column>
          <!-- column header -->
          <f:facet name="header">Job Name</f:facet>
          <!-- row record -->
              #{quartz.jobName}
            </h:column>

        <h:column>
          <f:facet name="header">Job Group</f:facet>
              #{quartz.jobGroup}
            </h:column>

        <h:column>
          <f:facet name="header">Next Fire Time</f:facet>
          <h:outputText value="#{quartz.nextFireTime}">
              <f:convertDateTime pattern="dd.MM.yyyy HH:mm"/>
          </h:outputText>
        </h:column>

        <h:column>
          <f:facet name="header">Action</f:facet>
          <h:commandLink value="Fire Now"
             action="#{scheduler.fireNow(quartz.jobName, quartz.jobGroup)}"/>
        </h:column>

       </h:dataTable>
    </h:form>
</h:body>
</html>

File:table-style.css

.quartz-table{
    border-collapse:collapse;
}

.quartz-table-header{
    text-align:center;
    background:none repeat scroll 0 0 #E5E5E5;
    border-bottom:1px solid #BBBBBB;
    padding:16px;
}

.quartz-table-odd-row{
    text-align:center;
    background:none repeat scroll 0 0 #FFFFFFF;
    border-top:1px solid #BBBBBB;
    padding:20px;
}

.quartz-table-even-row{
    text-align:center;
    background:none repeat scroll 0 0 #F9F9F9;
    border-top:1px solid #BBBBBB;
    padding:20px;
}

6.デモ

最終出力を参照してください。 http://localhost:8080/JavaServerFaces/

すべての石英ジョブを一覧表示するには、title = "all-quartz-jobs"、width = 484、height = 254

ソースコードをダウンロードする

それをダウンロードする - JSF-Quartz-Trigger-Job-Manually.zip (28 kb)

参考文献

管理者ページの例]。 link://jsf2/jsf-2-quartz-2-example/[Quartz 2 JSF 2の統合

JavaDoc]。リンク://java/example-to-run-multiple-jobs-in-quartz/[複数のジョブ

石英]