NoSuchJobException when running a job programmatically in Spring Batch

别说谁变了你拦得住时间么 提交于 2020-04-08 11:35:19

问题


I have a Job running on startup. I want to run this job programmatically at a particular point of my application, not when I start my app.

When running on startup I have no problem, but I got a "NoSuchJobException" (No job configuration with the name [importCityFileJob] was registered) when I try to run it programmatically.

After looking on the web, I think it's a problem related to JobRegistry, but I don't know how to solve it.

Note : my whole batch configuration is set programmatically, I don't use any XML file to configure my batch and my job. That's a big part of my problem while I lack the examples...

Here is my code to run the Job :

public String runBatch() {
    try {
        JobLauncher launcher = new SimpleJobLauncher();
        JobLocator locator = new MapJobRegistry();
        Job job = locator.getJob("importCityFileJob");
        JobParameters jobParameters = new JobParameters(); // ... ?
        launcher.run(job, jobParameters);
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("Something went wrong");
    }
    return "Job is running";
}

My Job declaration :

@Bean
public Job importCityFileJob(JobBuilderFactory jobs, Step step) {
    return jobs.get("importFileJob").incrementer(new RunIdIncrementer()).flow(step).end().build();
}

(I tried to replace importCityFileJob by importFileJob in my runBatch method, but it didn't work)

My BatchConfiguration file contains the job declaration above, a step declaration, the itemReader/itemWriter/itemProcessor, and that's all. I use the @EnableBatchProcessing annotation.

I'm new to Spring Batch & I'm stuck on this problem. Any help would be welcome.

Thanks


Edit : I've solved my problem. I wrote my solution in the answers


回答1:


A JobRegistry won't populate itself. In your example, you're creating a new instance, then trying to get the job from it without having registered it in the first place. Typically, the JobRegistry is configured as a bean along with an AutomaticJobRegistrar that will load all jobs into the registrar on startup. That doesn't mean they will be executed, just registered so they can be located later.

If you're using Java configuration, this should happen automatically using the @EnableBatchProcessing annotation. With that annotation, you'd just inject the provided JobRegistry and the jobs should already be there.

You can read more about the @EnableBatchProcessing in the documentation here: http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.html

You can also read about the AutomaticJobRegistrar in the documentation here: http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/configuration/support/AutomaticJobRegistrar.html




回答2:


Here is what I had to do to fix my problem:

Add the following Bean to the BatchConfiguration :

@Bean
public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) {
    JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor = new JobRegistryBeanPostProcessor();
    jobRegistryBeanPostProcessor.setJobRegistry(jobRegistry);
    return jobRegistryBeanPostProcessor;
}

Replace the JobLocator by an @Autowired JobRegistry, and use the @Autowired JobLauncher instead of creating one. My run method now have the following code :

@Autowired
private JobRegistry jobRegistry;

@Autowired
private JobLauncher launcher;

public String runBatch() {
    try {
        Job job = jobRegistry.getJob("importCityFileJob");
        JobParameters jobParameters = new JobParameters();
        launcher.run(job, jobParameters);
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("Something went wrong");
    }
    return "OK";
}

I hope it will help someone.




回答3:


I could not find the correct answer on this page. In my case the spring batch jobs were configured in a different configuration class not annotated with @EnableBatchProcessing. In that case you need to add the Job to the JobRegistry:

import org.springframework.batch.core.Job;
import org.springframework.batch.core.configuration.DuplicateJobException;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.support.ReferenceJobFactory;
import org.springframework.batch.core.job.flow.Flow;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatchJobConfigurations {

    @Bean
    public Job myCountBatchJob(final JobBuilderFactory jobFactory, final JobRegistry jobRegistry, final Flow myJobFlow)
        throws DuplicateJobException {
      final Job countJob = jobFactory.get("myCountBatchJob")
            .start(myJobFlow)
            .end().build();
      ReferenceJobFactory referenceJobFactory = new ReferenceJobFactory(countJob);
      jobRegistry.register(referenceJobFactory);
      return countJob;
    }

}



回答4:


Adding the following bean in the applicationContext.xml resolved the problem for me

<bean class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
    <property name="jobRegistry" ref="jobRegistry" />
</bean>

I also have this entry in the applicationContext.xml

<bean id="jobRegistry"
    class="org.springframework.batch.core.configuration.support.MapJobRegistry" />



回答5:


another solution:

rename the method name "importCityFileJob" to "job":

@Bean
public Job job(JobBuilderFactory jobs, Step step) {
    return jobs.get("importFileJob").incrementer(new RunIdIncrementer()).flow(step).end().build();
}



回答6:


@EnableBatchProcessing
@Configuration
public class SpringBatchCommon {

  @Bean
  public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) {
    JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor();
    postProcessor.setJobRegistry(jobRegistry);
    return postProcessor;
  }
}

Set the JobRegistry in the JobRegistryBeanPostProcessor , after that you can autowire the JobLauncher and the JobLocator

     Job job = jobLocator.getJob("importFileJob");
     JobParametersBuilder jobBuilder = new JobParametersBuilder();
     //set any parameters if required
     jobLauncher.run(job, jobBuilder.toJobParameters()


来源:https://stackoverflow.com/questions/28850051/nosuchjobexception-when-running-a-job-programmatically-in-spring-batch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!