基本的に、候補ファイルを検索するフォルダーを読み取るためのカスタム itemreader、ファイルを読み取って別のファイルに変換するためのカスタム itemprocessor、およびファイルを削除するためのカスタム itemwriter を備えた Spring Batch に基づくアプリケーションを作成しました。スケジューラを追加するまで、エラーなしで期待どおりに動作します。スケジューラを追加した後、質問のトピックに貼り付けられたエラーが表示されます。同様の問題であるが、コンテキストが非常に異なるいくつかの質問を見つけました。奇妙な点は、実際には、コンソールにそのようなエラーが表示されていても、機能していることです。つまり、フォルダが読み込まれ(itemreader)、ファイルが変換され(itemprocessor)、入力ファイルが削除されます(itemwriter)。私は非常に混乱しています。スケジューラなしでエラーを再現できれば、次に、一部のノードに焦点を当てるか、スケジューラを導入した後に結果が得られなかったため、スケジューラ構成で発生する可能性のあるエラーに焦点を当てることができましたが、どちらもそうではありません. どんな提案も高く評価されます。
次の段落は 1 月 10 日に追加されました。詳細な調査の結果、このようなエラーはメイン スレッドで 1 回だけ発生することがわかりました。つまり、アプリケーションを開始したときに候補者ファイルがあると、WRONG_DOCUMENT_ERR が返されます。たとえば、CustomItemReader で見つけられるファイルがない状態でアプリケーションを開始し、メイン スレッドが終了するまで待ってから、CustomItemReader で見つけられる候補ファイルを配置すると、エラーはまったく発生しません。つまり、CustomItemReader が pool-2-thread-1 によってトリガーされ、ファイルを見つけると、正しく機能します。一方、CustomItemReader がメイン スレッドによってトリガーされ、アプリケーションの起動時にのみ発生するファイルを見つけると、問題が発生します。JConsole を使用して、メイン スレッドが終了し、pool-2-thread-1 が稼働していることを確認できます。それで、入力フォルダーにファイルを追加すると、CustomItemReader は null ではなく文字列を返し、エラーは発生しません。確かに、Spring Scheduller と Spring Batch を一緒に使用することについて、特定の概念がありませんでした。明らかに、アプリケーションを起動してすぐに初期化されたファイルを見つけた場合に、アプリケーションでエラーが発生しないようにしたいと考えています。メインスレッドでのみ発生するのに、Spring Scheduller を取り出した場合、一度は期待どおりに動作するのはなぜですか? 同期パラメータが不足していますか? メインスレッドでのみ発生するのに、Spring Scheduller を取り出した場合、一度は期待どおりに動作するのはなぜですか? 同期パラメータが不足していますか? メインスレッドでのみ発生するのに、Spring Scheduller を取り出した場合、一度は期待どおりに動作するのはなぜですか? 同期パラメータが不足していますか?
次の段落は 1 月 11 日に追加されました。大きなスニペットでエラーが発生するクラスのみを更新しました。他のすべては同じままです。
@Component
public class Queue {
private Node queue;
@Autowired
private Environment env;
public Element myMethod(String file) {
//...
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document d = docBuilder.parse(env.getProperty("certainFile.xml"));
Element template = d.getDocumentElement();
queue = d.createElement("c:file");
((Element) queue).setAttribute("xmlns:c", "myApp");
queue.appendChild(queue.getOwnerDocument().importNode(template, true));
template = (Element) queue.getLastChild();
addField(template, "someFieldLabel");
}
private void addField(Element message, String field) {
// ....
Element newField = queue.getOwnerDocument().createElement(field);
for (int k = 0; k < certainList.getLength(); k++) {
if ("...certain logic") {
newField = (Element) queue.getOwnerDocument().importNode(fieldFormat, true);
if ("...other logic"){
newField.setAttribute("manual", "true");
}
newField.removeAttribute("indicator");
break;
}
}
for (int j = 0; j < fields.getLength(); j++) {
Element e = (Element) (fields.item(j));
if (e.getNodeName().equals(fieldType)) {
// some cascades "ifs"
// the error happens in next line but only in the main thread
message.insertBefore(newField, e);
// let's ignore the rest
}
}
}
//----
@Configuration
@ComponentScan("com.example")
@EnableBatchProcessing
@EnableAutoConfiguration
@EnableScheduling
@PropertySource(value="classpath:config.properties")
@PropertySource(value="classpath:ipm.properties",ignoreResourceNotFound=true)
public class BatchConfiguration {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Bean
public Step step1(ItemReader<String> reader, ItemProcessor<String, String> processor, ItemWriter<String> writer) {
return stepBuilderFactory.get("step1").<String, String> chunk(1)
.reader(reader).processor(processor).writer(writer).allowStartIfComplete(true)
.build();
}
@Bean
public ItemProcessor<String , String> processor(){
return new CustomItemProcessor();
}
@Bean
public ItemWriter<String> writer() {
return new CustomItemWriter();
}
@Bean
public Job job(Step step1) throws Exception {
return jobBuilderFactory.get("job1")
.incrementer(new RunIdIncrementer()).start(step1).build();
}
@Bean
@StepScope
public ItemReader<String> reader() {
return new CustomItemReader();
}
}
//-----
public class CustomItemReader implements ItemReader<String> {
private static final Logger log = LoggerFactory
.getLogger(CustomItemReader.class);
@Autowired
private Environment env;
@Override
public String read() throws Exception, UnexpectedInputException,
ParseException, NonTransientResourceException {
String[] stringArray;
try (Stream<Path> stream = Files.list(Paths.get(env
.getProperty("myFile")))) {
stringArray = stream.map(String::valueOf)
.filter(path -> path.endsWith("out"))
.toArray(size -> new String[size]);
}
if (stringArray.length > 0) {
log.info("read method - file found");
return stringArray[0];
} else {
log.info("read method - no file found");
return null;
}
}
}
//----
public class CustomItemProcessor implements ItemProcessor<String , String> {
@Autowired
@Qualifier(value="queue")
private Queue q;
@Autowired
private Environment env;
@Override
public String process(String s) throws Exception {
q.myMethod();
return s;
}
}
//----
public class CustomItemWriter implements ItemWriter<String> {
@Override
public void write(List<? extends String> s) throws Exception {
Path path1 = Paths.get(s, “notImportantDetail”);
java.nio.file.Files.deleteIfExists(path1);
}
}
//----
@Component
public class QueueScheduler {
private static final Logger log = LoggerFactory
.getLogger(QueueScheduler.class);
private Job job;
private JobLauncher jobLauncher;
@Autowired
public QueueScheduler(JobLauncher jobLauncher, @Qualifier("job") Job job){
this.job = job;
this.jobLauncher = jobLauncher;
}
@Scheduled(fixedRate=60000)
public void runJob(){
try{
jobLauncher.run(job, new JobParameters());
}catch(Exception ex){
log.info(ex.getMessage());
}
}
}
//----
:: スプリング ブート :: (v1.3.1.RELEASE)
2016-01-08 14:51:44.783 INFO 7716 --- [main] com.example.DemoApplication : PID 7716 の GH-VDIKCISV252 で DemoApplication を開始しています (C:\STS\wsRestTemplate\demo\target\classes で e049447 によって開始されましたC:\STS\wsRestTemplate\demo)
2016-01-08 14:51:44.788 INFO 7716 --- [メイン] com.example.DemoApplication: アクティブなプロファイルが設定されていないため、デフォルトのプロファイルにフォールバックします: デフォルト
2016-01-08 14:51:44.955 INFO 7716 --- [main] scaAnnotationConfigApplicationContext : org.springframework.context.annotation.AnnotationConfigApplicationContext@6e2c9341 の更新: 起動日 [Fri Jan 08 14:51:44 CST 2016]; コンテキスト階層のルート
2016-01-08 14:51:50.882 WARN 7716 --- [ main] oscaConfigurationClassEnhancer : @Bean メソッド ScopeConfiguration.stepScope は非静的であり、Spring の BeanFactoryPostProcessor インターフェースに割り当て可能なオブジェクトを返します。これにより、@Autowired、@Resource、および @PostConstruct などのアノテーションを、メソッドの @Configuration クラスを宣言する内で処理できなくなります。これらのコンテナーのライフサイクルの問題を回避するには、このメソッドに「静的」修飾子を追加します。詳細については、@Bean javadoc を参照してください。
2016-01-08 14:51:51.030 WARN 7716 --- [ main] oscaConfigurationClassEnhancer : @Bean メソッド ScopeConfiguration.jobScope は非静的であり、Spring の BeanFactoryPostProcessor インターフェースに割り当て可能なオブジェクトを返します。これにより、@Autowired、@Resource、および @PostConstruct などのアノテーションを、メソッドの @Configuration クラスを宣言する内で処理できなくなります。これらのコンテナーのライフサイクルの問題を回避するには、このメソッドに「静的」修飾子を追加します。詳細については、@Bean javadoc を参照してください。
2016-01-08 14:51:51.386 INFO 7716 --- [main] osjdeEmbeddedDatabaseFactory: 組み込みデータベースを開始しています: url='jdbc:hsqldb:mem:testdb', username='sa'
2016-01-08 14:51:52.503 WARN 7716 --- [メイン] osbclAbstractListenerFactoryBean : org.springframework.batch.item.ItemReader はインターフェースです。実装クラスは、アノテーション ベースのリスナー構成についてクエリされません。@Bean メソッドで @StepScope を使用する場合は、必ず実装クラスを返して、リスナー アノテーションを使用できるようにしてください。
2016-01-08 14:51:53.572 INFO 7716 --- [main] osjdbc.datasource.init.ScriptUtils : クラスパスリソースから SQL スクリプトを実行 [org/springframework/batch/core/schema-hsqldb.sql]
2016-01-08 14:51:53.667 INFO 7716 --- [main] osjdbc.datasource.init.ScriptUtils : 94 でクラスパス リソース [org/springframework/batch/core/schema-hsqldb.sql] から SQL スクリプトを実行しましたMS。
2016-01-08 14:51:54.506 INFO 7716 --- [メイン] osjeaAnnotationMBeanExporter: 起動時に JMX 公開用の Bean を登録しています
2016-01-08 14:51:54.617 INFO 7716 --- [pool-2-thread-1] osbcrsJobRepositoryFactoryBean: データベース タイプが設定されていません。次を示すメタ データを使用: HSQL
2016-01-08 14:51:54.744 INFO 7716 --- [main] osbabJobLauncherCommandLineRunner: デフォルトのコマンドラインを実行中: []
2016-01-08 14:51:54.745 INFO 7716 --- [main] osbcrsJobRepositoryFactoryBean: データベース タイプが設定されていません。次を示すメタ データを使用: HSQL
2016-01-08 14:51:54.912 INFO 7716 --- [pool-2-thread-1] osbclsupport.SimpleJobLauncher: TaskExecutor が設定されておらず、デフォルトで同期エグゼキューターに設定されています。
2016-01-08 14:51:54.961 INFO 7716 --- [main] osbclsupport.SimpleJobLauncher: TaskExecutor が設定されていません。デフォルトで同期エグゼキューターになります。
2016-01-08 14:51:55.044 INFO 7716 --- [pool-2-thread-1] osbclsupport.SimpleJobLauncher: ジョブ: [SimpleJob: [name=job1]] が次のパラメーターで起動されました: [{}]
2016-01-08 14:51:55.088 INFO 7716 --- [pool-2-thread-1] osbatch.core.job.SimpleStepHandler : 実行中のステップ: [step1]
2016-01-08 14:51:55.095 INFO 7716 --- [main] osbclsupport.SimpleJobLauncher: ジョブ: [SimpleJob: [name=job1]] が次のパラメーターで起動されました: [{run.id=1}]
2016-01-08 14:51:55.176 INFO 7716 --- [main] osbatch.core.job.SimpleStepHandler: 実行ステップ: [step1]
2016-01-08 14:51:55.245 INFO 7716 --- [メイン] com.example.CustomItemReader: メソッドの読み取り - 出力ファイル名の収集
2016-01-08 14:51:55.314 INFO 7716 --- [pool-2-thread-1] com.example.CustomItemReader: メソッドの読み取り - 出力ファイル名の収集
2016-01-08 14:51:55.440 INFO 7716 --- [pool-2-thread-1] com.example.CustomItemReader: メソッドの読み取り - ファイルが見つかりました
2016-01-08 14:51:55.443 INFO 7716 --- [pool-2-thread-1] com.example.CustomItemProcessor: プロセス メソッド:
2016-01-08 14:51:55.461 INFO 7716 --- [メイン] com.example.CustomItemReader: メソッドの読み取り - ファイルが見つかりました
2016-01-08 14:51:55.462 INFO 7716 --- [メイン] com.example.CustomItemProcessor: プロセス メソッド:
2016-01-08 14:51:57.088 ERROR 7716 --- [pool-2-thread-1] osbatch.core.step.AbstractStep : ジョブ job1 でステップ step1 を実行中にエラーが発生しました
org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR: ノードを作成したドキュメントとは別のドキュメントでノードが使用されています。
at com.sun.org.apache.xerces.internal.dom.ParentNode.internalInsertBefore(ParentNode.java:357) ~[na:1.8.0_45]
at com.sun.org.apache.xerces.internal.dom.ParentNode.insertBefore(ParentNode.java:288) ~[na:1.8.0_45]
at com.example.Queue.addField(Queue.java:1555) ~[classes/:na]
at com.example.Queue.addMessagesFromAuth(Queue.java:453) ~[classes/:na]
at com.example.CustomItemProcessor.process(CustomItemProcessor.java:45) ~[classes/:na]
at com.example.CustomItemProcessor.process(CustomItemProcessor.java:1) ~[classes/:na]
at org.springframework.batch.core.step.item.SimpleChunkProcessor.doProcess(SimpleChunkProcessor.java:126) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.step.item.SimpleChunkProcessor.transform(SimpleChunkProcessor.java:293) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:192) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:75) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:406) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:330) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133) ~[spring-tx-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:271) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:81) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:374) ~[spring-batch-infrastructure-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144) ~[spring-batch-infrastructure-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:257) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:200) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:392) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:135) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:306) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) [spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at com.sun.proxy.$Proxy44.run(Unknown Source) [na:na]
at com.example.QueueScheduler.runJob(QueueScheduler.java:33) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45]
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) [spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) [spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_45]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [na:1.8.0_45]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_45]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_45]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_45]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_45]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45]
2016-01-08 14:51:57.104 INFO 7716 --- [pool-2-thread-1] osbclsupport.SimpleJobLauncher: ジョブ: [SimpleJob: [name=job1]] が次のパラメーターで完了しました: [{}] および次のステータス: [FAILED]
2016-01-08 14:51:57.754 INFO 7716 --- [メイン] com.example.CustomItemWriter : 書き込み方法: [C:\myApp\from\0000000571900000999674MHlog.txt.out]
2016-01-08 14:51:57.761 INFO 7716 --- [メイン] com.example.CustomItemReader: メソッドの読み取り - 出力ファイル名の収集
2016-01-08 14:51:57.762 INFO 7716 --- [メイン] com.example.CustomItemReader: 読み取り方法 - ファイルが見つかりません
2016-01-08 14:51:57.783 INFO 7716 --- [main] osbclsupport.SimpleJobLauncher: ジョブ: [SimpleJob: [name=job1]] が次のパラメータで完了しました: [{run.id=1}] および次のステータス: [完了]
2016-01-08 14:51:57.786 INFO 7716 --- [ main] com.example.DemoApplication : DemoApplication を 13.693 秒で開始しました (JVM は 14.853 秒間実行されています)
2016-01-08 14:52:54.724 INFO 7716 --- [pool-2-thread-1] osbclsupport.SimpleJobLauncher: ジョブ: [SimpleJob: [name=job1]] が次のパラメーターで起動されました: [{}]
2016-01-08 14:52:54.750 INFO 7716 --- [pool-2-thread-1] osbatch.core.job.SimpleStepHandler: 実行中のステップ: [step1]
2016-01-08 14:52:54.755 INFO 7716 --- [pool-2-thread-1] com.example.CustomItemReader: メソッドの読み取り - 出力ファイル名の収集
2016-01-08 14:52:54.756 INFO 7716 --- [pool-2-thread-1] com.example.CustomItemReader: メソッドの読み取り - ファイルが見つかりません
2016-01-08 14:52:54.775 INFO 7716 --- [pool-2-thread-1] osbclsupport.SimpleJobLauncher: ジョブ: [SimpleJob: [name=job1]] が次のパラメーターで完了しました: [{}] および次のステータス: [完了]