Quartz Scheduler scheduled but not Fire - java

i try to schedule a scheduler and only print (only here) when my sheduler fire, when i schedule it cheduled in QRTZ_TRIGGERS table and also in QRTZ_JOB_DETAILS table but not fire on time.
where my Quartz Scheuler Configuration like,
#Configuration
public class QuartzSchedulerConfiguration {
#Bean
public Scheduler getScheduler() throws SchedulerException {
return StdSchedulerFactory.getDefaultScheduler();
}
}
and quartz.properties file like,
## QuartzProperties
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=10
org.quartz.threadPool.
threadsInheritContextClassLoaderOfInitializingThread=true
org.quartz.jobStore.tablePrefix=QRTZ_
#The datasource for the jobstore that is to be used
org.quartz.jobStore.dataSource=myDS
org.quartz.dataSource.myDS.driver=com.mysql.cj.jdbc.Driver
org.quartz.dataSource.myDS.URL=jdbc:mysql://localhost:3306/my_db?
useSSL=false
org.quartz.dataSource.myDS.user=root
org.quartz.dataSource.myDS.password=1111
org.quartz.dataSource.myDS.maxConnections=20
and Service class have,
#Autowired
private Scheduler scheduler;
public String addFTP(FTPDomain ftpDomain) {
String msg = "";
//Start schedule =======================================================
String str = "2019-01-16 13:10:01";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localeDateTime = LocalDateTime.parse(str, formatter);
System.out.println("Date time is "+localeDateTime);
try {
ZonedDateTime dateTime = ZonedDateTime.of(localeDateTime, ZoneId.of("Asia/Kolkata"));
if(dateTime.isBefore(ZonedDateTime.now())) {
msg = "You are schedule a expired Date and time";
System.out.println(msg);
}
JobDetail jobDetail = buildJobDetail(ftpDomain);
Trigger trigger = buildJobTrigger(jobDetail, dateTime);
scheduler.scheduleJob(jobDetail, trigger); // ## here i schedule
System.out.println(jobDetail.getKey().getName()+" "+ jobDetail.getKey().getGroup()+""+ "Scheduller Scheduled Successfully!");
} catch (SchedulerException ex) {
System.out.println( "Error scheduling email. Please try later!");
}
//Stop schedulling=========================================================================
return ftpTransferDaoInterface.addFTP(ftpDomain);
}
private JobDetail buildJobDetail(FTPDomain ftpDamain) {
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("destPath", ftpDamain.getServerDestinationPath());
jobDataMap.put("ip", ftpDamain.getServerIP());
jobDataMap.put("user", ftpDamain.getServerUser());
return JobBuilder.newJob(FTPTransferJob.class)
.withIdentity(UUID.randomUUID().toString(), "schedule-jobs")
.withDescription("Send schedule Job")
.usingJobData(jobDataMap)
.storeDurably().build();
}
private Trigger buildJobTrigger(JobDetail jobDetail, ZonedDateTime startAt) {
return TriggerBuilder.newTrigger()
.forJob(jobDetail)
.withIdentity(jobDetail.getKey().getName(), "email-triggers")
.withDescription("Send Email Trigger")
.startAt(Date.from(startAt.toInstant()))
.withSchedule(SimpleScheduleBuilder
.simpleSchedule()
.withMisfireHandlingInstructionFireNow()
).build();
}
and my Quartz JOB class like,
#Component
public class FTPTransferJob extends QuartzJobBean {
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
System.err.println("Executing Job with key {}"+
context.getJobDetail().getKey());
JobDataMap jobDataMap = context.getMergedJobDataMap();
String destination = jobDataMap.getString("destPath");
String ip = jobDataMap.getString("ip");
String user = jobDataMap.getString("user");
System.err.println("Schedulled Job Executed Here "+destination+", ip
is "+ip+", user is "+user);
}
}
can any one find the solution ? Thanks...

Related

Configureable Scheduling in Spring Boot

I am using Spring Boot 2.6.6 and I want to configure scheduled tasks at runtime. The task configs are saved in a database. Here is my code:
#Configuration
#EnableScheduling
public class SchedulerConfig implements SchedulingConfigurer, DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(SchedulerConfig.class);
private BackupJobsService backupJobsService;
private BackupService backupService;
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
public SchedulerConfig(#Autowired BackupJobsService backupJobsService, #Autowired BackupService backupService) {
this.backupJobsService = backupJobsService;
this.backupService = backupService;
}
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
logger.info("Register all custom cron jobs...");
logger.debug("====> SchedulerConfig: configureTasks <====");
List<BackupJob> listOfJobs = backupJobsService.findAll();
for (BackupJob backupJob : listOfJobs) {
BackupTask backupTask = new BackupTask(backupJob, backupService);
Trigger trigger = new Trigger() {
#Override
public Date nextExecutionTime(TriggerContext triggerContext) {
logger.debug("====> SchedulerConfig: nextExecutionTime (" + backupJob.getJobName() + ") <====");
CronTrigger crontrigger = new CronTrigger(backupJob.getJobConfig());
return crontrigger.nextExecutionTime(triggerContext);
}
};
taskRegistrar.addTriggerTask(backupTask, trigger);
}
}
#Override
public void destroy() throws Exception {
logger.debug("====> SchedulerConfig: destroy <====");
if (executor != null) {
executor.shutdownNow();
}
}
}
The object backupJob has all Infos about the job. In the field JobConfig save the cron string for the job.
This class work perfect if I start the spring boot application. How can I reconfigure the tasks without a restart of the spring boot application ?

How to check which Quartz Scheduler job is not running

I have below code which i have used to check which quartz scheduler job is running. And it also send me an email the list of running scheduler job. But i dont know its not returning all the scheduler jobs which are running.And now i want to know only those scheduler job which has issues,stopped and not running. I found critical issue in my Production environment where i found that some of the scheduler jobs are not running but i really dont know which scheduler job it is.
public String getPrintJobs() {
StringBuilder sb = new StringBuilder();
try {
sb.append("Quartz Jobs\r\n\r\n");
Scheduler scheduler = this.getJobScheduler();
// All scheduled jobs
for (String groupName : scheduler.getJobGroupNames()) {
for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
final List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
Date nextFireTime = null;
int priority = 5;
if (triggers.size() > 0)
{
nextFireTime = triggers.get(0).getNextFireTime();
priority = triggers.get(0).getPriority();
}
sb.append("Name= "+ jobKey.getName() + " Group=" + jobKey.getGroup() + " NextFireTime=" + nextFireTime + " Priority=" + priority + " Paused=" + (isJobPaused(jobKey.getName())?"IS PAUSED":"NOT PAUSED") + " Triggers #=" + triggers.size() + "\r\n\r\n");
}
}
sb.append("End Quartz Jobs\r\n\r\n");
} catch (Exception e) {
logger.debug("debugPrintJobs:" + e.getMessage());
}
return sb.toString();
}
private Boolean isJobPaused(String jobName) throws SchedulerException {
Scheduler scheduler = this.getJobScheduler();
JobKey jobKey = new JobKey(jobName);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobDetail.getKey());
for (Trigger trigger : triggers) {
TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
if (TriggerState.PAUSED.equals(triggerState)) {
return true;
}
}
return false;
}
I haven't used it for getting any problem but the following interfaces could be helped you.
TriggerListener could check misfired when Quartz couldn't start the job.
JobListener could check completed the job which is both successful and failure cases.
https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/tutorial-lesson-07.html

Quartz Scheduler not inserting records in DB using JDBCStore

Configured Quartz job,
public static void schedule(IEntity entity, Date startdate) {
try {
JobDetail job = JobBuilder.newJob(StatingUpdateJob.class)
.withIdentity("UpdateStagingRecords" + entity.getId(), "StgToProduction").build();
JobDataMap data = new JobDataMap(new HashMap<>());
data.put("Entity", entity);
job.getJobBuilder().setJobData(data);
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
Date enddate = new Date();
enddate.setTime(startdate.getTime() + 6000000);
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
.withIdentity("UpdateStagingRecords" + entity.getId(), "StgToProduction").startAt(startdate)
.withSchedule(CronScheduleBuilder.cronSchedule("0 0/5 * 1/1 * ? *")
.withMisfireHandlingInstructionDoNothing())
.endAt(enddate).build();
Connection connection = DBConnectionManager.getInstance().getConnection("myDS");
System.out.println(connection);
scheduler.scheduleJob(job, cronTrigger);
scheduler.start();
} catch (Exception e) {
System.out.println("Something went wrong");
e.printStackTrace();
}
}
And then placed the quartz.properties in my class path
org.quartz.scheduler.instanceName=JavacodeGeeksScheduler
org.quartz.scheduler.instanceId=99199
org.quartz.scheduler.rmi.export=false
org.quartz.scheduler.rmi.proxy=false
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=3
org.quartz.context.key.QuartzTopic=QuartzPorperties
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.dataSource=myDS
org.quartz.jobListener.NAME.class=com.javacodegeeks.quartz.MyJobListener
org.quartz.dataSource.myDS.driver=com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL=jdbc:mysql://localhost/test
org.quartz.dataSource.myDS.user=admin
org.quartz.dataSource.myDS.password=admin
org.quartz.dataSource.myDS.maxConnections=30
My job is successfully created and triggering properly. But however the job details are not placing in DB. Here is my tables
Not sure what else I have to configure.
It is strange that quartz datasource URL is not accepting as same as native jdbc url.
When I changed jdbc:mysql://localhost/test to
jdbc:mysql://localhost:3306/test
IT WORKED (thanks to #pringi and #Bilbo Baggins).

Spring + Quartz, Trigger is null

I'm dwelling with Quartz from days..
I need to create, the app starts, some triggers and job details..
So, this is my Job
#DisallowConcurrentExecution
public class TimeoutJob extends QuartzJobBean{
public final String ID = "idInterruttore";
private final Logger logger = Logger.getLogger(TimeoutJob.class);
#Autowired InterruttoreService interruttoreService;
#Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
int idInterruttore = dataMap.getIntFromString(ID);
Interruttore interruttore = interruttoreService.findById(idInterruttore);
logger.debug("Job reached for " + interruttore.getNomeInterruttore());
}
}
Then i configure some bean in QuartzConfiguration.java
#Configuration
#ComponentScan("it.besmart")
public class QuartzConfiguration {
#Autowired
ApplicationContext applicationContext;
#Bean
public SchedulerFactoryBean scheduler() {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setJobFactory(springBeanJobFactory());
return schedulerFactory;
}
#Bean
public SpringBeanJobFactory springBeanJobFactory() {
AutoWiringSpringBeanJobFactory jobFactory = new AutoWiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
}
Now, I have a JobManager.class which manage jobDetails and Triggers
#Service("jobManager")
public class JobManager {
private final Logger logger = Logger.getLogger(JobManager.class);
#Autowired
SchedulerFactoryBean scheduler;
#Autowired
InterruttoreService interruttoreService;
#PostConstruct
public void createInitialJobs() {
logger.debug("Start ut jobs to create");
List<Interruttore> interruttori = interruttoreService.findAllSwitches();
Date now = new Date();
for (int i = 0; i < interruttori.size(); i++) {
Interruttore interruttore = interruttori.get(i);
if (interruttore.getTimeoutDate().after(now) && interruttore.isStato()) {
// JobDetail and Trigger creation
createJob(interruttore, interruttore.getTimeoutDate());
}
}
}
public void createJob(Interruttore interruttore, Date richiesta) {
JobDetailFactoryBean jobDetail = new JobDetailFactoryBean();
jobDetail.setJobClass(TimeoutJob.class);
jobDetail.setName("Job detail for " + interruttore.getNomeInterruttore());
jobDetail.setDescription("Job Description");
jobDetail.setDurability(true);
Map<String, Integer> map = new HashMap<String,Integer>();
map.put("idInterruttore", interruttore.getIdInterruttore());
jobDetail.setJobDataAsMap(map);
long future = richiesta.getTime() - new Date().getTime();
logger.debug("next timeout is " + future / 1000 / 60 + " minuti for " + interruttore.getNomeInterruttore());
//trigger creation
SimpleTriggerFactoryBean trigger = new SimpleTriggerFactoryBean();
trigger.setName("myTrigger"+interruttore.getNomeInterruttore());
trigger.setGroup("timeoutTriggers");
trigger.setJobDetail(jobDetail.getObject());
trigger.setStartDelay(0);
trigger.setRepeatCount(1);
trigger.setRepeatInterval(future);
trigger.afterPropertiesSet();
logger.debug("Trigger for " + interruttore.getNomeInterruttore());
logger.debug("Trigger object is :" + trigger.getObject());
logger.debug("Next Trigger date " + trigger.getObject().getFinalFireTime());
try {
scheduler.getScheduler().scheduleJob(jobDetail.getObject(), trigger.getObject());
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
When launching the app, the #PostConstruct method tries to create the triggers, but i'm getting an exception when creating jobManager
Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobManager': Invocation of init method failed; nested exception is java.lang.NullPointerException
caused by
Caused by: java.lang.NullPointerException
at org.springframework.scheduling.quartz.SimpleTriggerFactoryBean.afterPropertiesSet(SimpleTriggerFactoryBean.java:231)
at it.besmart.quartz.JobManager.createJob(JobManager.java:85)
at it.besmart.quartz.JobManager.createInitialJobs(JobManager.java:54)
which is
trigger.afterPropertiesSet();
as my triggers are not created...
There is a bug in the spring-context-support jar 4.2.5 version.
sti.setJobKey(this.jobDetail.getKey());
i.e. jobDetail can be null.
In the new versions it is fixed. I checked 4.3.2 version.
You can use 4.3.2 or later.
In 4.3.2 version
if (this.jobDetail != null) {
sti.setJobKey(this.jobDetail.getKey());
}

Jersey 2.0: Create repeating job

In our REST-Service we want to implement a job that checks something every 10 seconds. So we thought we could use Quartz to make a Job that cover this. But the problem is, that we need to inject a singleton, because it is used in the job and the job seems to be not in the context of our service, so the injected class is always null (NullPointerException).
So is there another possible solution to achieve such a job without using Quartz? Already tried to write our own JobFactory that connects the job with the BeanManager, but it didnt work at all.
This is the code for the job that is not working:
#Stateless
public class GCEStatusJob implements Job, Serializable{
private Logger log = LoggerFactory.getLogger(GCEStatusJob.class);
#Inject
SharedMemory sharedMemory;
#Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
GoogleComputeEngineFactory googleComputeEngineFactory = new GoogleComputeEngineFactory();
List<HeartbeatModel> heartbeatList = new ArrayList<>(sharedMemory.getAllHeartbeats());
List<GCE> gceList = googleComputeEngineFactory.listGCEs();
List<String> ipAddressList = gceList.stream().map(GCE::getIp).collect(Collectors.toList());
for(HeartbeatModel heartbeat : heartbeatList){
if(ipAddressList.contains(heartbeat.getIpAddress())){
long systemTime = System.currentTimeMillis();
if(systemTime-heartbeat.getSystemTime()>10000){
log.info("Compute Engine mit IP "+heartbeat.getIpAddress()+" antwortet nicht mehr. Wird neu gestartet!");
String name = gceList.stream().filter((i) -> i.getIp().equals(heartbeat.getIpAddress())).findFirst().get().getName();
googleComputeEngineFactory.resetGCE(name);
}
}
}
}
}
SharedMemory is always null.
I have used Scheduler context map to achive this. You can try this.
In REST API when we create a Scheduler we can use the Context map to pass the parameters to Job
#Path("job")
public class RESTApi {
private String _userID;
public String get_userID() {
return _userID;
}
public void set_userID(String _userID) {
this._userID = _userID;
}
#GET
#Path("/start/{userId}")
public void startJob(#PathParam("userId") String userID) {
_userID = userID;
try {
SimpleTrigger trigger = new SimpleTrigger();
trigger.setName("updateTrigger");
trigger.setStartTime(new Date(System.currentTimeMillis() + 1000));
trigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
trigger.setRepeatInterval(1000);
JobDetail job = new JobDetail();
job.setName("updateJob");
job.setJobClass(GCEStatusJob.class);
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.getContext().put("apiClass", this);
scheduler.start();
scheduler.scheduleJob(job, trigger);
} catch (Exception e) {
e.printStackTrace();
}
}
}
JOB implementation
public class GCEStatusJob implements Job {
#Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
RESTApi apiClass;
try {
apiClass = ((RESTApi) arg0.getScheduler().getContext().get("apiClass"));
System.out.println("User name is" + apiClass.get_userID());
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
Correct me, if my understanding is wrong.

Categories

Resources