Dav*_*ave 5 jobs restart spring-batch
当使用 jobOperator.stop(id) 停止正在运行的作业或想使用 jobOperator.restart(id) 重新启动它时,我看到此异常。我不知道为什么 MapJobRegistry 是空的......我错过了一个步骤吗?我使用https://github.com/spring-guides/gs-batch-processing.git
中的完整示例重现了该问题
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
// end::setup[]
@Autowired
JobRepository jobRepository;
// tag::readerwriterprocessor[]
@Bean
public FlatFileItemReader<Person> reader() {
return new FlatFileItemReaderBuilder<Person>()
.name("personItemReader")
.resource(new ClassPathResource("sample-data.csv"))
.delimited()
.names(new String[]{"firstName", "lastName"})
.fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
setTargetType(Person.class);
}})
.build();
}
@Bean
public PersonItemProcessor processor() {
return new PersonItemProcessor();
}
@Bean
public JdbcBatchItemWriter<Person> writer(DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<Person>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)")
.dataSource(dataSource)
.build();
}
// end::readerwriterprocessor[]
// tag::jobstep[]
@Bean
public Job importUserJob(JobCompletionNotificationListener listener, Step step1) {
return jobBuilderFactory.get("importUserJob")
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(step1)
.end()
.build();
}
@Bean
public Step step1(JdbcBatchItemWriter<Person> writer) {
return stepBuilderFactory.get("step1")
.<Person, Person> chunk(10)
.reader(reader())
.processor(processor())
.writer(writer)
.build();
}
// end::jobstep[]
@Bean
public JobLauncher simpleJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
}
Run Code Online (Sandbox Code Playgroud)
其余控制器
@RestController
public class BatchController {
Logger logger = LoggerFactory.getLogger(BatchController.class);
@Autowired
JobLauncher simpleJobLauncher;
@Autowired
Job importUserJob;
@Autowired
JobOperator jobOperator;
@RequestMapping("/startNewJob")
public String handle() {
try {
JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
.toJobParameters();
JobExecution jobExecution = simpleJobLauncher.run(importUserJob, jobParameters);
return jobExecution.toString();
} catch (Exception e) {
logger.info(e.getMessage());
return ("An error has occured, please check the logs");
}
}
@RequestMapping("/stopJob/{id}")
public Boolean stopJob(@PathVariable Long id) throws Exception {
logger.info("stopJob "+id);
return jobOperator.stop(id);
}
@RequestMapping("/restartJob/{id}")
public Long restartJob(@PathVariable Long id) throws Exception {
logger.info("restartJob "+id);
return jobOperator.restart(id);
}
}
Run Code Online (Sandbox Code Playgroud)
重新启动作业时的堆栈跟踪
2020-11-12 21:47:16.452 ERROR 26252 --- [nio-8080-exec-3] oaccC[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [ DispatcherServlet] 在路径 [] 的上下文中抛出异常 [请求处理失败;嵌套异常是org.springframework.batch.core.launch.NoSuchJobException:没有名称为[importUserJob]的作业配置已注册],其根本原因
org.springframework.batch.core.launch.NoSuchJobException:在 org.springframework.batch.core.configuration.support.MapJobRegistry.getJob(MapJobRegistry.java:68) ~[spring- batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE] 在 sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法) ~[na:1.8.0_92] 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java :62)〜[na:1.8.0_92]在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)〜[na:1.8.0_92]在java.lang.reflect.Method.invoke(Method.java:498) )〜[na:1.8.0_92]在org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)〜[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]在组织.springframework.aop.framework.ReflectiveMethodInspiration.invokeJoinpoint(ReflectiveMethodInitation.java:198)~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]在org.springframework.aop.framework.ReflectiveMethodInitation.proceed( ReflectiveMethodIncation.java:163) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE] 在 org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127 )~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE] 在 org.springframework.aop.framework.ReflectiveMethodInitation.proceed(ReflectiveMethodInitation.java:186)~[spring-aop-5.2。 2.RELEASE.jar:5.2.2.RELEASE] 在 org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE ] 在 com.sun.proxy.$Proxy68.getJob(未知来源) ~[na:na] 在 org.springframework.batch.core.launch.support.SimpleJobOperator.restart(SimpleJobOperator.java:275) ~[spring-batch -core-4.2.1.RELEASE.jar:4.2.1.RELEASE] 在 org.springframework.batch.core.launch.support.SimpleJobOperator$$FastClassBySpringCGLIB$$44ee6049.invoke() ~[spring-batch-core-4.2 .1.RELEASE.jar:4.2.1.RELEASE] 在 org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.2.RELEASE.jar:5.2.2。发布] 在 org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE] 在 org.springframework.batch。 core.launch.support.SimpleJobOperator$$EnhancerBySpringCGLIB$$853e8727.restart() ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE] 在 com.example.batchprocessing.BatchController.restartJob( BatchController.java:60) ~[classes/:na] 在 sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法) ~[na:1.8.0_92] 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[ na:1.8.0_92] 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_92] 在 java.lang.reflect.Method.invoke(Method.java:498) ~[na: 1.8.0_92] 在 org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE] 在 org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE] 在 org.springframework.web.servlet.mvc.method .annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE] 位于 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter。 invokeHandlerMethod(RequestMappingHandlerAdapter.java:888) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE] 在 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java :793)〜[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]在org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)〜[spring- webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE] 在 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2 .2.RELEASE] 在 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE] 在 org.springframework.web .servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE] 在 org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:第898章)~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
我只是添加了一个 JobRegistryBeanPostProcessor 并将其设置为 jobRegistry。
@Autowired
JobRegistry jobRegistry;
@Bean
public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor() {
JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor();
postProcessor.setJobRegistry(jobRegistry);
return postProcessor;
}
Run Code Online (Sandbox Code Playgroud)
需要JobOperatoraJobLocator来定位要重新启动、停止等的作业。这JobLocator(通常是 a MapJobRegistry)应该填充已知作业,并且这应该手动完成或通过将JobRegistryBeanPostProcessor添加到应用程序上下文来完成。
此处的参考文档对此进行了解释:JobRegistry。