Quartz 作业未参与 Spring 托管事务(Quartz + Spring 批量启动)
Quartz Job Not Participating in Spring Managed Transaction (Quartz + Spring Batch Boot)
我有几个 spring 批处理作业,如果在 Spring 批处理中触发作业执行,它们可以正常工作。这些作业将使用 JpaItemWriter 来读写数据库,其中需要事务。
我的问题是,我有配置为定期 运行 这些作业的 quartz 调度程序,我收到 "javax.persistence.TransactionRequiredException: no transaction is in progress" 错误。我知道目前石英正在实例化作业 bean 而不是 spring 本身,这使得 bean 不知道 spring 管理的正在进行的事务,如果我错了请纠正我。
不过,我尝试了很多方法,但 none 的方法都有效。以下是我当前的配置:
quartz.properties
org.quartz.scheduler.instanceName=sample_instance
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.threadCount=5
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreCMT
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.MSSQLDelegate
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.misfireThreshold=60000
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval=20000
SchedulerConfig.java
@EnableScheduling
@Configuration
public class SchedulerConfig {
@Inject
private DataSource dataSource;
@Inject
private JobsListenerService jobsListenerService;
@Bean
public JobFactory jobFactory(ApplicationContext applicationContext) {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory)
throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setJobFactory(jobFactory);
factory.setDataSource(dataSource);
factory.setQuartzProperties(quartzProperties());
factory.setGlobalJobListeners(jobsListenerService);
return factory;
}
@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
}
工作:
@Component
@DisallowConcurrentExecution
public class TestJob implements Job {
private static final String PARAMETERS = "param1=abc";
@Inject
private JobRegistry jobRegistry;
@Inject
private JobLauncher jobLauncher;
@Inject
private JobRepository jobRepository;
@Inject
private JobExplorer jobExplorer;
private JobParametersConverter jobParametersConverter = new DefaultJobParametersConverter();
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
org.springframework.batch.core.Job job = jobRegistry.getJob("Job1");
JobParameters jobParameters = JobParametersUtil.createJobParametersWithIncrementerIfAvailable(PARAMETERS, job);
jobLauncher.run(job, jobParameters).getId();
} catch (NoSuchJobException | JobParametersNotFoundException | JobParametersInvalidException | JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException e) {
e.printStackTrace();
}
}
}
我已经配置 quartz 来使用 JobStoreCMT。我是否必须显式声明一个 TransactionManager 并将其传递给 SchedulerFactoryBean?非常感谢您的帮助。
如果您遇到与我类似或相同的问题,为了节省世界各地其他人的时间,这对我有用。
我明确地为 SchedulerFactoryBean 提供了一个事务管理器。
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory, PlatformTransactionManager transactionManager)
throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setJobFactory(jobFactory);
factory.setDataSource(dataSource);
factory.setTransactionManager(transactionManager);
factory.setQuartzProperties(quartzProperties());
factory.setGlobalJobListeners(jobsListenerService);
return factory;
}
我有几个 spring 批处理作业,如果在 Spring 批处理中触发作业执行,它们可以正常工作。这些作业将使用 JpaItemWriter 来读写数据库,其中需要事务。
我的问题是,我有配置为定期 运行 这些作业的 quartz 调度程序,我收到 "javax.persistence.TransactionRequiredException: no transaction is in progress" 错误。我知道目前石英正在实例化作业 bean 而不是 spring 本身,这使得 bean 不知道 spring 管理的正在进行的事务,如果我错了请纠正我。
不过,我尝试了很多方法,但 none 的方法都有效。以下是我当前的配置:
quartz.properties
org.quartz.scheduler.instanceName=sample_instance
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.threadCount=5
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreCMT
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.MSSQLDelegate
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.misfireThreshold=60000
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval=20000
SchedulerConfig.java
@EnableScheduling
@Configuration
public class SchedulerConfig {
@Inject
private DataSource dataSource;
@Inject
private JobsListenerService jobsListenerService;
@Bean
public JobFactory jobFactory(ApplicationContext applicationContext) {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory)
throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setJobFactory(jobFactory);
factory.setDataSource(dataSource);
factory.setQuartzProperties(quartzProperties());
factory.setGlobalJobListeners(jobsListenerService);
return factory;
}
@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
}
工作:
@Component
@DisallowConcurrentExecution
public class TestJob implements Job {
private static final String PARAMETERS = "param1=abc";
@Inject
private JobRegistry jobRegistry;
@Inject
private JobLauncher jobLauncher;
@Inject
private JobRepository jobRepository;
@Inject
private JobExplorer jobExplorer;
private JobParametersConverter jobParametersConverter = new DefaultJobParametersConverter();
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
org.springframework.batch.core.Job job = jobRegistry.getJob("Job1");
JobParameters jobParameters = JobParametersUtil.createJobParametersWithIncrementerIfAvailable(PARAMETERS, job);
jobLauncher.run(job, jobParameters).getId();
} catch (NoSuchJobException | JobParametersNotFoundException | JobParametersInvalidException | JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException e) {
e.printStackTrace();
}
}
}
我已经配置 quartz 来使用 JobStoreCMT。我是否必须显式声明一个 TransactionManager 并将其传递给 SchedulerFactoryBean?非常感谢您的帮助。
如果您遇到与我类似或相同的问题,为了节省世界各地其他人的时间,这对我有用。
我明确地为 SchedulerFactoryBean 提供了一个事务管理器。
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory, PlatformTransactionManager transactionManager)
throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setJobFactory(jobFactory);
factory.setDataSource(dataSource);
factory.setTransactionManager(transactionManager);
factory.setQuartzProperties(quartzProperties());
factory.setGlobalJobListeners(jobsListenerService);
return factory;
}