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