001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.scheduling.quartz; 018 019import java.util.Date; 020import java.util.Map; 021 022import org.quartz.JobDataMap; 023import org.quartz.JobDetail; 024import org.quartz.Scheduler; 025import org.quartz.SimpleTrigger; 026import org.quartz.impl.triggers.SimpleTriggerImpl; 027 028import org.springframework.beans.factory.BeanNameAware; 029import org.springframework.beans.factory.FactoryBean; 030import org.springframework.beans.factory.InitializingBean; 031import org.springframework.core.Constants; 032import org.springframework.lang.Nullable; 033import org.springframework.util.Assert; 034 035/** 036 * A Spring {@link FactoryBean} for creating a Quartz {@link org.quartz.SimpleTrigger} 037 * instance, supporting bean-style usage for trigger configuration. 038 * 039 * <p>{@code SimpleTrigger(Impl)} itself is already a JavaBean but lacks sensible defaults. 040 * This class uses the Spring bean name as job name, the Quartz default group ("DEFAULT") 041 * as job group, the current time as start time, and indefinite repetition, if not specified. 042 * 043 * <p>This class will also register the trigger with the job name and group of 044 * a given {@link org.quartz.JobDetail}. This allows {@link SchedulerFactoryBean} 045 * to automatically register a trigger for the corresponding JobDetail, 046 * instead of registering the JobDetail separately. 047 * 048 * @author Juergen Hoeller 049 * @since 3.1 050 * @see #setName 051 * @see #setGroup 052 * @see #setStartDelay 053 * @see #setJobDetail 054 * @see SchedulerFactoryBean#setTriggers 055 * @see SchedulerFactoryBean#setJobDetails 056 */ 057public class SimpleTriggerFactoryBean implements FactoryBean<SimpleTrigger>, BeanNameAware, InitializingBean { 058 059 /** Constants for the SimpleTrigger class. */ 060 private static final Constants constants = new Constants(SimpleTrigger.class); 061 062 063 @Nullable 064 private String name; 065 066 @Nullable 067 private String group; 068 069 @Nullable 070 private JobDetail jobDetail; 071 072 private JobDataMap jobDataMap = new JobDataMap(); 073 074 @Nullable 075 private Date startTime; 076 077 private long startDelay; 078 079 private long repeatInterval; 080 081 private int repeatCount = -1; 082 083 private int priority; 084 085 private int misfireInstruction; 086 087 @Nullable 088 private String description; 089 090 @Nullable 091 private String beanName; 092 093 @Nullable 094 private SimpleTrigger simpleTrigger; 095 096 097 /** 098 * Specify the trigger's name. 099 */ 100 public void setName(String name) { 101 this.name = name; 102 } 103 104 /** 105 * Specify the trigger's group. 106 */ 107 public void setGroup(String group) { 108 this.group = group; 109 } 110 111 /** 112 * Set the JobDetail that this trigger should be associated with. 113 */ 114 public void setJobDetail(JobDetail jobDetail) { 115 this.jobDetail = jobDetail; 116 } 117 118 /** 119 * Set the trigger's JobDataMap. 120 * @see #setJobDataAsMap 121 */ 122 public void setJobDataMap(JobDataMap jobDataMap) { 123 this.jobDataMap = jobDataMap; 124 } 125 126 /** 127 * Return the trigger's JobDataMap. 128 */ 129 public JobDataMap getJobDataMap() { 130 return this.jobDataMap; 131 } 132 133 /** 134 * Register objects in the JobDataMap via a given Map. 135 * <p>These objects will be available to this Trigger only, 136 * in contrast to objects in the JobDetail's data map. 137 * @param jobDataAsMap a Map with String keys and any objects as values 138 * (for example Spring-managed beans) 139 */ 140 public void setJobDataAsMap(Map<String, ?> jobDataAsMap) { 141 this.jobDataMap.putAll(jobDataAsMap); 142 } 143 144 /** 145 * Set a specific start time for the trigger. 146 * <p>Note that a dynamically computed {@link #setStartDelay} specification 147 * overrides a static timestamp set here. 148 */ 149 public void setStartTime(Date startTime) { 150 this.startTime = startTime; 151 } 152 153 /** 154 * Set the start delay in milliseconds. 155 * <p>The start delay is added to the current system time (when the bean starts) 156 * to control the start time of the trigger. 157 * @see #setStartTime 158 */ 159 public void setStartDelay(long startDelay) { 160 Assert.isTrue(startDelay >= 0, "Start delay cannot be negative"); 161 this.startDelay = startDelay; 162 } 163 164 /** 165 * Specify the interval between execution times of this trigger. 166 */ 167 public void setRepeatInterval(long repeatInterval) { 168 this.repeatInterval = repeatInterval; 169 } 170 171 /** 172 * Specify the number of times this trigger is supposed to fire. 173 * <p>Default is to repeat indefinitely. 174 */ 175 public void setRepeatCount(int repeatCount) { 176 this.repeatCount = repeatCount; 177 } 178 179 /** 180 * Specify the priority of this trigger. 181 */ 182 public void setPriority(int priority) { 183 this.priority = priority; 184 } 185 186 /** 187 * Specify a misfire instruction for this trigger. 188 */ 189 public void setMisfireInstruction(int misfireInstruction) { 190 this.misfireInstruction = misfireInstruction; 191 } 192 193 /** 194 * Set the misfire instruction via the name of the corresponding 195 * constant in the {@link org.quartz.SimpleTrigger} class. 196 * Default is {@code MISFIRE_INSTRUCTION_SMART_POLICY}. 197 * @see org.quartz.SimpleTrigger#MISFIRE_INSTRUCTION_FIRE_NOW 198 * @see org.quartz.SimpleTrigger#MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_EXISTING_COUNT 199 * @see org.quartz.SimpleTrigger#MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT 200 * @see org.quartz.SimpleTrigger#MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT 201 * @see org.quartz.SimpleTrigger#MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT 202 * @see org.quartz.Trigger#MISFIRE_INSTRUCTION_SMART_POLICY 203 */ 204 public void setMisfireInstructionName(String constantName) { 205 this.misfireInstruction = constants.asNumber(constantName).intValue(); 206 } 207 208 /** 209 * Associate a textual description with this trigger. 210 */ 211 public void setDescription(String description) { 212 this.description = description; 213 } 214 215 @Override 216 public void setBeanName(String beanName) { 217 this.beanName = beanName; 218 } 219 220 221 @Override 222 public void afterPropertiesSet() { 223 if (this.name == null) { 224 this.name = this.beanName; 225 } 226 if (this.group == null) { 227 this.group = Scheduler.DEFAULT_GROUP; 228 } 229 if (this.jobDetail != null) { 230 this.jobDataMap.put("jobDetail", this.jobDetail); 231 } 232 if (this.startDelay > 0 || this.startTime == null) { 233 this.startTime = new Date(System.currentTimeMillis() + this.startDelay); 234 } 235 236 SimpleTriggerImpl sti = new SimpleTriggerImpl(); 237 sti.setName(this.name != null ? this.name : toString()); 238 sti.setGroup(this.group); 239 if (this.jobDetail != null) { 240 sti.setJobKey(this.jobDetail.getKey()); 241 } 242 sti.setJobDataMap(this.jobDataMap); 243 sti.setStartTime(this.startTime); 244 sti.setRepeatInterval(this.repeatInterval); 245 sti.setRepeatCount(this.repeatCount); 246 sti.setPriority(this.priority); 247 sti.setMisfireInstruction(this.misfireInstruction); 248 sti.setDescription(this.description); 249 this.simpleTrigger = sti; 250 } 251 252 253 @Override 254 @Nullable 255 public SimpleTrigger getObject() { 256 return this.simpleTrigger; 257 } 258 259 @Override 260 public Class<?> getObjectType() { 261 return SimpleTrigger.class; 262 } 263 264 @Override 265 public boolean isSingleton() { 266 return true; 267 } 268 269}