xkcoding/spring-boot-demo · error · Exception
【定时任务】创建失败!
Error message
【定时任务】创建失败!
What it means
JobServiceImpl.addJob wraps scheduler.scheduleJob(jobDetail, trigger) in try/catch(SchedulerException) and rethrows a generic Exception('【定时任务】创建失败!') at JobServiceImpl.java:62. Note the cron build (CronScheduleBuilder.cronSchedule at line 53) is OUTSIDE the try, so an invalid cron expression escapes uncaught.
Source
Thrown at demo-task-quartz/src/main/java/com/xkcoding/task/quartz/service/impl/JobServiceImpl.java:62
@Override
public void addJob(JobForm form) throws Exception {
// 启动调度器
scheduler.start();
// 构建Job信息
JobDetail jobDetail = JobBuilder.newJob(JobUtil.getClass(form.getJobClassName()).getClass()).withIdentity(form.getJobClassName(), form.getJobGroupName()).build();
// Cron表达式调度构建器(即任务执行的时间)
CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule(form.getCronExpression());
//根据Cron表达式构建一个Trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(form.getJobClassName(), form.getJobGroupName()).withSchedule(cron).build();
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
log.error("【定时任务】创建失败!", e);
throw new Exception("【定时任务】创建失败!");
}
}
/**
* 删除定时任务
*
* @param form 表单参数 {@link JobForm}
* @throws SchedulerException 异常
*/
@Override
public void deleteJob(JobForm form) throws SchedulerException {
scheduler.pauseTrigger(TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName()));
scheduler.unscheduleJob(TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName()));
scheduler.deleteJob(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName()));
}
/**View on GitHub (pinned to 87a142f960)
Solutions
- Check scheduler.checkExists(JobKey.jobKey(className, groupName)) before scheduleJob
- Ensure the job class implements org.quartz.Job and is loadable by JobUtil.getClass
- Validate the cron expression (CronExpression.isValidExpression) before building the schedule
- Keep job class+group unique per submission
Example fix
// before
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
throw new Exception('【定时任务】创建失败!');
}
// after
JobKey jobKey = JobKey.jobKey(form.getJobClassName(), form.getJobGroupName());
if (scheduler.checkExists(jobKey)) {
throw new IllegalStateException('任务已存在: ' + jobKey);
}
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
throw new Exception('【定时任务】创建失败!', e);
} Defensive patterns
Strategy: validation
Validate before calling
JobKey jobKey = JobKey.jobKey(form.getJobClassName(), form.getJobGroupName());
if (scheduler.checkExists(jobKey)) {
throw new IllegalStateException('job already exists: ' + jobKey);
}
if (!CronExpression.isValidExpression(form.getCronExpression())) {
throw new IllegalArgumentException('invalid cron: ' + form.getCronExpression());
} Try / catch
try { jobService.addJob(form); }
catch (Exception e) { if ('【定时任务】创建失败!'.equals(e.getMessage())) { /* surface scheduling failure */ } } Prevention
- Check checkExists before scheduleJob to avoid ObjectAlreadyExistsException
- Ensure the job class implements org.quartz.Job
- Validate the cron expression before CronScheduleBuilder.cronSchedule
When it happens
Trigger: Adding a job whose class+group already exists (ObjectAlreadyExistsException, a SchedulerException); a job class not on the classpath or not implementing org.quartz.Job; a scheduler-store error during scheduleJob.
Common situations: Submitting the same jobClassName twice; a wrong class name in JobForm; clustered Quartz with a conflicting job identity.
AI-assisted analysis of xkcoding/spring-boot-demo@87a142f960 (2026-08-14).
Data as JSON: /api/errors/959341cfdc1807e7.
Report an issue: GitHub.