Apache Camelでのスケジューリング（Timer/Quartz2コンポーネント）

# はじめに

Apache Camelで指定した時間に処理を実行するためには、以下の3つのコンポーネントのいずれかを使用することになります。

- Timer
- Scheduler
- Quartz2

Timerコンポーネントは一定間隔ごとに処理を実行することができるシンプルなコンポーネントです。Schedulerも同様の機能を提供しますが、Timerコンポーネントよりも多くの機能を提供します。
一方、Quartz2はCRON式で実行時間を指定できる高機能のコンポーネントです。

通常はQuartz2コンポーネントを利用することになると思います。開発時に試しで動かすときにはTimerを利用することもあるかと思います。例えば、即時に10秒間隔で5回だけ実行してみたいなど。Schedulerは特に使用することはないと思いますし、私も使用したことはないため、今回は説明を省略します。

# Timerコンポーネント

Timerコンポーネントを使用するためのURIは以下のようになります。

```
timer:name[?options]
```

nameは単なる名前で、好きな名前を指定して構いません。
XML DSLで書いた時のサンプルTimerは以下のようになります。

```xml
		<route id="main_timer">
			<from uri="timer://timer_sample?fixedRate=true&amp;period=1000&amp;repeatCount=10" />
			<log message="Timer Processed..." />
		</route>
```

オプションはfixedRate、period、repeatCountの3つを指定しています。
fixedRateはできるだけ一定間隔で実行されるようになります。falseにすると徐々に間隔がずれていきます。
periodは実行の間隔で、例では1000(ms)毎に実行されます。
repeatCountは実行回数を指定します。例では10（回）実行されます。

実行例は以下のようになります。

```
[2019-10-26 10:15:55.088], [INFO ], main_timer, Camel (camel-1) thread #2 - timer://timer_sample, main_timer, Timer Processed...
[2019-10-26 10:15:56.075], [INFO ], main_timer, Camel (camel-1) thread #2 - timer://timer_sample, main_timer, Timer Processed...
[2019-10-26 10:15:57.076], [INFO ], main_timer, Camel (camel-1) thread #2 - timer://timer_sample, main_timer, Timer Processed...
[2019-10-26 10:15:58.075], [INFO ], main_timer, Camel (camel-1) thread #2 - timer://timer_sample, main_timer, Timer Processed...
[2019-10-26 10:15:59.075], [INFO ], main_timer, Camel (camel-1) thread #2 - timer://timer_sample, main_timer, Timer Processed...
[2019-10-26 10:16:00.076], [INFO ], main_timer, Camel (camel-1) thread #2 - timer://timer_sample, main_timer, Timer Processed...
[2019-10-26 10:16:01.076], [INFO ], main_timer, Camel (camel-1) thread #2 - timer://timer_sample, main_timer, Timer Processed...
[2019-10-26 10:16:02.075], [INFO ], main_timer, Camel (camel-1) thread #2 - timer://timer_sample, main_timer, Timer Processed...
[2019-10-26 10:16:03.076], [INFO ], main_timer, Camel (camel-1) thread #2 - timer://timer_sample, main_timer, Timer Processed...
[2019-10-26 10:16:04.075], [INFO ], main_timer, Camel (camel-1) thread #2 - timer://timer_sample, main_timer, Timer Processed...
```


# Quartz2コンポーネント

Quartz2コンポーネントを使用するためのURIは以下のようになります。

```
quartz://groupName/timerName?cron=expression
```


Quartz2コンポーネントを使用するためには、pom.xmlに以下の依存関係を追記します。


```xml:pom.xml
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-quartz2</artifactId>
			<version>${camel.version}</version>
		</dependency>
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz-jobs</artifactId>
			<version>2.3.0</version>
		</dependency>
```

XML DSLで書いた時のサンプルは以下のようになります。

```xml:camel-context.xml
		<route id="main_quartz">
			<from uri="quartz2://myGroupName/myTrigger?cron=0/10+*+*+*+*+?" />
			<log message="Processed..." />
		</route>
```

myGroupNameとmyTriggerはそれぞれQuartzグループ名、トリガー名になります。2つ合わせて一意である必要があります。
オプションのcronには、CRON式を指定します。

"cron=0/10+*+*+*+*+?"ですと、左から、秒、分、時、日、月、曜日、年を指定し、毎0秒から10秒毎に実行する意味になります。

CRON式の詳細は以下を参照してください。

- [Cron Trigger Tutorial ](http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html)

今回のサンプルの実行結果は以下のようになります。

```
[2019-10-26 11:02:00.020], [INFO ], main_quartz, DefaultQuartzScheduler-camel-1_Worker-1, main_quartz, Processed...
```

また、Exchangeのヘッダーを表示すると以下のようにスケジュールに関する情報が出力されます。
Quartz2でスケジュールが開始されると、"scheduledFireTime=Sat Oct 26 11:08:52 JST 2019"のようにスケジュールが実行された時間がヘッダーに自動で格納されます。

```
[2019-10-26 11:18:40.017], [INFO ], testLog, DefaultQuartzScheduler-camel-1_Worker-1, testLog, Exchange[ExchangePattern: InOnly, Headers: {breadcrumbId=ID-mky-PC-1572056310765-0-9, calendar=null, fireTime=Sat Oct 26 11:18:40 JST 2019, jobDetail=JobDetail 'myGroupName.myTrigger':  jobClass: 'org.apache.camel.component.quartz2.CamelJob concurrentExectionDisallowed: false persistJobDataAfterExecution: false isDurable: false requestsRecovers: false, jobInstance=org.apache.camel.component.quartz2.CamelJob@3e79dafc, jobRunTime=-1, mergedJobDataMap=org.quartz.JobDataMap@7d24345, nextFireTime=Sat Oct 26 11:18:50 JST 2019, previousFireTime=null, refireCount=0, result=null, scheduledFireTime=Sat Oct 26 11:18:40 JST 2019, scheduler=org.quartz.impl.StdScheduler@11395a2f, trigger=Trigger 'myGroupName.myTrigger':  triggerClass: 'org.quartz.impl.triggers.CronTriggerImpl calendar: 'null' misfireInstruction: 1 nextFireTime: Sat Oct 26 11:18:50 JST 2019, triggerGroup=myGroupName, triggerName=myTrigger}, BodyType: null, Body: [Body is null]]
```


# 参考

- [Quartz2 Component（公式サイト）](https://camel.apache.org/components/latest/quartz-component.html)
- [Scheduler Component（公式サイト）](https://camel.apache.org/components/latest/scheduler-component.html)
- [Timer Component（公式サイト）](https://camel.apache.org/components/latest/timer-component.html)