先日書いた↓は、SpringMVCを使ってActiveMQにキューイングする処理でしたが、
SpringのJmsTemplateを使ってActiveMQにキューイング | shinodogg.com
今日は、MQからバッチでデータを取り出す処理を実装してみます。
■ Spring Batch
Spring Batchについては今までちょいちょいブログ書いてきましたが、
今日動かしたら以下のエラーを出力して動きませんでしたw
まぁ、要は管理テーブル既に作っちゃってあるから、エラーだぜぃと。
そんなもんイイ感じに、、って思いますが、対応します。
2011-09-21 16:47:04,679 ERROR [org.springframework.batch.core.launch.support.CommandLineJobRunner] - org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.jdbc.datasource.init.DataSourceInitializer#0': Invocation of init method failed; nested exception is org.springframework.dao.DataAccessResourceFailureException: Failed to populate database; nested exception is org.springframework.jdbc.datasource.init.ScriptStatementFailedException: Failed to execute SQL script statement at line 1 of resource class path resource [org/springframework/batch/core/schema-mysql.sql]: CREATE TABLE BATCH_JOB_INSTANCE ( JOB_INSTANCE_ID BIGINT NOT NULL PRIMARY KEY , VERSION BIGINT , JOB_NAME VARCHAR(100) NOT NULL, JOB_KEY VARCHAR(32) NOT NULL, constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY) ) ENGINE=InnoDB
SpringのJDBCのドキュメントみてくと、12.9 Initializing a DataSourceってところに、
割とドンピシャな記述が出てきます。
However, to get more control over the creation and deletion of existing data, the XML namespace provides a couple more options. The first is flag to switch the initialization on and off. This can be set according to the environment (e.g. to pull a boolean value from system properties or an environment bean), e.g. <jdbc:initialize-database data-source="dataSource" enabled="#{systemProperties.INITIALIZE_DATABASE}"> <jdbc:script location="..."/> </jdbc:initialize-database>
スタックトレース的にもDataSourceInitializerってヤツがこの辺を解釈してホゲホゲしてそうなので、
JavaDocみてみると、setEnabledってメソッドがあって、
こいつが最初にアレやコレやするのを制御してるみたいです。
public void setEnabled(boolean enabled) Flag to explicitly enable or disable the database populator. Parameters: enabled - true if the database populator will be called on startup
ということで、falseにして流したら大丈夫になりました。
<jdbc:initialize-database data-source="dataSource" enabled="false"> <jdbc:script location="${batch.schema.script}" /> </jdbc:initialize-database>
■ module-context.xml
Spring BatchではJobとStepをXMLで組み合わせて処理を動かすわけですが、
STSでSpring Batch Project作った時に出来るサンプルジョブの定義を拝借して、
以下のように定義しました。
<batch:job id="jobFromMqToMySQL"> <batch:step id="step2" > <batch:tasklet transaction-manager="transactionManager" start-limit="100" > <batch:chunk reader="mq_reader" writer="updater" commit-interval="1" /> </batch:tasklet> </batch:step> </batch:job>
mq_readerってのがMQから読むヤツで、
@Component("mq_reader") public class MQReader implements ItemReader<String> {
updaterってのがMySQLを更新するヤツ。
@Component("updater") public class Updater implements ItemWriter<Object> {
■ launch-context.xml
以下のようにJMSの定義を設定します。コレはWeb側(SpringMVC)の設定が使いまわせて、
必要なMavenの定義とかも同じ感じでイケます。
<bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="tcp://localhost:61616" /> </bean> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="jmsFactory" /> <property name="defaultDestinationName" value="TestQueue" /> </bean>
■ アプリケーション
SpringMVCと同様にJmsTemplateをアノテーションでインジェクションしてやって、
MQからJSON文字列取得してバリューオブジェクトに戻してやります。
#シリアライザブルなバリューオブジェクトってそのままMQ突っ込めそうだけど、
#その辺は @atushi がイイ感じやってくれるかなと…w
@Autowired private JmsTemplate jmsTemplate; public String read() throws Exception { String jmsStr = (String)jmsTemplate.receiveAndConvert(); Hoge hoge = (Hoge)JSON.decode(jmsStr, Hoge.class); System.out.println("HogeStr : " + hoge.getHogeStr()); return hoge.getHogeStr(); }
■ 動作確認
ActiveMQ立ち上げて管理画面表示
SpringMVCのWeb画面からのリクエストでキューイング
ActiveMQの管理画面で↓こんなグラフが見れたりします。
バッチジョブ動かしてやって処理がちゃんと動くの確認して、
2011-09-21 16:40:59,948 INFO [org.springframework.batch.core.launch.support.SimpleJobLauncher] - 2011-09-21 16:40:59,964 INFO [org.springframework.batch.core.job.SimpleStepHandler] - HogeStr : aaaaa 2011-09-21 16:41:00,188 INFO [com.shinodogg.Updater] -
MQの管理画面的にもキューイングされてたの、全部取り出されましたよ的な。
日経BP社
売り上げランキング: 76547
コメント