Spring-batch 异常:org.springframework.batch.core.launch.NoSuchJobException:未注册名称为 [] 的作业配置

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]

Dav*_*ave 6

我只是添加了一个 JobRegistryBeanPostProcessor 并将其设置为 jobRegistry。

   @Autowired
   JobRegistry jobRegistry;

   @Bean
   public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor() {
       JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor();
       postProcessor.setJobRegistry(jobRegistry);
       return postProcessor;
   }
Run Code Online (Sandbox Code Playgroud)


Mah*_*ine 5

需要JobOperatoraJobLocator来定位要重新启动、停止等的作业。这JobLocator(通常是 a MapJobRegistry)应该填充已知作业,并且这应该手动完成或通过将JobRegistryBeanPostProcessor添加到应用程序上下文来完成。

此处的参考文档对此进行了解释:JobRegistry