NoSuchJobException when running a job programmatically in Spring Batch

Carrm picture Carrm · Mar 4, 2015 · Viewed 12.4k times · Source

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

Answer

Carrm picture Carrm · Mar 9, 2015

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.