How can I call beans in spring mvc controller method . - java

I have the QuartzConfig configuration class that have three beans ,How can I call this beans in spring mvc controller method.
This beans executed automatically once I start application,But I don't want that I want to execute this beans by controller
Quartz configuration class
#Configuration
public class QuartzConfig {
#Autowired
private PlatformTransactionManager transactionManager;
#Autowired
private ApplicationContext applicationContext;
#Bean
public SchedulerFactoryBean quartzScheduler() {
SchedulerFactoryBean quartzScheduler = new SchedulerFactoryBean();
quartzScheduler.setTransactionManager(transactionManager);
quartzScheduler.setOverwriteExistingJobs(true);
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
quartzScheduler.setJobFactory(jobFactory);
Trigger[] triggers = {
processMyJobTrigger().getObject()
};
quartzScheduler.setTriggers(triggers);
return quartzScheduler;
}
#Bean
public JobDetailFactoryBean processMyJob() {
JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
jobDetailFactory.setJobClass(HelloJob.class);
jobDetailFactory.setDurability(true);
return jobDetailFactory;
}
#Bean
public CronTriggerFactoryBean processMyJobTrigger() {
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
cronTriggerFactoryBean.setJobDetail(processMyJob().getObject());
cronTriggerFactoryBean.setCronExpression("0 0/1 * * * ?");
return cronTriggerFactoryBean;
}
}
Quartz job
#Service
#Transactional
public class HelloJob implements Job{
#Inject
TestrecordRepository testrecordRepository;
#Inject
ScoreRepository scoreRepository;
public void execute(JobExecutionContext context)
throws JobExecutionException {
System.out.println("Hello Quartz!");
List<Testrecord> records=testrecordRepository.findAll();
for(Testrecord t:records){
Testrecord testrecord = new Testrecord();
testrecord.setValue_integer(t.getValue_integer());
testrecord.setId(t.getId());
RuleExecutor ruleExecutor = new RuleExecutor();
Score score= ruleExecutor.processRules(testrecord);
scoreRepository.save(score);
}
}
}

Related

How to schedule the Quartz cron jobs on spring boot app startup?

I am integrating Quartz with Spring boot and postgres.
I have created all the required tables for quartz.
Issue : The application starts but the Job is not getting executed as per the cron.
I want that the jobs should be automatically scheduled on start-up and should run as per the cron expression.
But right now the application starts and no trigger is fired.
The QuartzJobFactory class
public class QuartzJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
private transient AutowireCapableBeanFactory beanFactory;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
beanFactory = applicationContext.getAutowireCapableBeanFactory();
}
#Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
beanFactory.autowireBean(job);
return job;
}
}
The ConfigQuartz class
#Configuration
public class ConfigQuartz {
#Value("${quartz.dataSource.myDS.URL}")
String orgQuartzDatasourceMydsUrl;
#Value("${spring.datasource.username}")
String orgQuartzDatasourceMydsUser;
#Value("${spring.datasource.password}")
String orgQuartzDatasourceMydsPassword;
#Value("${quartz.enabled}")
Boolean isQuartzEnabled;
private static List<Trigger> triggers = new ArrayList<>();
#Bean
public JobFactory jobFactory(ApplicationContext applicationContext) {
QuartzJobFactory sampleJobFactory = new QuartzJobFactory();
sampleJobFactory.setApplicationContext(applicationContext);
return sampleJobFactory;
}
#Bean
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource, JobFactory jobFactory)
throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setOverwriteExistingJobs(true);
factory.setAutoStartup(isQuartzEnabled);
// factory.setDataSource(dataSource);
factory.setJobFactory(jobFactory);
factory.setQuartzProperties(quartzProperties());
factory.setTriggers(triggers.toArray(new Trigger[triggers.size()]));
return factory;
}
public Properties setQuartzProperties() {
Properties properties = new Properties();
properties.setProperty("org.quartz.dataSource.myDS.URL",orgQuartzDatasourceMydsUrl);
properties.setProperty("org.quartz.dataSource.myDS.user",orgQuartzDatasourceMydsUser);
properties.setProperty("org.quartz.dataSource.myDS.password",orgQuartzDatasourceMydsPassword);
return properties;
}
#Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("quartz.properties"));
propertiesFactoryBean.setProperties(setQuartzProperties());
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
public static SimpleTriggerFactoryBean createTrigger(JobDetail jobDetail, long pollFrequencyMs,
String triggerName) {
SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
factoryBean.setJobDetail(jobDetail);
factoryBean.setStartDelay(0L);
factoryBean.setRepeatInterval(pollFrequencyMs);
factoryBean.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
factoryBean.setName(triggerName);
// in case of misfire, ignore all missed triggers and continue :
factoryBean.setMisfireInstruction(
SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT);
return factoryBean;
}
// Use this method for creating cron triggers instead of simple triggers:
public static CronTriggerFactoryBean createCronTrigger(JobDetail jobDetail, String cronExpression,
String triggerName) throws Exception {
CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();
factoryBean.setJobDetail(jobDetail);
factoryBean.setCronExpression(cronExpression);
factoryBean.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW);
factoryBean.setName(triggerName);
try {
factoryBean.afterPropertiesSet();
} catch (ParseException e) {
throw new Exception(e.getMessage());
}
triggers.add(factoryBean.getObject());
return factoryBean;
}
public static JobDetailFactoryBean createJobDetail(Class jobClass) {
JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
factoryBean.setJobClass(jobClass);
// job has to be durable to be stored in DB:
factoryBean.setDurability(true);
return factoryBean;
}
}
The QuartzJobFactory class
public class QuartzJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
private transient AutowireCapableBeanFactory beanFactory;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
beanFactory = applicationContext.getAutowireCapableBeanFactory();
}
#Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
beanFactory.autowireBean(job);
return job;
}
}
The CronExpression class
public class CronExpression {
private static final Map<String, String> cronExpressionMap = ImmutableMap
.<String, String>builder()
.put(TestJob.CLASS_NAME, "* 0 0 ? * * *")
.build();
public static String get(String key) {
return cronExpressionMap.get(key);
}
}
The TestJob class
#Component
#DisallowConcurrentExecution
public class TestJob implements Job {
public static final String CLASS_NAME = "TestJob";
private final String JOB_BEAN_NAME = CLASS_NAME + AppConstants.QUARTZ_JOB_SUFFIX;
private final String TRIGGER_BEAN_NAME = CLASS_NAME + AppConstants.QUARTZ_TRIGGER_SUFFIX;
#Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
LocalDateTime start = LocalDateTime.now();
System.out.println("*************** execute method is running *******");
}
#Bean(name = JOB_BEAN_NAME)
public JobDetailFactoryBean sampleJob() {
return ConfigQuartz.createJobDetail(this.getClass());
}
#Bean(name = TRIGGER_BEAN_NAME)
public CronTriggerFactoryBean sampleJobTrigger(
#Qualifier(JOB_BEAN_NAME) JobDetailFactoryBean jobDetail) throws Exception {
return ConfigQuartz.createCronTrigger(jobDetail.getObject(), CronExpression.get(CLASS_NAME),
CLASS_NAME);
}
}
The main class
EnableConfigurationProperties
#EntityScan(basePackages = {"com.example"})
#ComponentScan({"com.example"})
#SpringBootApplication
#EnableScheduling
public class QuartzSchedulerApplication {
public static void main(String[] args) {
SpringApplication.run(QuartzSchedulerApplication.class, args);
}
}
application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/quartz
spring.datasource.username=postgres
spring.datasource.password=mysecretpassword
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
spring.jpa.show-sql=true
spring.jpa.database=POSTGRESQL
spring.datasource.platform=postgres
spring.datasource.driverClassName=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=none
spring.datasource.hikari.maximum-pool-size=5
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false
quartz.dataSource.myDS.URL=jdbc:postgresql://localhost:5432/quartz
quartz.enabled=true
The quartz.properties
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName = PropScheduler
org.quartz.scheduler.instanceId = 10
#org.quartz.scheduler.instanceId = AUTO
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource=myDS
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 5000
org.quartz.scheduler.name=test-schedulers
#============================================================================
# Configure Datasources
#============================================================================
org.quartz.dataSource.myDS.driver=org.postgresql.Driver
org.quartz.dataSource.myDS.maxConnections = 5
org.quartz.dataSource.myDS.validationQuery = select 1
#============================================================================
# Configure trigger history loging , enble if needed more information regaring triggers
#============================================================================
#org.quartz.plugin.triggerHistory.class=org.quartz.plugins.history.LoggingTriggerHistoryPlugin
#org.quartz.plugin.triggerHistory.triggerFiredMessage=Trigger [{1}.{0}] fired job [{6}.{5}] scheduled at: {2, date, dd-MM-yyyy HH:mm:ss.SSS}, next scheduled at: {3, date, dd-MM-yyyy HH:mm:ss.SSS}
#org.quartz.plugin.triggerHistory.triggerCompleteMessage=Trigger [{1}.{0}] completed firing job [{6}.{5}] with resulting trigger instruction code: {9}. Next scheduled at: {3, date, dd-MM-yyyy HH:mm:ss.SSS}
#org.quartz.plugin.triggerHistory.triggerMisfiredMessage=Trigger [{1}.{0}] misfired job [{6}.{5}]. Should have fired at: {3, date, dd-MM-yyyy HH:mm:ss.SSS}
Your TriggerListener class (SimpleTriggerFactoryBean) doesn't seem to be implementing TriggerListener interface of quartz.
You can create custom class which implements TriggerListener and see if that works.
Reference

Start Spring Batch job in Async method throws lazy exception

I need to start spring batch job in Async method, but I got lazy exception in item processor:
This is my Approach:
Service that contains Async method looks like:
#Service
#RequiredArgsConstructor
#Slf4j
public class BatchService {
#Qualifier(value = "attachmentsJob")
private final Job job;
#Qualifier(value = "asyncJobLauncher")
private final JobLauncher jobLauncher;
private final JobLogService jobLogService;
#Async
public void migrateAttachments() {
JobLogDB jobLogDB = jobLogService.createStartJobLog(job);
try {
Map<String, JobParameter> parameters = new HashMap<>();
parameters.put("jobId", new JobParameter(jobLogDB.getId()));
jobLauncher.run(job, new JobParameters(parameters));
} catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException | JobParametersInvalidException e) {
e.printStackTrace();
jobLogService.markJobAsFailed(jobLogDB.getId());
}
}
}
The Batch Config is:
#Configuration
#RequiredArgsConstructor
#EnableBatchProcessing
public class BatchConfig {
private final JobBuilderFactory jobBuilderFactory;
private final JobRepository jobRepository;
private final StepBuilderFactory stepBuilderFactory;
private final MessageRepository messageRepository;
private final PlatformTransactionManager platformTransactionManager;
private final MessageDbAttachmentsProcessor messageDbAttachmentsProcessor;
#Bean(name = "asyncBatchTaskExecutor")
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(64);
executor.setMaxPoolSize(64);
executor.setQueueCapacity(64);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setThreadNamePrefix("MigrateAttachmentsThread-");
executor.initialize();
return executor;
}
/**
* Batch Reader
*/
#Bean
public RepositoryItemReader<MessageDB> reader() {
return new RepositoryItemReaderBuilder<MessageDB>().name("readerName")
.repository(messageRepository)
.methodName("findAllByTaskIdIsNotNull")
.pageSize(10)
.sorts(Collections.singletonMap("taskId", Sort.Direction.ASC))
.build();
}
/**
* Batch Processor
*/
#Bean
public AsyncItemProcessor<MessageDB, MessageDB> processor() {
AsyncItemProcessor<MessageDB, MessageDB> asyncItemProcessor = new AsyncItemProcessor<>();
asyncItemProcessor.setDelegate(messageDbAttachmentsProcessor);
asyncItemProcessor.setTaskExecutor(taskExecutor());
return asyncItemProcessor;
}
/**
* Batch Writer
*/
#Bean
public RepositoryItemWriter<MessageDB> writer() {
RepositoryItemWriter repositoryItemWriter = new RepositoryItemWriter();
repositoryItemWriter.setRepository(messageRepository);
repositoryItemWriter.setMethodName("save");
return repositoryItemWriter;
}
#Bean
public AsyncItemWriter<MessageDB> asyncWriter() {
AsyncItemWriter<MessageDB> asyncItemWriter = new AsyncItemWriter<>();
asyncItemWriter.setDelegate(writer());
return asyncItemWriter;
}
#Bean(name = "attachmentsJob")
public Job migrateTaskAttachmentsJob(JobCompletionNotificationListener listener, Step step) {
return jobBuilderFactory.get("taskAttachmentsJob")
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(step)
.end()
.build();
}
#Bean
public Step step() {
return stepBuilderFactory.get("step")
.<MessageDB, Future<MessageDB>>chunk(5)
.reader(reader())
.processor(processor())
.writer(asyncWriter())
.transactionManager(platformTransactionManager)
.build();
}
#Bean(name = "asyncJobLauncher")
public JobLauncher asyncJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor(taskExecutor());
return jobLauncher;
}
}
When I call the method in the MessageDbAttachmentsProcessor I get lazy exception:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: xxx.xxx.xxx.xxx, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
at org.hibernate.collection.internal.AbstractPersistentCollection.write(AbstractPersistentCollection.java:409)
at org.hibernate.collection.internal.PersistentBag.add(PersistentBag.java:407)
I tried to fix it by adding #Transactional(propagation = Propagation.REQUIRES_NEW) on migrateAttachments method but without success, after I added I got following exception:
java.lang.IllegalStateException: Existing transaction detected in JobRepository. Please fix this and try again (e.g. remove #Transactional annotations from client).
I do not know what to change and in which direction to modify. Any help is welcomed.

How can I use Scheduler in multiple service?

I've tried the following methods to use the scheduler, but I can't find an answer, so I'd like to ask you a question.
The scheduler service is running exactly on time.
However, only 'sessionService.getUserInfo()' runs.
We are not doing any work on youtubeSearchService.searchYoutube and youtubeSearchService.searchYoutube.
Why there's only work one service. I wonder what to do to use multiple services.
#Component
public class SchedulerService {
private static final Logger logger = LoggerFactory.getLogger(SchedulerService.class);
#Autowired
private YoutubeSearchService youtubeSearchService;
#Autowired
private WeatherService weatherService;
#Autowired
private SessionService sessionService;
public static int i = 0;
public static int j = 0;
#Scheduled(cron="0 40 0/1 * * *")
public void weatherSchedulerService() throws Exception {
++i;
weatherService.insertRTweather(sessionService.getUserInfo());
}
#Scheduled(cron = "0 0/1 * * * *")
public void youtubeSearchSchedulerService() throws Exception {
++j;
youtubeSearchService.searchYoutube(sessionService.getUserInfo(),j);
}
}
I used to have challenges with spring scheduler, especially with annotation based config and finally use following solution I hope it helps:
SchedulerConfig.java using quartz
#Configuration
public class SchedulerConfig
{
private static final Logger logger = Logger.getLogger(SchedulerConfig.class.getName());
#Autowired
private ApplicationContext applicationContext;
#Bean
public SpringBeanJobFactory springBeanJobFactory()
{
AutoWiringSpringBeanJobFactory jobFactory = new AutoWiringSpringBeanJobFactory();
logger.info("Configuring Job factory");
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
#Bean
public SchedulerFactoryBean scheduler(Trigger trigger, JobDetail job)
{
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setConfigLocation(new ClassPathResource("quartz.properties"));
logger.info("Setting the Scheduler up");
schedulerFactory.setJobFactory(springBeanJobFactory());
schedulerFactory.setJobDetails(job);
schedulerFactory.setTriggers(trigger);
return schedulerFactory;
}
#Bean
public JobDetailFactoryBean jobDetail()
{
JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
jobDetailFactory.setJobClass(SchedulerService.class);
jobDetailFactory.setName("Qrtz_Job_Detail");
jobDetailFactory.setDescription("Invoke Sample Job service...");
jobDetailFactory.setDurability(true);
return jobDetailFactory;
}
#Bean
public CronTriggerFactoryBean trigger(JobDetail job)
{
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
//three am
trigger.setCronExpression("0 0 3 * * ?");
trigger.setJobDetail(job);
trigger.setName("Qrtz_Trigger");
return trigger;
}
}
quartz.properties : put it in classptah
# thread-pool
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=1
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
# job-store
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
# others
org.quartz.jobStore.misfireThreshold = 60000
Your scheduler service define as follow :
#Component
public class SchedulerService implements Job {
#Autowired
private YoutubeSearchService youtubeSearchService;
#Autowired
private WeatherService weatherService;
#Autowired
private SessionService sessionService;
public void execute(JobExecutionContext context) throws JobExecutionException
{
weatherService.insertRTweather(sessionService.getUserInfo());
}
}
if you want two define more than one schedule, you can it to schedulerconfig by adding a jobdetail and trigger.
Don't forget to add quartz jar file
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>${quartz.version}</version>
</dependency>

Not able inject bean in the component

I have implemented Spring Quartz scheduler example using this link
I am having simple MyJobTwo.java component that has a method executeInternal() that is being called using CronTriggerFactoryBean.
This is my QuartzConfiguration.java
#Configuration
#ComponentScan("com.example")
public class QuartzConfiguration {
// we need to create a bean that will excuted by MethodInvokingJobDetailFactoryBean
// in this case we have myJobOne is the simple bean
#Bean
public MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean() {
MethodInvokingJobDetailFactoryBean obj = new MethodInvokingJobDetailFactoryBean();
obj.setTargetBeanName("myJobOne");
obj.setTargetMethod("myTask");
return obj;
}
// This trigger will schedule the job after 3 seconds and repeat after every 30 seconds for 3+1 times.
#Bean
public SimpleTriggerFactoryBean simpleTriggerFactoryBean(){
SimpleTriggerFactoryBean stFactory = new SimpleTriggerFactoryBean();
stFactory.setJobDetail(methodInvokingJobDetailFactoryBean().getObject());
stFactory.setStartDelay(3000);
stFactory.setRepeatInterval(30000);
stFactory.setRepeatCount(1);
return stFactory;
}
// We use it to configure complex job such as job scheduling using cron-expression
#Bean
public JobDetailFactoryBean jobDetailFactoryBean(){
JobDetailFactoryBean factory = new JobDetailFactoryBean();
factory.setJobClass(MyJobTwo.class);
// Map<String,Object> map = new HashMap<String,Object>();
// map.put("myJobOne", myJobOne);
// map.put(MyJobTwo.myJodOne, 1);
//factory.setJobDataAsMap(map);
//factory.setGroup("mygroup");
//factory.setName("myjob");
return factory;
}
// CronTriggerFactoryBean configures JobDetailFactoryBean
// We also configure start delay, trigger name, and cron-expression to schedule the job
#Bean
public CronTriggerFactoryBean cronTriggerFactoryBean(){
CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean();
stFactory.setJobDetail(jobDetailFactoryBean().getObject());
stFactory.setStartDelay(3000);
//stFactory.setName("mytrigger");
//stFactory.setGroup("mygroup");
stFactory.setCronExpression("0 0/1 * 1/1 * ? *");
return stFactory;
}
// SchedulerFactoryBean use to register the triggers
// those registered triggers will be executed
#Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
scheduler.setTriggers(cronTriggerFactoryBean().getObject());
//scheduler.setTriggers(simpleTriggerFactoryBean().getObject());
return scheduler;
}
}
This is the bean that I am executing using CronTriggerFactoryBean.
MyJobTwo.java
#Component
public class MyJobTwo extends QuartzJobBean {
private SmtpMailSender smtpMailSender;
#Autowired
public MyJobTwo(MyJobOne myJobOne, SmtpMailSender smtpMailSender) {
super();
this.myJobOne = myJobOne;
this.smtpMailSender = smtpMailSender;
}
#Override
protected void executeInternal(JobExecutionContext ctx)
throws JobExecutionException {
System.out.println("this is the test");
myJobOne.myTask();
System.out.println("task is done");
}
}
Whenever I am trying to inject other beans and service I am getting these errors. Anyone having any idea what is causing these errors, what changes do I need to make?
org.quartz.SchedulerException: Job instantiation failed
at org.springframework.scheduling.quartz.AdaptableJobFactory.newJob(AdaptableJobFactory.java:45)
at org.quartz.core.JobRunShell.initialize(JobRunShell.java:127)
at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:375)
Caused by: java.lang.InstantiationException: com.example.job.MyJobTwo
at java.lang.Class.newInstance(Class.java:427)
at org.springframework.scheduling.quartz.AdaptableJobFactory.createJobInstance(AdaptableJobFactory.java:58)
at org.springframework.scheduling.quartz.AdaptableJobFactory.newJob(AdaptableJobFactory.java:41)
... 2 common frames omitted
Caused by: java.lang.NoSuchMethodException: com.example.job.MyJobTwo.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
... 4 common frames omitted
The default job factory implementation AdaptableJobFactory doesn't have autowiring capability.
To use dependency injection do following:
1.Create job factory
package com.concretepage.config;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
public class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
private transient AutowireCapableBeanFactory beanFactory;
public void setApplicationContext(final ApplicationContext context) {
beanFactory = context.getAutowireCapableBeanFactory();
}
#Override
public Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
beanFactory.autowireBean(job); //the magic is done here
return job;
}
}
Implementation is found on http://codrspace.com/Khovansa/spring-quartz-with-a-database/
2.Update schedulerFactoryBean declaration in QuartzConfiguration:
#Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
scheduler.setTriggers(simpleTriggerFactoryBean().getObject(), cronTriggerFactoryBean().getObject());
scheduler.setJobFactory(jobFactory());
return scheduler;
}
#Bean
public JobFactory jobFactory() {
return new AutowiringSpringBeanJobFactory();
}
Use setter-based injection instead of constructor injection

Fire Quartz manually By Spring controller

I use the following configuration class to integrate spring framework with Quartz,It works fine,but the job fires dynamically once the application has started because I use #Configuration annotation,I want to fire the job manually by controller and ui.
How to Fire Quartz manually By Spring controller?
Quartz configuration class
#Configuration
public class QuartzConfig {
#Autowired
private PlatformTransactionManager transactionManager;
#Autowired
private ApplicationContext applicationContext;
#Bean
public SchedulerFactoryBean quartzScheduler() {
SchedulerFactoryBean quartzScheduler = new SchedulerFactoryBean();
quartzScheduler.setTransactionManager(transactionManager);
quartzScheduler.setOverwriteExistingJobs(true);
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
quartzScheduler.setJobFactory(jobFactory);
Trigger[] triggers = {
processMyJobTrigger().getObject()
};
quartzScheduler.setTriggers(triggers);
return quartzScheduler;
}
#Bean
public JobDetailFactoryBean processMyJob() {
JobDetailFactoryBean jobDetailFactory = new JobDetailFactoryBean();
jobDetailFactory.setJobClass(HelloJob.class);
jobDetailFactory.setDurability(true);
return jobDetailFactory;
}
#Bean
public CronTriggerFactoryBean processMyJobTrigger() {
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
cronTriggerFactoryBean.setJobDetail(processMyJob().getObject());
cronTriggerFactoryBean.setCronExpression("0 0/1 * * * ?");
return cronTriggerFactoryBean;
}
}
Quartz job
#Service
#Transactional
public class HelloJob implements Job{
#Inject
TestrecordRepository testrecordRepository;
#Inject
ScoreRepository scoreRepository;
public void execute(JobExecutionContext context)
throws JobExecutionException {
System.out.println("Hello Quartz!");
List<Testrecord> records=testrecordRepository.findAll();
for(Testrecord t:records){
Testrecord testrecord = new Testrecord();
testrecord.setValue_integer(t.getValue_integer());
testrecord.setId(t.getId());
RuleExecutor ruleExecutor = new RuleExecutor();
Score score= ruleExecutor.processRules(testrecord);
scoreRepository.save(score);
}
}
}
From the controller you need to get access to SchedulerFactoryBean, then take scheduler and trigger job you like.
Scheduler scheduler = (Scheduler) getApplicationContext().getBean("schedulerFactoryBean");
scheduler.triggerJob(JobKey jobKey)

Categories

Resources