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 org.quartz.Job; 020import org.quartz.Scheduler; 021import org.quartz.SchedulerException; 022import org.quartz.spi.JobFactory; 023import org.quartz.spi.TriggerFiredBundle; 024 025import org.springframework.util.ReflectionUtils; 026 027/** 028 * {@link JobFactory} implementation that supports {@link java.lang.Runnable} 029 * objects as well as standard Quartz {@link org.quartz.Job} instances. 030 * 031 * <p>Compatible with Quartz 2.1.4 and higher, as of Spring 4.1. 032 * 033 * @author Juergen Hoeller 034 * @since 2.0 035 * @see DelegatingJob 036 * @see #adaptJob(Object) 037 */ 038public class AdaptableJobFactory implements JobFactory { 039 040 @Override 041 public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException { 042 try { 043 Object jobObject = createJobInstance(bundle); 044 return adaptJob(jobObject); 045 } 046 catch (Throwable ex) { 047 throw new SchedulerException("Job instantiation failed", ex); 048 } 049 } 050 051 /** 052 * Create an instance of the specified job class. 053 * <p>Can be overridden to post-process the job instance. 054 * @param bundle the TriggerFiredBundle from which the JobDetail 055 * and other info relating to the trigger firing can be obtained 056 * @return the job instance 057 * @throws Exception if job instantiation failed 058 */ 059 protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { 060 Class<?> jobClass = bundle.getJobDetail().getJobClass(); 061 return ReflectionUtils.accessibleConstructor(jobClass).newInstance(); 062 } 063 064 /** 065 * Adapt the given job object to the Quartz Job interface. 066 * <p>The default implementation supports straight Quartz Jobs 067 * as well as Runnables, which get wrapped in a DelegatingJob. 068 * @param jobObject the original instance of the specified job class 069 * @return the adapted Quartz Job instance 070 * @throws Exception if the given job could not be adapted 071 * @see DelegatingJob 072 */ 073 protected Job adaptJob(Object jobObject) throws Exception { 074 if (jobObject instanceof Job) { 075 return (Job) jobObject; 076 } 077 else if (jobObject instanceof Runnable) { 078 return new DelegatingJob((Runnable) jobObject); 079 } 080 else { 081 throw new IllegalArgumentException( 082 "Unable to execute job class [" + jobObject.getClass().getName() + 083 "]: only [org.quartz.Job] and [java.lang.Runnable] supported."); 084 } 085 } 086 087}