001/* 002 * Copyright 2002-2014 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.JobExecutionContext; 021import org.quartz.JobExecutionException; 022import org.quartz.SchedulerException; 023 024import org.springframework.beans.BeanWrapper; 025import org.springframework.beans.MutablePropertyValues; 026import org.springframework.beans.PropertyAccessorFactory; 027 028/** 029 * Simple implementation of the Quartz Job interface, applying the 030 * passed-in JobDataMap and also the SchedulerContext as bean property 031 * values. This is appropriate because a new Job instance will be created 032 * for each execution. JobDataMap entries will override SchedulerContext 033 * entries with the same keys. 034 * 035 * <p>For example, let's assume that the JobDataMap contains a key 036 * "myParam" with value "5": The Job implementation can then expose 037 * a bean property "myParam" of type int to receive such a value, 038 * i.e. a method "setMyParam(int)". This will also work for complex 039 * types like business objects etc. 040 * 041 * <p><b>Note that the preferred way to apply dependency injection 042 * to Job instances is via a JobFactory:</b> that is, to specify 043 * {@link SpringBeanJobFactory} as Quartz JobFactory (typically via 044 * {@link SchedulerFactoryBean#setJobFactory} SchedulerFactoryBean's "jobFactory" property}). 045 * This allows to implement dependency-injected Quartz Jobs without 046 * a dependency on Spring base classes. 047 * 048 * @author Juergen Hoeller 049 * @since 18.02.2004 050 * @see org.quartz.JobExecutionContext#getMergedJobDataMap() 051 * @see org.quartz.Scheduler#getContext() 052 * @see SchedulerFactoryBean#setSchedulerContextAsMap 053 * @see SpringBeanJobFactory 054 * @see SchedulerFactoryBean#setJobFactory 055 */ 056public abstract class QuartzJobBean implements Job { 057 058 /** 059 * This implementation applies the passed-in job data map as bean property 060 * values, and delegates to {@code executeInternal} afterwards. 061 * @see #executeInternal 062 */ 063 @Override 064 public final void execute(JobExecutionContext context) throws JobExecutionException { 065 try { 066 BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this); 067 MutablePropertyValues pvs = new MutablePropertyValues(); 068 pvs.addPropertyValues(context.getScheduler().getContext()); 069 pvs.addPropertyValues(context.getMergedJobDataMap()); 070 bw.setPropertyValues(pvs, true); 071 } 072 catch (SchedulerException ex) { 073 throw new JobExecutionException(ex); 074 } 075 executeInternal(context); 076 } 077 078 /** 079 * Execute the actual job. The job data map will already have been 080 * applied as bean property values by execute. The contract is 081 * exactly the same as for the standard Quartz execute method. 082 * @see #execute 083 */ 084 protected abstract void executeInternal(JobExecutionContext context) throws JobExecutionException; 085 086}