我创建了一个基于Spring Batch的应用程序,它基本上有一个自定义项目阅读器,用于读取搜索候选文件的文件夹,一个自定义迭代处理器,用于读取文件并将其转换为diferente文件和自定义项目编写器以删除文件。它按预期工作,没有错误,直到我添加了一个scheduller。在我添加了scheduller后,我得到了问题主题中粘贴的错误。我发现了一些类似问题的问题,但非常不同。必须奇怪的是,事实上,即使我在控制台上看到这样的错误,它仍然有效。我的意思是,读取文件夹(itemreader),转换文件(itemprocessor)并删除输入文件(itemwriter)。 我很迷茫。如果我可以在没有scheduller的情况下重现错误,那么我可以专注于某个节点,或者在我介绍scheduller之后我没有得到结果所以我可以专注于我的scheduller配置中的一些可能的错误,但两者都不是案件。任何建议都会得到赞赏。
下一段是在1月10日添加的:经过深入调查后,我发现这种错误只发生一次,只发生在主线程上。我的意思是,如果我在启动应用程序时有候选文件,那么我会得到WRONG_DOCUMENT_ERR。让我们说,我启动我的应用程序,没有CustomItemReader可以找到的文件,等到主线程完成,然后我放置一个候选文件,由CustomItemReader找到,根本不会有任何错误。换句话说,当pool-2-thread-1触发CustomItemReader并找到一个文件时,它可以正常工作。另一方面,当主线程触发CustomItemReader并找到仅在应用程序启动期间发生的文件时,会导致问题。 通过使用JConsole,我可以检查主线程是否已经消失,并且pool-2-thread-1已启动并正在运行。然后,我在输入文件夹中添加我的文件,导致CustomItemReader返回String而不是null,并且不会有错误。当然,我错过了一起使用Spring Scheduller和Spring Batch的某些概念。显然,如果我启动它,我希望我的应用程序不会引发错误,并且很快就会找到该文件。为什么它只发生在主线程中,但是如果我把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());
}
}
}
// ----
:: Spring Boot ::(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 --- [main] 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] o.s.c.a.ConfigurationClassEnhancer:@Bean方法ScopeConfiguration.stepScope是非静态的,并返回一个可分配给Spring的BeanFactoryPostProcessor接口的对象。这将导致无法在声明@Configuration类的方法中处理@Autowired,@ Resource和@PostConstruct等注释。添加&#39;静态&#39;修改此方法以避免这些容器生命周期问题;有关完整的详细信息,请参阅@Bean javadoc。
2016-01-08 14:51:51.030 WARN 7716 --- [main] o.s.c.a.ConfigurationClassEnhancer:@Bean方法ScopeConfiguration.jobScope是非静态的,并返回一个可分配给Spring的BeanFactoryPostProcessor接口的对象。这将导致无法在声明@Configuration类的方法中处理@Autowired,@ Resource和@PostConstruct等注释。添加&#39;静态&#39;修改此方法以避免这些容器生命周期问题;有关完整的详细信息,请参阅@Bean javadoc。
2016-01-08 14:51:51.386 INFO 7716 --- [main] osjdeEmbeddedDatabaseFactory:启动嵌入式数据库:url =&#39; jdbc:hsqldb:mem:testdb&#39;,username =&#39 ; SA&#39;
2016-01-08 14:51:52.503 WARN 7716 --- [main] o.s.b.c.l.AbstractListenerFactoryBean:org.springframework.batch.item.ItemReader是一个接口。不会为基于注释的侦听器配置查询实现类。如果在@Bean方法上使用@StepScope,请确保返回实现类,以便可以使用listner注释。
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:从类路径资源执行的SQL脚本[org / springframework / batch / core / schema-hsqldb。 s ms]在94毫秒。
2016-01-08 14:51:54.506 INFO 7716 --- [main] o.s.j.e.a.AnnotationMBeanExporter:在启动时为JMX曝光注册bean
2016-01-08 14:51:54.617 INFO 7716 --- [pool-2-thread-1] o.s.b.c.r.s.JobRepositoryFactoryBean:没有数据库类型集,使用元数据指示:HSQL
2016-01-08 14:51:54.744 INFO 7716 --- [main] o.s.b.a.b.JobLauncherCommandLineRunner:运行默认命令行:[]
2016-01-08 14:51:54.745 INFO 7716 --- [main] o.s.b.c.r.s.JobRepositoryFactoryBean:没有数据库类型集,使用元数据指示:HSQL
2016-01-08 14:51:54.912 INFO 7716 --- [pool-2-thread-1] o.s.b.c.l.support.SimpleJobLauncher:没有设置TaskExecutor,默认为同步执行程序。
2016-01-08 14:51:54.961 INFO 7716 --- [main] o.s.b.c.l.support.SimpleJobLauncher:没有设置TaskExecutor,默认为同步执行程序。
2016-01-08 14:51:55.044 INFO 7716 --- [pool-2-thread-1] osbclsupport.SimpleJobLauncher:Job:[SimpleJob:[name = job1]]使用以下参数启动:[ {}]
2016-01-08 14:51:55.088 INFO 7716 --- [pool-2-thread-1] o.s.batch.core.job.SimpleStepHandler:执行步骤:[step1]
2016-01-08 14:51:55.095 INFO 7716 --- [main] osbclsupport.SimpleJobLauncher:Job:[SimpleJob:[name = job1]]使用以下参数启动:[{run.id = 1 }]
2016-01-08 14:51:55.176 INFO 7716 --- [main] o.s.batch.core.job.SimpleStepHandler:执行步骤:[step1]
2016-01-08 14:51:55.245 INFO 7716 --- [main] com.example.CustomItemReader:read方法 - 收集输出文件名
2016-01-08 14:51:55.314 INFO 7716 --- [pool-2-thread-1] com.example.CustomItemReader:read方法 - 收集输出文件名
2016-01-08 14:51:55.440 INFO 7716 --- [pool-2-thread-1] com.example.CustomItemReader:read method - file found
2016-01-08 14:51:55.443 INFO 7716 --- [pool-2-thread-1] com.example.CustomItemProcessor:process method:
2016-01-08 14:51:55.461 INFO 7716 --- [main] com.example.CustomItemReader:读取方法 - 找到文件
2016-01-08 14:51:55.462 INFO 7716 --- [main] com.example.CustomItemProcessor:process method:
2016-01-08 14:51:57.088 ERROR 7716 --- [pool-2-thread-1] o.s.batch.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:Job:[SimpleJob:[name = job1]]使用以下参数完成:[ {}]及以下状态:[FAILED]
2016-01-08 14:51:57.754 INFO 7716 --- [main] com.example.CustomItemWriter:write方法:[C:\ myApp \ from \ 0000000571900000999674MHlog.txt.out]
2016-01-08 14:51:57.761 INFO 7716 --- [main] com.example.CustomItemReader:read方法 - 收集输出文件名
2016-01-08 14:51:57.762 INFO 7716 --- [main] com.example.CustomItemReader:读取方法 - 找不到文件
2016-01-08 14:51:57.783 INFO 7716 --- [main] osbclsupport.SimpleJobLauncher:Job:[SimpleJob:[name = job1]]使用以下参数完成:[{run.id = 1 }]和以下状态:[已完成]
2016-01-08 14:51:57.786 INFO 7716 --- [main] com.example.DemoApplication:在13.693秒内启动DemoApplication(JVM运行14.853)
2016-01-08 14:52:54.724 INFO 7716 --- [pool-2-thread-1] osbclsupport.SimpleJobLauncher:Job:[SimpleJob:[name = job1]]使用以下参数启动:[ {}]
2016-01-08 14:52:54.750 INFO 7716 --- [pool-2-thread-1] o.s.batch.core.job.SimpleStepHandler:执行步骤:[step1]
2016-01-08 14:52:54.755 INFO 7716 --- [pool-2-thread-1] com.example.CustomItemReader:read方法 - 收集输出文件名
2016-01-08 14:52:54.756 INFO 7716 --- [pool-2-thread-1] com.example.CustomItemReader:read方法 - 找不到文件
2016-01-08 14:52:54.775 INFO 7716 --- [pool-2-thread-1] osbclsupport.SimpleJobLauncher:Job:[SimpleJob:[name = job1]]使用以下参数完成:[ {}]和以下状态:[已完成]