0

我创建了一个基于 Spring Batch 的应用程序,它基本上有一个自定义 itemreader 用于读取文件夹以搜索候选文件,一个自定义 itemprocessor 用于读取文件并将其转换为不同的文件,以及一个自定义 itemwriter 以删除文件。在我添加调度程序之前,它按预期工作,没有错误。添加调度程序后,我将错误粘贴在问题主题中。我发现了一些具有相似问题但背景非常不同的问题。必须奇怪的一点是,事实上,即使我在控制台上看到这样的错误,它也能正常工作。我的意思是,读取文件夹(itemreader),转换文件(itemprocessor)并删除输入文件(itemwriter)。我很困扰。如果我可以在没有调度程序的情况下重现错误,然后我可以专注于某个节点,或者在我引入调度程序后我没有得到结果,所以我可以专注于调度程序配置中的一些可能的错误,但两者都不是这样。任何建议将不胜感激。

下一段是在 1 月 10 日添加的:

经过深入调查,我发现这种错误只发生一次,而且只发生在主线程中。我的意思是,如果我在开始申请时有一个候选文件,那么我会得到 WRONG_DOCUMENT_ERR。比方说,我启动我的应用程序时没有可供 CustomItemReader 找到的文件,等到主线程完成,然后我放置一个可供 CustomItemReader 找到的候选文件,根本不会有错误。换句话说,当 CustomItemReader 被 pool-2-thread-1 触发并找到一个文件时,它可以正常工作。另一方面,当主线程触发 CustomItemReader 并找到一个文件时,这仅在应用程序启动期间发生,它会导致问题。通过使用 JConsole,我可以检查主线程是否已消失,并且 pool-2-thread-1 是否已启动并正在运行。然后,我将我的文件添加到输入文件夹中,这会导致 CustomItemReader 返回一个字符串而不是 null 并且不会出现错误。当然,我错过了一些关于一起使用 Spring Scheduler 和 Spring Batch 的概念。显然,我希望我的应用程序在我启动它时不会引发任何错误,并且它很快就会找到它初始化的文件。为什么它只发生在主线程中,但如果我把 Spring Scheduler 拿出来,它会按预期工作一次?我错过了一些同步参数吗?为什么它只发生在主线程中,但如果我把 Spring Scheduler 拿出来,它会按预期工作一次?我错过了一些同步参数吗?为什么它只发生在主线程中,但如果我把 Spring Scheduler 拿出来,它会按预期工作一次?我错过了一些同步参数吗?

下一段是在 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] oscaConfigurationClassEnhancer:@Bean 方法 ScopeConfiguration.stepScope 是非静态的,并返回一个可分配给 Spring 的 BeanFactoryPostProcessor 接口的对象。这将导致无法处理方法的声明@Configuration 类中的@Autowired、@Resource 和@PostConstruct 等注解。将“静态”修饰符添加到此方法以避免这些容器生命周期问题;有关完整的详细信息,请参阅@Bean javadoc。

2016-01-08 14:51:51.030 WARN 7716 --- [main] oscaConfigurationClassEnhancer:@Bean 方法 ScopeConfiguration.jobScope 是非静态的,并返回一个可分配给 Spring 的 BeanFactoryPostProcessor 接口的对象。这将导致无法处理方法的声明@Configuration 类中的@Autowired、@Resource 和@PostConstruct 等注解。将“静态”修饰符添加到此方法以避免这些容器生命周期问题;有关完整的详细信息,请参阅@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 --- [main] osbclAbstractListenerFactoryBean:org.springframework.batch.item.ItemReader 是一个接口。不会查询实现类以获取基于注释的侦听器配置。如果在 @Bean 方法上使用 @StepScope,请务必返回实现类,以便可以使用侦听器注释。

2016-01-08 14:51:53.572 INFO 7716 --- [main] osjdbc.datasource.init.ScriptUtils:从类路径资源 [org/springframework/batch/core/schema-hsqldb.sql] 执行 SQL 脚本

2016-01-08 14:51:53.667 INFO 7716 --- [main] osjdbc.datasource.init.ScriptUtils:从 94 中的类路径资源 [org/springframework/batch/core/schema-hsqldb.sql] 执行 SQL 脚本小姐。

2016-01-08 14:51:54.506 INFO 7716 --- [main] 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:未设置任务执行器,默认为同步执行器。

2016-01-08 14:51:54.961 INFO 7716 --- [main] osbclsupport.SimpleJobLauncher:未设置任务执行器,默认为同步执行器。

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 --- [main] 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 --- [main] com.example.CustomItemReader:读取方法 - 找到文件

2016-01-08 14:51:55.462 INFO 7716 --- [main] com.example.CustomItemProcessor:处理方法:

2016-01-08 14:51:57.088 错误 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]] 使用以下参数完成:[{}] 和以下状态:[失败]

2016-01-08 14:51:57.754 INFO 7716 --- [main] com.example.CustomItemWriter:写入方法:[C:\myApp\from\0000000571900000999674MHlog.txt.out]

2016-01-08 14:51:57.761 INFO 7716 --- [main] com.example.CustomItemReader:读取方法 - 收集输出文件名

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:作业:[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:作业:[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]] 使用以下参数完成:[{}] 和以下状态:[已完成]

4

0 回答 0