Search code examples
spring-bootspring-batchquartz-scheduler

Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered


I know this has been asked many time but I could not find answer for I problem. I am Trying to schedule my spring batch for every 20 second but its getting fail.

QuartzConfiguration.java

@Configuration
public class QuartzConfiguration {

    @Autowired
    private JobLauncher jobLauncher;
    @Autowired
    private JobLocator jobLocator;

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

    @Bean
    public JobDetailFactoryBean jobDetailFactoryBean() {
        JobDetailFactoryBean jobfactory = new JobDetailFactoryBean();
        jobfactory.setJobClass(QuartzJobLauncher.class);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("jobName", "Test_Job");
        map.put("jobLauncher", jobLauncher);
        map.put("jobLocator", jobLocator);
        jobfactory.setJobDataAsMap(map);
        jobfactory.setGroup("group");
        jobfactory.setName("job");
        return jobfactory;
    }

    // Job is scheduled after every 20 sec
    @Bean
    public CronTriggerFactoryBean cronTriggerFactoryBean() {
        CronTriggerFactoryBean ctFactory = new CronTriggerFactoryBean();
        ctFactory.setJobDetail(jobDetailFactoryBean().getObject());
        ctFactory.setStartDelay(3000);
        ctFactory.setName("cron_trigger");
        ctFactory.setGroup("cron_group");
        ctFactory.setCronExpression("0/20 * * * * ?");
        return ctFactory;
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() {
        SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
        scheduler.setTriggers(cronTriggerFactoryBean().getObject());
        return scheduler;
    }

}

QuartzJobLauncher.java

public class QuartzJobLauncher extends QuartzJobBean {

    private static final Logger log = LoggerFactory.getLogger(QuartzJobLauncher.class);

    private String jobName;
    private JobLauncher jobLauncher;
    private JobLocator jobLocator;

    public String getJobName() {
        return jobName;
    }
    public void setJobName(String jobName) {
        this.jobName = jobName;
    }
    public JobLauncher getJobLauncher() {
        return jobLauncher;
    }
    public void setJobLauncher(JobLauncher jobLauncher) {
        this.jobLauncher = jobLauncher;
    }
    public JobLocator getJobLocator() {
        return jobLocator;
    }
    public void setJobLocator(JobLocator jobLocator) {
        this.jobLocator = jobLocator;
    }

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        try {
            Job job = jobLocator.getJob(jobName);
            JobExecution jobExecution = jobLauncher.run(job, new JobParameters());
            log.info("{}_{} was completed successfully", job.getName(), jobExecution.getId());
        } catch (Exception e) {
            log.error("Encountered job execution exception!");
        }

    }

}

BatchConfig.java

@Configuration
public class BatchConfig {

    @Autowired
    JobBuilderFactory jobBuilderFactory;

    @Autowired
    StepBuilderFactory stepBuilderFactory;

    @Bean
    public Tasklet task1()
    {
        return new Tasklet(){

            @Override
            public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
                // TODO Auto-generated method stub
                System.out.println("hello world");
                return RepeatStatus.FINISHED;
            }
        };
    }
    @Bean
    public Step step1(){

        return stepBuilderFactory.get("step1")
                .tasklet(task1())
                .build();
    }

    @Bean
    public Job job1()
    {
        return jobBuilderFactory.get("job1")
                .start(step1())
                .build();
    }


}

BatchApplication.java

@SpringBootApplication
@EnableBatchProcessing
@Import(QuartzConfiguration.class)
public class BatchApplication {

    public static void main(String[] args) {
        SpringApplication.run(BatchApplication.class, args);
    }
}

error log

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.4.RELEASE)

2017-07-11 14:35:59.370  INFO 8868 --- [           main] com.schwab.cat.BatchApplication          : Starting BatchApplication on KVMOF0487DVLBDC with PID 8868 (started by pankaj.k.singh in C:\Users\pankaj.k.singh\Desktop\batch\sample hello world)
2017-07-11 14:35:59.377  INFO 8868 --- [           main] com.schwab.cat.BatchApplication          : No active profile set, falling back to default profiles: default
2017-07-11 14:35:59.511  INFO 8868 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@221af3c0: startup date [Tue Jul 11 14:35:59 IST 2017]; root of context hierarchy
2017-07-11 14:36:00.992  WARN 8868 --- [           main] o.s.c.a.ConfigurationClassEnhancer       : @Bean method ScopeConfiguration.stepScope is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
2017-07-11 14:36:01.013  WARN 8868 --- [           main] o.s.c.a.ConfigurationClassEnhancer       : @Bean method ScopeConfiguration.jobScope is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
2017-07-11 14:36:01.230  INFO 8868 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Tomcat' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Tomcat] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-07-11 14:36:01.253  INFO 8868 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$1bb5301] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-07-11 14:36:01.435  INFO 8868 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-07-11 14:36:01.632  INFO 8868 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'dataSource' of type [org.apache.tomcat.jdbc.pool.DataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-07-11 14:36:01.641  INFO 8868 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$$EnhancerBySpringCGLIB$$e3aef661] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-07-11 14:36:01.672  INFO 8868 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'dataSourceInitializer' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-07-11 14:36:01.679  INFO 8868 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration' of type [org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$$EnhancerBySpringCGLIB$$17e2d67] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-07-11 14:36:01.718  INFO 8868 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jobLauncher' of type [com.sun.proxy.$Proxy41] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-07-11 14:36:01.732  INFO 8868 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jobRegistry' of type [com.sun.proxy.$Proxy43] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-07-11 14:36:01.733  INFO 8868 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'com.quantvalley.batch.quartz.QuartzConfiguration' of type [com.quantvalley.batch.quartz.QuartzConfiguration$$EnhancerBySpringCGLIB$$88291ebb] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-07-11 14:36:03.256  INFO 8868 --- [           main] o.s.b.c.r.s.JobRepositoryFactoryBean     : No database type set, using meta data indicating: HSQL
2017-07-11 14:36:03.606  INFO 8868 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : No TaskExecutor has been set, defaulting to synchronous executor.
2017-07-11 14:36:03.912  INFO 8868 --- [           main] org.quartz.impl.StdSchedulerFactory      : Using default implementation for ThreadExecutor
2017-07-11 14:36:03.980  INFO 8868 --- [           main] org.quartz.core.SchedulerSignalerImpl    : Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2017-07-11 14:36:03.984  INFO 8868 --- [           main] org.quartz.core.QuartzScheduler          : Quartz Scheduler v.2.2.3 created.
2017-07-11 14:36:03.987  INFO 8868 --- [           main] org.quartz.simpl.RAMJobStore             : RAMJobStore initialized.
2017-07-11 14:36:03.991  INFO 8868 --- [           main] org.quartz.core.QuartzScheduler          : Scheduler meta-data: Quartz Scheduler (v2.2.3) 'schedulerFactoryBean' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

2017-07-11 14:36:03.993  INFO 8868 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler 'schedulerFactoryBean' initialized from an externally provided properties instance.
2017-07-11 14:36:03.993  INFO 8868 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler version: 2.2.3
2017-07-11 14:36:03.998  INFO 8868 --- [           main] org.quartz.core.QuartzScheduler          : JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@20312893
2017-07-11 14:36:04.335  INFO 8868 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from class path resource [org/springframework/batch/core/schema-hsqldb.sql]
2017-07-11 14:36:04.366  INFO 8868 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from class path resource [org/springframework/batch/core/schema-hsqldb.sql] in 25 ms.
2017-07-11 14:36:04.733  INFO 8868 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-07-11 14:36:04.748  INFO 8868 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147483647
2017-07-11 14:36:04.749  INFO 8868 --- [           main] o.s.s.quartz.SchedulerFactoryBean        : Starting Quartz Scheduler now
2017-07-11 14:36:04.750  INFO 8868 --- [           main] org.quartz.core.QuartzScheduler          : Scheduler schedulerFactoryBean_$_NON_CLUSTERED started.
2017-07-11 14:36:04.773  INFO 8868 --- [           main] com.schwab.cat.BatchApplication          : Started BatchApplication in 6.481 seconds (JVM running for 11.417)
2017-07-11 14:36:20.039 ERROR 8868 --- [ryBean_Worker-1] c.q.batch.quartz.QuartzJobLauncher       : Encountered job execution exception!
2017-07-11 14:36:40.006 ERROR 8868 --- [ryBean_Worker-2] c.q.batch.quartz.QuartzJobLauncher       : Encountered job execution exception!
2017-07-11 14:37:00.001 ERROR 8868 --- [ryBean_Worker-3] c.q.batch.quartz.QuartzJobLauncher       : Encountered job execution exception!
2017-07-11 14:37:20.002 ERROR 8868 --- [ryBean_Worker-4] c.q.batch.quartz.QuartzJobLauncher       : Encountered job execution exception!
2017-07-11 14:37:40.002 ERROR 8868 --- [ryBean_Worker-5] c.q.batch.quartz.QuartzJobLauncher       : Encountered job execution exception!
2017-07-11 14:38:00.002 ERROR 8868 --- [ryBean_Worker-6] c.q.batch.quartz.QuartzJobLauncher       : Encountered job execution exception!

Please someone look into it and let me know the problem.


Solution

  • You swallowed the exception in your try/catch and instead, you logged only the fact that exception occurrent, but not what kind of exception it was. If you change logging statement to this:

    log.error("Encountered job execution exception!", e);
    

    You'll see that the error says:

    org.springframework.batch.core.launch.NoSuchJobException: No job configuration with the name [Test_Job] was registered

    You have declared a job with name job1, not Test_Job so that's why you're getting the exception. You have to change job data map to:

    map.put("jobName", "job1");
    

    This will remove the exception, but your job will still run once as Spring Batch requires unique job parameters to restart it, see this answer for explanation. So because of that, you have to modify your job execution to something like this (the simplest) to be able to run it continually:

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        try {
            Job job = jobLocator.getJob(jobName);
            Map<String, JobParameter> parametersMap = new HashMap<>();
            parametersMap.put("timestamp", new JobParameter(System.currentTimeMillis()));
            JobParameters jobParameters = new JobParameters(parametersMap);
            JobExecution jobExecution = jobLauncher.run(job, jobParameters);
            log.info("{}_{} was completed successfully", job.getName(), jobExecution.getId());
        } catch (Exception e) {
            log.error("Encountered job execution exception!", e);
        }
    }