JBoss EAP 7でJDBCバッチジョブリポジトリ

Java EE 7からバッチジョブを作成できるようになりました。バッチジョブの状態は永続化されますが、JBoss EAP 7ではデフォルトの保存先がインメモリとなっています。これをデータベースに変更してみます。

EAP7を起動し、バッチジョブのJDBCバッチジョブリポジトリを定義します。EAP7ではH2 Databaseのデータソースが定義済みなのでこれを使ってみます。尚、手元の環境では、定義済みデータソースのパスワードが誤っており接続できませんでした。これを事前に修正します。

$ cd $JBOSS_HOME/bin
$ ./standalone.sh
$ ./jboss-cli.sh -c
# ExampleDSの設定を修正する(saというパスワードが指定されているが、パスワード無しが正解)。
[standalone@localhost:9990 /] data-source disable --name=ExampleDS
[standalone@localhost:9990 /] /subsystem=datasources/data-source=ExampleDS:undefine-attribute(name=password)
[standalone@localhost:9990 /] data-source enable --name=ExampleDS
[standalone@localhost:9990 /] data-source test-connection-in-pool --name=ExampleDS
true
# バッチジョブの保存先をデータベースに変更する。
[standalone@localhost:9990 /] /subsystem=batch-jberet/jdbc-job-repository=batch-repos-on-exampleds:add(data-source=ExampleDS)
[standalone@localhost:9990 /] /subsystem=batch-jberet:write-attribute(name=default-job-repository, value=batch-repos-on-exampleds)
[standalone@localhost:9990 /] :reload

続いてEAP7に同梱されているバッチのサンプル「batch-processing」をデプロイしますが、その前に少し手直しします。

手直しせず動かすと以下のエラーが出ました。このサンプルは、連絡先のテキストファイルを読み込みデータベースに保存するバッチジョブですが、アプリの接続先とバッチジョブの保存先が異なるデータソースのため、XAデータソースでないとダメなようです。

2016-07-14 12:34:19,662 ERROR [org.jberet] (Batch Thread - 1) JBERET000007: Failed to run job import-file, import-file-chunk, org.jberet.job.model.Chunk@49a55147: javax.batch.operations.BatchRuntimeException: JBERET000622: Failed to obtain connection from org.jboss.as.connector.subsystems.datasources.WildFlyDataSource@19e76b7
 at org.jberet.repository.JdbcRepository.getConnection(JdbcRepository.java:972)
 at org.jberet.repository.JdbcRepository.updateStepExecution(JdbcRepository.java:648)
 at org.jberet.repository.JdbcRepository.savePersistentData(JdbcRepository.java:685)
 at org.wildfly.extension.batch.jberet.job.repository.JobRepositoryService.savePersistentData(JobRepositoryService.java:189)
 at org.wildfly.extension.batch.jberet.job.repository.JdbcJobRepositoryService.savePersistentData(JdbcJobRepositoryService.java:44)
 at org.jberet.runtime.context.StepContextImpl.savePersistentData(StepContextImpl.java:190)
 at org.jberet.runtime.runner.ChunkRunner.doCheckpoint(ChunkRunner.java:538)
 at org.jberet.runtime.runner.ChunkRunner.readProcessWriteItems(ChunkRunner.java:317)
 at org.jberet.runtime.runner.ChunkRunner.run(ChunkRunner.java:201)
 at org.jberet.runtime.runner.StepExecutionRunner.runBatchletOrChunk(StepExecutionRunner.java:219)
 at org.jberet.runtime.runner.StepExecutionRunner.run(StepExecutionRunner.java:140)
 at org.jberet.runtime.runner.CompositeExecutionRunner.runStep(CompositeExecutionRunner.java:164)
 at org.jberet.runtime.runner.CompositeExecutionRunner.runFromHeadOrRestartPoint(CompositeExecutionRunner.java:88)
 at org.jberet.runtime.runner.JobExecutionRunner.run(JobExecutionRunner.java:59)
 at org.wildfly.extension.batch.jberet.impl.BatchEnvironmentService$WildFlyBatchEnvironment$1.run(BatchEnvironmentService.java:243)
 at org.wildfly.extension.requestcontroller.RequestController$QueuedTask$1.run(RequestController.java:497)
 at org.jberet.spi.JobExecutor$3.run(JobExecutor.java:161)
 at org.jberet.spi.JobExecutor$1.run(JobExecutor.java:99)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 at java.lang.Thread.run(Thread.java:745)
 at org.jboss.threads.JBossThread.run(JBossThread.java:320)
Caused by: java.sql.SQLException: javax.resource.ResourceException: IJ000457: Unchecked throwable in managedConnectionReconnected() cl=org.jboss.jca.core.connectionmanager.listener.TxConnectionListener@1755ff47[state=NORMAL managed connection=org.jboss.jca.adapters.jdbc.local.LocalManagedConnection@4b9896b4 connection handles=0 lastReturned=1468467259635 lastValidated=1468467240764 lastCheckedOut=1468467259633 trackByTx=false pool=org.jboss.jca.core.connectionmanager.pool.strategy.OnePool@53626e8e mcp=SemaphoreConcurrentLinkedQueueManagedConnectionPool@62e02ed2[pool=ExampleDS] xaResource=LocalXAResourceImpl@5ad6acbb[connectionListener=1755ff47 connectionManager=6e068928 warned=false currentXid=null productName=H2 productVersion=@PROJECT_VERSION@ (2013-07-28) jndiName=java:jboss/datasources/ExampleDS] txSync=null]
 at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:146)
 at org.jboss.as.connector.subsystems.datasources.WildFlyDataSource.getConnection(WildFlyDataSource.java:66)
 at org.jberet.repository.JdbcRepository.getConnection(JdbcRepository.java:970)
 ... 21 more
Caused by: javax.resource.ResourceException: IJ000457: Unchecked throwable in managedConnectionReconnected() cl=org.jboss.jca.core.connectionmanager.listener.TxConnectionListener@1755ff47[state=NORMAL managed connection=org.jboss.jca.adapters.jdbc.local.LocalManagedConnection@4b9896b4 connection handles=0 lastReturned=1468467259635 lastValidated=1468467240764 lastCheckedOut=1468467259633 trackByTx=false pool=org.jboss.jca.core.connectionmanager.pool.strategy.OnePool@53626e8e mcp=SemaphoreConcurrentLinkedQueueManagedConnectionPool@62e02ed2[pool=ExampleDS] xaResource=LocalXAResourceImpl@5ad6acbb[connectionListener=1755ff47 connectionManager=6e068928 warned=false currentXid=null productName=H2 productVersion=@PROJECT_VERSION@ (2013-07-28) jndiName=java:jboss/datasources/ExampleDS] txSync=null]
 at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.reconnectManagedConnection(AbstractConnectionManager.java:933)
 at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:750)
 at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:138)
 ... 23 more
Caused by: javax.resource.ResourceException: IJ000461: Could not enlist in transaction on entering meta-aware object
 at org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl.managedConnectionReconnected(TxConnectionManagerImpl.java:560)
 at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.reconnectManagedConnection(AbstractConnectionManager.java:928)
 ... 25 more
Caused by: javax.transaction.SystemException: IJ000356: Failed to enlist: java.lang.Throwable: Unabled to enlist resource, see the previous warnings. tx=TransactionImple < ac, BasicAction: 0:ffffc0a86470:7ba3905d:57870827:12 status: ActionStatus.ABORT_ONLY >
 at org.jboss.jca.core.connectionmanager.listener.TxConnectionListener$TransactionSynchronization.checkEnlisted(TxConnectionListener.java:943)
 at org.jboss.jca.core.connectionmanager.listener.TxConnectionListener.enlist(TxConnectionListener.java:394)
 at org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl.managedConnectionReconnected(TxConnectionManagerImpl.java:553)
 ... 26 more

手間を省くためXAデータソースを定義するかわりに、サンプルの接続先データベースをExampleDSにしてしまいます。

batch-processingをコピーし、JPAのデータソース指定を変更します。

$ cd path/to/jboss-eap-7.0.0.GA-quickstarts
$ cp -R batch-processing batch-processing-with-h2-repos

# src/main/resources/META-INF/persistence.xml を編集する。
...
 <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
...                                      ^^^^^^^^^

ビルドしてデプロイします。

$ mvn -Dmaven.test.skip=true clean package
$ cd $JBOSS_HOME/bin
$ ./jboss-cli.sh -c --command="deploy path/to/jboss-eap-7.0.0.GA-quickstarts/batch-processing-with-h2-repos/target/jboss-batch-processing.war"

H2 Databaseの中身を見るために、EAP7サンプルに同梱されているH2コンソールもデプロイします。

$ ./jboss-cli.sh -c --command="deploy path/to/jboss-eap-7.0.0.GA-quickstarts/h2-console/h2console.war"

サンプルの画面を開き、バッチを動かします。

batch-processing

バッチジョブの状態が保存されているか確認します。H2コンソールを開き、ExampleDSとして定義されているインスタンス(JDBC URLは「jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE」)に接続します。

h2console-login

五つあるテーブルのうちCONTACTはバッチサンプルのアプリデータ、残りはバッチジョブの状態を保存するテーブルです。JOB_EXECUTIONテーブルを見ると、各バッチジョブの実行結果が記録されているのが分かります。

h2console-select

EAP7のバッチの実装であるJBeretでは、JDBC以外にもMongoDBやInfinispanに保存できるようですが、EAP7のbatch-jberetサブシステムにはそのような設定項目は無いようです。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です