感謝のプログラミング 10000時間

たどり着いた結果(さき)は、感謝でした。

Spring Frameworkのsheduler機能を使って、定期的にツイートするbotを作ってみる。

スポンサーリンク

Springフレームワークのタスクスケジューリング機能を使えば、cronで実行するみたいに、Java上からタスクの定期実行ができる。
以前もSpringのタスクスケジューリングの機能のサンプルは作ったけれど(ブログ内検索でspringなど検索してみてください)、今回はちょっと応用してtwitter4jも使って、botを作ってみたい。

フォルダ構成

まずはフォルダ構成。eclipseを使って作ったんだけど、srcフォルダ以下はこのようになっている。

C:\ECLIPSE\PLEIADES\WORKSPACE\MY-SPRING\SRC
│  beans.xml
│  commons-logging.properties
│  log4j.xml
│
└─sample
    ├─scheduler
    │      Main.java
    │
    └─tweet
            TaskTweet.java
            TaskTweetImpl.java

src直下にbeans.xmlがあることに注意する。
beans.xmlの位置を間違えると、

Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource 

のようにエラーが出てしまう。

twitter4jでツイートするサンプル

まずは、定期実行するプログラムを作る。
twitter4jのバージョン3.0.4を使っている。
今までとアクセストークンの設定部分が少し違うので注意が必要だ。

インターフェース。

package sample.tweet;

public interface TaskTweet {
	public void tweet();
}

実装。

package sample.tweet;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;

public class TaskTweetImpl implements TaskTweet {
	private String consumerKey;
	private String consumerSecret;
	private String accessToken;
	private String accessTokenSecret;

	public void tweet() {
		Twitter twitter = getTwitter();
		try {
			System.out.println("tweetします!");
			System.out.println("スレッドID:" + Thread.currentThread().getId());
			twitter.updateStatus("hay! this is bot");
		} catch (TwitterException e) {
			e.printStackTrace();
		}
	}

	private Twitter getTwitter() {
		Twitter twitter = new TwitterFactory().getInstance();

		if (consumerKey == null || consumerSecret == null) {
			return null;
		}
		twitter.setOAuthConsumer(consumerKey, consumerSecret);

		if (accessToken == null) {
			return null;
		}

		AccessToken accessTokenObj = new AccessToken(accessToken, accessTokenSecret);
		twitter.setOAuthAccessToken(accessTokenObj);

		return twitter;
	}

	public String getConsumerKey() {
		return consumerKey;
	}

	public void setConsumerKey(String consumerKey) {
		this.consumerKey = consumerKey;
	}

	public String getConsumerSecret() {
		return consumerSecret;
	}

	public void setConsumerSecret(String consumerSecret) {
		this.consumerSecret = consumerSecret;
	}

	public String getAccessToken() {
		return accessToken;
	}

	public void setAccessToken(String accessToken) {
		this.accessToken = accessToken;
	}

	public String getAccessTokenSecret() {
		return accessTokenSecret;
	}

	public void setAccessTokenSecret(String accessTokenSecret) {
		this.accessTokenSecret = accessTokenSecret;
	}

}

cronみたいに設定する書き方

beans.xmlの書き方。
このようにbeans.xmlにアクセストークンなどを記載することで、設定を外出しにすることができる。

<?xml version="1.0" encoding="Windows-31J" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/task
	http://www.springframework.org/schema/task/spring-task-3.0.xsd">
	<bean id="tweetBean" class="sample.tweet.TaskTweetImpl">
	<!--
		<constructor-arg>
			<value>Spring</value>
		</constructor-arg>
	-->
		<property name="consumerKey">
			<value>XXXX</value>
		</property>
		<property name="consumerSecret">
			<value>YYYY</value>
		</property>
		<property name="accessToken">
			<value>ZZZZZ</value>
		</property>
		<property name="accessTokenSecret">
			<value>TTTTT</value>
		</property>
	</bean>

	<task:scheduler id="tweetScheduler" pool-size="5" />

	<task:scheduled-tasks scheduler="tweetScheduler">
		<task:scheduled ref="tweetBean" method="tweet"
			cron="30 * * * * ?" />
	</task:scheduled-tasks>

</beans>

task:schedulerのところで、定期実行するbeanを設定している。
どのメソッドを実行するかは、method="tweet"のところで設定している。

cron="30 * * * * ?"
||M
となっているのは、毎分30秒で実行するということだ。こうすると、1分おきにJavaのメソッドを実行できる。
この順番は、
秒 分 時 月 年 曜日
の順となっている。[*]はすべての値に一致させるとき、[?]は記述を省略するときに使用する。

実行するMainクラスはこんな感じ。
>|java|
package sample.scheduler;

import java.io.File;
import java.io.IOException;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class Main {
	public static void main(String[] args) throws IOException {
		ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		File newFile = new File("hoge.txt");
		newFile.createNewFile();
	}
}

さて、実際に起動してみると、1分おきにこんなメッセージが。

(略)
2013-10-27 02:09:19,498 INFO [org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler] - Initializing ExecutorService  'tweetScheduler'
tweetします!
スレッドID:9
tweetします!
スレッドID:9

これでSpringを使って、cronで動かすみたいに実行するツイッターbotを作ることができた!

読んだ本

SpringによるWebアプリケーションスーパーサンプル 第2版

SpringによるWebアプリケーションスーパーサンプル 第2版

Springを使うならまずこれ、という本。
サンプルが豊富で、動かしながら勉強することができる。
スーパーサンプルシリーズでもピカ一だと思う。

感謝のプログラミング

今回で感謝のプログラミングは【685時間目】
10000時間まで、あと【9315時間】