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"
サンプルの画面を開き、バッチを動かします。
バッチジョブの状態が保存されているか確認します。H2コンソールを開き、ExampleDSとして定義されているインスタンス(JDBC URLは「jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE」)に接続します。
五つあるテーブルのうちCONTACTはバッチサンプルのアプリデータ、残りはバッチジョブの状態を保存するテーブルです。JOB_EXECUTIONテーブルを見ると、各バッチジョブの実行結果が記録されているのが分かります。
EAP7のバッチの実装であるJBeretでは、JDBC以外にもMongoDBやInfinispanに保存できるようですが、EAP7のbatch-jberetサブシステムにはそのような設定項目は無いようです。