Source Code Cross Referenced for SchedulerFactoryBean.java in  » J2EE » spring-framework-2.5 » org » springframework » scheduling » quartz » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.5 » org.springframework.scheduling.quartz 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2002-2007 the original author or authors.
0003:         *
0004:         * Licensed under the Apache License, Version 2.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         *
0008:         *      http://www.apache.org/licenses/LICENSE-2.0
0009:         *
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:
0017:        package org.springframework.scheduling.quartz;
0018:
0019:        import java.io.IOException;
0020:        import java.util.ArrayList;
0021:        import java.util.Arrays;
0022:        import java.util.Iterator;
0023:        import java.util.LinkedList;
0024:        import java.util.List;
0025:        import java.util.Map;
0026:        import java.util.Properties;
0027:
0028:        import javax.sql.DataSource;
0029:
0030:        import org.apache.commons.logging.Log;
0031:        import org.apache.commons.logging.LogFactory;
0032:        import org.quartz.Calendar;
0033:        import org.quartz.JobDetail;
0034:        import org.quartz.JobListener;
0035:        import org.quartz.ObjectAlreadyExistsException;
0036:        import org.quartz.Scheduler;
0037:        import org.quartz.SchedulerException;
0038:        import org.quartz.SchedulerFactory;
0039:        import org.quartz.SchedulerListener;
0040:        import org.quartz.Trigger;
0041:        import org.quartz.TriggerListener;
0042:        import org.quartz.impl.RemoteScheduler;
0043:        import org.quartz.impl.StdSchedulerFactory;
0044:        import org.quartz.simpl.SimpleThreadPool;
0045:        import org.quartz.spi.JobFactory;
0046:
0047:        import org.springframework.beans.BeanUtils;
0048:        import org.springframework.beans.factory.DisposableBean;
0049:        import org.springframework.beans.factory.FactoryBean;
0050:        import org.springframework.beans.factory.InitializingBean;
0051:        import org.springframework.context.ApplicationContext;
0052:        import org.springframework.context.ApplicationContextAware;
0053:        import org.springframework.context.Lifecycle;
0054:        import org.springframework.core.io.Resource;
0055:        import org.springframework.core.io.support.PropertiesLoaderUtils;
0056:        import org.springframework.core.task.TaskExecutor;
0057:        import org.springframework.scheduling.SchedulingException;
0058:        import org.springframework.transaction.PlatformTransactionManager;
0059:        import org.springframework.transaction.TransactionException;
0060:        import org.springframework.transaction.TransactionStatus;
0061:        import org.springframework.transaction.support.DefaultTransactionDefinition;
0062:        import org.springframework.util.CollectionUtils;
0063:
0064:        /**
0065:         * FactoryBean that sets up a Quartz {@link org.quartz.Scheduler},
0066:         * manages its lifecycle as part of the Spring application context,
0067:         * and exposes the Scheduler reference for dependency injection.
0068:         *
0069:         * <p>Allows registration of JobDetails, Calendars and Triggers, automatically
0070:         * starting the scheduler on initialization and shutting it down on destruction.
0071:         * In scenarios that just require static registration of jobs at startup, there
0072:         * is no need to access the Scheduler instance itself in application code.
0073:         *
0074:         * <p>For dynamic registration of jobs at runtime, use a bean reference to
0075:         * this SchedulerFactoryBean to get direct access to the Quartz Scheduler
0076:         * (<code>org.quartz.Scheduler</code>). This allows you to create new jobs
0077:         * and triggers, and also to control and monitor the entire Scheduler.
0078:         *
0079:         * <p>Note that Quartz instantiates a new Job for each execution, in
0080:         * contrast to Timer which uses a TimerTask instance that is shared
0081:         * between repeated executions. Just JobDetail descriptors are shared.
0082:         *
0083:         * <p>When using persistent jobs, it is strongly recommended to perform all
0084:         * operations on the Scheduler within Spring-managed (or plain JTA) transactions.
0085:         * Else, database locking will not properly work and might even break.
0086:         * (See {@link #setDataSource setDataSource} javadoc for details.)
0087:         *
0088:         * <p>The preferred way to achieve transactional execution is to demarcate
0089:         * declarative transactions at the business facade level, which will
0090:         * automatically apply to Scheduler operations performed within those scopes.
0091:         * Alternatively, you may add transactional advice for the Scheduler itself.
0092:         *
0093:         * <p>This version of Spring's SchedulerFactoryBean requires Quartz 1.5 or higher.
0094:         *
0095:         * @author Juergen Hoeller
0096:         * @since 18.02.2004
0097:         * @see #setDataSource
0098:         * @see org.quartz.Scheduler
0099:         * @see org.quartz.SchedulerFactory
0100:         * @see org.quartz.impl.StdSchedulerFactory
0101:         * @see org.springframework.transaction.interceptor.TransactionProxyFactoryBean
0102:         */
0103:        public class SchedulerFactoryBean implements  FactoryBean,
0104:                ApplicationContextAware, InitializingBean, DisposableBean,
0105:                Lifecycle {
0106:
0107:            public static final String PROP_THREAD_COUNT = "org.quartz.threadPool.threadCount";
0108:
0109:            public static final int DEFAULT_THREAD_COUNT = 10;
0110:
0111:            private static final ThreadLocal configTimeTaskExecutorHolder = new ThreadLocal();
0112:
0113:            private static final ThreadLocal configTimeDataSourceHolder = new ThreadLocal();
0114:
0115:            private static final ThreadLocal configTimeNonTransactionalDataSourceHolder = new ThreadLocal();
0116:
0117:            /**
0118:             * Return the TaskExecutor for the currently configured Quartz Scheduler,
0119:             * to be used by LocalTaskExecutorThreadPool.
0120:             * <p>This instance will be set before initialization of the corresponding
0121:             * Scheduler, and reset immediately afterwards. It is thus only available
0122:             * during configuration.
0123:             * @see #setDataSource
0124:             * @see LocalDataSourceJobStore
0125:             */
0126:            public static TaskExecutor getConfigTimeTaskExecutor() {
0127:                return (TaskExecutor) configTimeTaskExecutorHolder.get();
0128:            }
0129:
0130:            /**
0131:             * Return the DataSource for the currently configured Quartz Scheduler,
0132:             * to be used by LocalDataSourceJobStore.
0133:             * <p>This instance will be set before initialization of the corresponding
0134:             * Scheduler, and reset immediately afterwards. It is thus only available
0135:             * during configuration.
0136:             * @see #setDataSource
0137:             * @see LocalDataSourceJobStore
0138:             */
0139:            public static DataSource getConfigTimeDataSource() {
0140:                return (DataSource) configTimeDataSourceHolder.get();
0141:            }
0142:
0143:            /**
0144:             * Return the non-transactional DataSource for the currently configured
0145:             * Quartz Scheduler, to be used by LocalDataSourceJobStore.
0146:             * <p>This instance will be set before initialization of the corresponding
0147:             * Scheduler, and reset immediately afterwards. It is thus only available
0148:             * during configuration.
0149:             * @see #setNonTransactionalDataSource
0150:             * @see LocalDataSourceJobStore
0151:             */
0152:            public static DataSource getConfigTimeNonTransactionalDataSource() {
0153:                return (DataSource) configTimeNonTransactionalDataSourceHolder
0154:                        .get();
0155:            }
0156:
0157:            protected final Log logger = LogFactory.getLog(getClass());
0158:
0159:            private Class schedulerFactoryClass = StdSchedulerFactory.class;
0160:
0161:            private String schedulerName;
0162:
0163:            private Resource configLocation;
0164:
0165:            private Properties quartzProperties;
0166:
0167:            private TaskExecutor taskExecutor;
0168:
0169:            private DataSource dataSource;
0170:
0171:            private DataSource nonTransactionalDataSource;
0172:
0173:            private PlatformTransactionManager transactionManager;
0174:
0175:            private Map schedulerContextMap;
0176:
0177:            private ApplicationContext applicationContext;
0178:
0179:            private String applicationContextSchedulerContextKey;
0180:
0181:            private JobFactory jobFactory;
0182:
0183:            private boolean jobFactorySet = false;
0184:
0185:            private boolean overwriteExistingJobs = false;
0186:
0187:            private String[] jobSchedulingDataLocations;
0188:
0189:            private List jobDetails;
0190:
0191:            private Map calendars;
0192:
0193:            private List triggers;
0194:
0195:            private SchedulerListener[] schedulerListeners;
0196:
0197:            private JobListener[] globalJobListeners;
0198:
0199:            private JobListener[] jobListeners;
0200:
0201:            private TriggerListener[] globalTriggerListeners;
0202:
0203:            private TriggerListener[] triggerListeners;
0204:
0205:            private boolean autoStartup = true;
0206:
0207:            private int startupDelay = 0;
0208:
0209:            private boolean waitForJobsToCompleteOnShutdown = false;
0210:
0211:            private Scheduler scheduler;
0212:
0213:            /**
0214:             * Set the Quartz SchedulerFactory implementation to use.
0215:             * <p>Default is StdSchedulerFactory, reading in the standard
0216:             * quartz.properties from quartz.jar. To use custom Quartz
0217:             * properties, specify "configLocation" or "quartzProperties".
0218:             * @see org.quartz.impl.StdSchedulerFactory
0219:             * @see #setConfigLocation
0220:             * @see #setQuartzProperties
0221:             */
0222:            public void setSchedulerFactoryClass(Class schedulerFactoryClass) {
0223:                if (schedulerFactoryClass == null
0224:                        || !SchedulerFactory.class
0225:                                .isAssignableFrom(schedulerFactoryClass)) {
0226:                    throw new IllegalArgumentException(
0227:                            "schedulerFactoryClass must implement [org.quartz.SchedulerFactory]");
0228:                }
0229:                this .schedulerFactoryClass = schedulerFactoryClass;
0230:            }
0231:
0232:            /**
0233:             * Set the name of the Scheduler to fetch from the SchedulerFactory.
0234:             * If not specified, the default Scheduler will be used.
0235:             * @see org.quartz.SchedulerFactory#getScheduler(String)
0236:             * @see org.quartz.SchedulerFactory#getScheduler
0237:             */
0238:            public void setSchedulerName(String schedulerName) {
0239:                this .schedulerName = schedulerName;
0240:            }
0241:
0242:            /**
0243:             * Set the location of the Quartz properties config file, for example
0244:             * as classpath resource "classpath:quartz.properties".
0245:             * <p>Note: Can be omitted when all necessary properties are specified
0246:             * locally via this bean, or when relying on Quartz' default configuration.
0247:             * @see #setQuartzProperties
0248:             */
0249:            public void setConfigLocation(Resource configLocation) {
0250:                this .configLocation = configLocation;
0251:            }
0252:
0253:            /**
0254:             * Set Quartz properties, like "org.quartz.threadPool.class".
0255:             * <p>Can be used to override values in a Quartz properties config file,
0256:             * or to specify all necessary properties locally.
0257:             * @see #setConfigLocation
0258:             */
0259:            public void setQuartzProperties(Properties quartzProperties) {
0260:                this .quartzProperties = quartzProperties;
0261:            }
0262:
0263:            /**
0264:             * Set the Spring TaskExecutor to use as Quartz backend.
0265:             * Exposed as thread pool through the Quartz SPI.
0266:             * <p>Can be used to assign a JDK 1.5 ThreadPoolExecutor or a CommonJ
0267:             * WorkManager as Quartz backend, to avoid Quartz's manual thread creation.
0268:             * <p>By default, a Quartz SimpleThreadPool will be used, configured through
0269:             * the corresponding Quartz properties.
0270:             * @see #setQuartzProperties
0271:             * @see LocalTaskExecutorThreadPool
0272:             * @see org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
0273:             * @see org.springframework.scheduling.commonj.WorkManagerTaskExecutor
0274:             */
0275:            public void setTaskExecutor(TaskExecutor taskExecutor) {
0276:                this .taskExecutor = taskExecutor;
0277:            }
0278:
0279:            /**
0280:             * Set the default DataSource to be used by the Scheduler. If set,
0281:             * this will override corresponding settings in Quartz properties.
0282:             * <p>Note: If this is set, the Quartz settings should not define
0283:             * a job store "dataSource" to avoid meaningless double configuration.
0284:             * <p>A Spring-specific subclass of Quartz' JobStoreCMT will be used.
0285:             * It is therefore strongly recommended to perform all operations on
0286:             * the Scheduler within Spring-managed (or plain JTA) transactions.
0287:             * Else, database locking will not properly work and might even break
0288:             * (e.g. if trying to obtain a lock on Oracle without a transaction).
0289:             * <p>Supports both transactional and non-transactional DataSource access.
0290:             * With a non-XA DataSource and local Spring transactions, a single DataSource
0291:             * argument is sufficient. In case of an XA DataSource and global JTA transactions,
0292:             * SchedulerFactoryBean's "nonTransactionalDataSource" property should be set,
0293:             * passing in a non-XA DataSource that will not participate in global transactions.
0294:             * @see #setNonTransactionalDataSource
0295:             * @see #setQuartzProperties
0296:             * @see #setTransactionManager
0297:             * @see LocalDataSourceJobStore
0298:             */
0299:            public void setDataSource(DataSource dataSource) {
0300:                this .dataSource = dataSource;
0301:            }
0302:
0303:            /**
0304:             * Set the DataSource to be used by the Scheduler <i>for non-transactional access</i>.
0305:             * <p>This is only necessary if the default DataSource is an XA DataSource that will
0306:             * always participate in transactions: A non-XA version of that DataSource should
0307:             * be specified as "nonTransactionalDataSource" in such a scenario.
0308:             * <p>This is not relevant with a local DataSource instance and Spring transactions.
0309:             * Specifying a single default DataSource as "dataSource" is sufficient there.
0310:             * @see #setDataSource
0311:             * @see LocalDataSourceJobStore
0312:             */
0313:            public void setNonTransactionalDataSource(
0314:                    DataSource nonTransactionalDataSource) {
0315:                this .nonTransactionalDataSource = nonTransactionalDataSource;
0316:            }
0317:
0318:            /**
0319:             * Set the transaction manager to be used for registering jobs and triggers
0320:             * that are defined by this SchedulerFactoryBean. Default is none; setting
0321:             * this only makes sense when specifying a DataSource for the Scheduler.
0322:             * @see #setDataSource
0323:             */
0324:            public void setTransactionManager(
0325:                    PlatformTransactionManager transactionManager) {
0326:                this .transactionManager = transactionManager;
0327:            }
0328:
0329:            /**
0330:             * Register objects in the Scheduler context via a given Map.
0331:             * These objects will be available to any Job that runs in this Scheduler.
0332:             * <p>Note: When using persistent Jobs whose JobDetail will be kept in the
0333:             * database, do not put Spring-managed beans or an ApplicationContext
0334:             * reference into the JobDataMap but rather into the SchedulerContext.
0335:             * @param schedulerContextAsMap Map with String keys and any objects as
0336:             * values (for example Spring-managed beans)
0337:             * @see JobDetailBean#setJobDataAsMap
0338:             */
0339:            public void setSchedulerContextAsMap(Map schedulerContextAsMap) {
0340:                this .schedulerContextMap = schedulerContextAsMap;
0341:            }
0342:
0343:            public void setApplicationContext(
0344:                    ApplicationContext applicationContext) {
0345:                this .applicationContext = applicationContext;
0346:            }
0347:
0348:            /**
0349:             * Set the key of an ApplicationContext reference to expose in the
0350:             * SchedulerContext, for example "applicationContext". Default is none.
0351:             * Only applicable when running in a Spring ApplicationContext.
0352:             * <p>Note: When using persistent Jobs whose JobDetail will be kept in the
0353:             * database, do not put an ApplicationContext reference into the JobDataMap
0354:             * but rather into the SchedulerContext.
0355:             * <p>In case of a QuartzJobBean, the reference will be applied to the Job
0356:             * instance as bean property. An "applicationContext" attribute will
0357:             * correspond to a "setApplicationContext" method in that scenario.
0358:             * <p>Note that BeanFactory callback interfaces like ApplicationContextAware
0359:             * are not automatically applied to Quartz Job instances, because Quartz
0360:             * itself is reponsible for the lifecycle of its Jobs.
0361:             * @see JobDetailBean#setApplicationContextJobDataKey
0362:             * @see org.springframework.context.ApplicationContext
0363:             */
0364:            public void setApplicationContextSchedulerContextKey(
0365:                    String applicationContextSchedulerContextKey) {
0366:                this .applicationContextSchedulerContextKey = applicationContextSchedulerContextKey;
0367:            }
0368:
0369:            /**
0370:             * Set the Quartz JobFactory to use for this Scheduler.
0371:             * <p>Default is Spring's {@link AdaptableJobFactory}, which supports
0372:             * {@link java.lang.Runnable} objects as well as standard Quartz
0373:             * {@link org.quartz.Job} instances. Note that this default only applies
0374:             * to a <i>local</i> Scheduler, not to a RemoteScheduler (where setting
0375:             * a custom JobFactory is not supported by Quartz).
0376:             * <p>Specify an instance of Spring's {@link SpringBeanJobFactory} here
0377:             * (typically as an inner bean definition) to automatically populate a job's
0378:             * bean properties from the specified job data map and scheduler context.
0379:             * @see AdaptableJobFactory
0380:             * @see SpringBeanJobFactory
0381:             */
0382:            public void setJobFactory(JobFactory jobFactory) {
0383:                this .jobFactory = jobFactory;
0384:                this .jobFactorySet = true;
0385:            }
0386:
0387:            /**
0388:             * Set whether any jobs defined on this SchedulerFactoryBean should overwrite
0389:             * existing job definitions. Default is "false", to not overwrite already
0390:             * registered jobs that have been read in from a persistent job store.
0391:             */
0392:            public void setOverwriteExistingJobs(boolean overwriteExistingJobs) {
0393:                this .overwriteExistingJobs = overwriteExistingJobs;
0394:            }
0395:
0396:            /**
0397:             * Set the location of a Quartz job definition XML file that follows the
0398:             * "job_scheduling_data_1_0" DTD. Can be specified to automatically
0399:             * register jobs that are defined in such a file, possibly in addition
0400:             * to jobs defined directly on this SchedulerFactoryBean.
0401:             * @see ResourceJobSchedulingDataProcessor
0402:             * @see org.quartz.xml.JobSchedulingDataProcessor
0403:             */
0404:            public void setJobSchedulingDataLocation(
0405:                    String jobSchedulingDataLocation) {
0406:                this .jobSchedulingDataLocations = new String[] { jobSchedulingDataLocation };
0407:            }
0408:
0409:            /**
0410:             * Set the locations of Quartz job definition XML files that follow the
0411:             * "job_scheduling_data_1_0" DTD. Can be specified to automatically
0412:             * register jobs that are defined in such files, possibly in addition
0413:             * to jobs defined directly on this SchedulerFactoryBean.
0414:             * @see ResourceJobSchedulingDataProcessor
0415:             * @see org.quartz.xml.JobSchedulingDataProcessor
0416:             */
0417:            public void setJobSchedulingDataLocations(
0418:                    String[] jobSchedulingDataLocations) {
0419:                this .jobSchedulingDataLocations = jobSchedulingDataLocations;
0420:            }
0421:
0422:            /**
0423:             * Register a list of JobDetail objects with the Scheduler that
0424:             * this FactoryBean creates, to be referenced by Triggers.
0425:             * <p>This is not necessary when a Trigger determines the JobDetail
0426:             * itself: In this case, the JobDetail will be implicitly registered
0427:             * in combination with the Trigger.
0428:             * @see #setTriggers
0429:             * @see org.quartz.JobDetail
0430:             * @see JobDetailBean
0431:             * @see JobDetailAwareTrigger
0432:             * @see org.quartz.Trigger#setJobName
0433:             */
0434:            public void setJobDetails(JobDetail[] jobDetails) {
0435:                // Use modifiable ArrayList here, to allow for further adding of
0436:                // JobDetail objects during autodetection of JobDetailAwareTriggers.
0437:                this .jobDetails = new ArrayList(Arrays.asList(jobDetails));
0438:            }
0439:
0440:            /**
0441:             * Register a list of Quartz Calendar objects with the Scheduler
0442:             * that this FactoryBean creates, to be referenced by Triggers.
0443:             * @param calendars Map with calendar names as keys as Calendar
0444:             * objects as values
0445:             * @see org.quartz.Calendar
0446:             * @see org.quartz.Trigger#setCalendarName
0447:             */
0448:            public void setCalendars(Map calendars) {
0449:                this .calendars = calendars;
0450:            }
0451:
0452:            /**
0453:             * Register a list of Trigger objects with the Scheduler that
0454:             * this FactoryBean creates.
0455:             * <p>If the Trigger determines the corresponding JobDetail itself,
0456:             * the job will be automatically registered with the Scheduler.
0457:             * Else, the respective JobDetail needs to be registered via the
0458:             * "jobDetails" property of this FactoryBean.
0459:             * @see #setJobDetails
0460:             * @see org.quartz.JobDetail
0461:             * @see JobDetailAwareTrigger
0462:             * @see CronTriggerBean
0463:             * @see SimpleTriggerBean
0464:             */
0465:            public void setTriggers(Trigger[] triggers) {
0466:                this .triggers = Arrays.asList(triggers);
0467:            }
0468:
0469:            /**
0470:             * Specify Quartz SchedulerListeners to be registered with the Scheduler.
0471:             */
0472:            public void setSchedulerListeners(
0473:                    SchedulerListener[] schedulerListeners) {
0474:                this .schedulerListeners = schedulerListeners;
0475:            }
0476:
0477:            /**
0478:             * Specify global Quartz JobListeners to be registered with the Scheduler.
0479:             * Such JobListeners will apply to all Jobs in the Scheduler.
0480:             */
0481:            public void setGlobalJobListeners(JobListener[] globalJobListeners) {
0482:                this .globalJobListeners = globalJobListeners;
0483:            }
0484:
0485:            /**
0486:             * Specify named Quartz JobListeners to be registered with the Scheduler.
0487:             * Such JobListeners will only apply to Jobs that explicitly activate
0488:             * them via their name.
0489:             * @see org.quartz.JobListener#getName
0490:             * @see org.quartz.JobDetail#addJobListener
0491:             * @see JobDetailBean#setJobListenerNames
0492:             */
0493:            public void setJobListeners(JobListener[] jobListeners) {
0494:                this .jobListeners = jobListeners;
0495:            }
0496:
0497:            /**
0498:             * Specify global Quartz TriggerListeners to be registered with the Scheduler.
0499:             * Such TriggerListeners will apply to all Triggers in the Scheduler.
0500:             */
0501:            public void setGlobalTriggerListeners(
0502:                    TriggerListener[] globalTriggerListeners) {
0503:                this .globalTriggerListeners = globalTriggerListeners;
0504:            }
0505:
0506:            /**
0507:             * Specify named Quartz TriggerListeners to be registered with the Scheduler.
0508:             * Such TriggerListeners will only apply to Triggers that explicitly activate
0509:             * them via their name.
0510:             * @see org.quartz.TriggerListener#getName
0511:             * @see org.quartz.Trigger#addTriggerListener
0512:             * @see CronTriggerBean#setTriggerListenerNames
0513:             * @see SimpleTriggerBean#setTriggerListenerNames
0514:             */
0515:            public void setTriggerListeners(TriggerListener[] triggerListeners) {
0516:                this .triggerListeners = triggerListeners;
0517:            }
0518:
0519:            /**
0520:             * Set whether to automatically start the scheduler after initialization.
0521:             * Default is "true"; set this to "false" to allow for manual startup.
0522:             */
0523:            public void setAutoStartup(boolean autoStartup) {
0524:                this .autoStartup = autoStartup;
0525:            }
0526:
0527:            /**
0528:             * Set the number of seconds to wait after initialization before
0529:             * starting the scheduler asynchronously. Default is 0, meaning
0530:             * immediate synchronous startup on initialization of this bean.
0531:             * <p>Setting this to 10 or 20 seconds makes sense if no jobs
0532:             * should be run before the entire application has started up.
0533:             */
0534:            public void setStartupDelay(int startupDelay) {
0535:                this .startupDelay = startupDelay;
0536:            }
0537:
0538:            /**
0539:             * Set whether to wait for running jobs to complete on shutdown.
0540:             * <p>Default is "false". Switch this to "true" if you prefer
0541:             * fully completed jobs at the expense of a longer shutdown phase.
0542:             * @see org.quartz.Scheduler#shutdown(boolean)
0543:             */
0544:            public void setWaitForJobsToCompleteOnShutdown(
0545:                    boolean waitForJobsToCompleteOnShutdown) {
0546:                this .waitForJobsToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
0547:            }
0548:
0549:            //---------------------------------------------------------------------
0550:            // Implementation of InitializingBean interface
0551:            //---------------------------------------------------------------------
0552:
0553:            public void afterPropertiesSet() throws Exception {
0554:                if (this .dataSource == null
0555:                        && this .nonTransactionalDataSource != null) {
0556:                    this .dataSource = this .nonTransactionalDataSource;
0557:                }
0558:
0559:                // Create SchedulerFactory instance.
0560:                SchedulerFactory schedulerFactory = (SchedulerFactory) BeanUtils
0561:                        .instantiateClass(this .schedulerFactoryClass);
0562:
0563:                initSchedulerFactory(schedulerFactory);
0564:
0565:                if (this .taskExecutor != null) {
0566:                    // Make given TaskExecutor available for SchedulerFactory configuration.
0567:                    configTimeTaskExecutorHolder.set(this .taskExecutor);
0568:                }
0569:                if (this .dataSource != null) {
0570:                    // Make given DataSource available for SchedulerFactory configuration.
0571:                    configTimeDataSourceHolder.set(this .dataSource);
0572:                }
0573:                if (this .nonTransactionalDataSource != null) {
0574:                    // Make given non-transactional DataSource available for SchedulerFactory configuration.
0575:                    configTimeNonTransactionalDataSourceHolder
0576:                            .set(this .nonTransactionalDataSource);
0577:                }
0578:
0579:                // Get Scheduler instance from SchedulerFactory.
0580:                try {
0581:                    this .scheduler = createScheduler(schedulerFactory,
0582:                            this .schedulerName);
0583:                    if (!this .jobFactorySet
0584:                            && !(this .scheduler instanceof  RemoteScheduler)) {
0585:                        // Use AdaptableJobFactory as default for a local Scheduler, unless when
0586:                        // explicitly given a null value through the "jobFactory" bean property.
0587:                        this .jobFactory = new AdaptableJobFactory();
0588:                    }
0589:                    if (this .jobFactory != null) {
0590:                        if (this .jobFactory instanceof  SchedulerContextAware) {
0591:                            ((SchedulerContextAware) this .jobFactory)
0592:                                    .setSchedulerContext(this .scheduler
0593:                                            .getContext());
0594:                        }
0595:                        this .scheduler.setJobFactory(this .jobFactory);
0596:                    }
0597:                }
0598:
0599:                finally {
0600:                    if (this .taskExecutor != null) {
0601:                        configTimeTaskExecutorHolder.set(null);
0602:                    }
0603:                    if (this .dataSource != null) {
0604:                        configTimeDataSourceHolder.set(null);
0605:                    }
0606:                    if (this .nonTransactionalDataSource != null) {
0607:                        configTimeNonTransactionalDataSourceHolder.set(null);
0608:                    }
0609:                }
0610:
0611:                populateSchedulerContext();
0612:
0613:                registerListeners();
0614:
0615:                registerJobsAndTriggers();
0616:
0617:                // Start Scheduler immediately, if demanded.
0618:                if (this .autoStartup) {
0619:                    startScheduler(this .scheduler, this .startupDelay);
0620:                }
0621:            }
0622:
0623:            /**
0624:             * Load and/or apply Quartz properties to the given SchedulerFactory.
0625:             * @param schedulerFactory the SchedulerFactory to initialize
0626:             */
0627:            private void initSchedulerFactory(SchedulerFactory schedulerFactory)
0628:                    throws SchedulerException, IOException {
0629:
0630:                if (this .configLocation != null
0631:                        || this .quartzProperties != null
0632:                        || this .dataSource != null
0633:                        || this .schedulerName != null
0634:                        || this .taskExecutor != null) {
0635:
0636:                    if (!(schedulerFactory instanceof  StdSchedulerFactory)) {
0637:                        throw new IllegalArgumentException(
0638:                                "StdSchedulerFactory required for applying Quartz properties");
0639:                    }
0640:
0641:                    Properties mergedProps = new Properties();
0642:
0643:                    // Set necessary default properties here, as Quartz will not apply
0644:                    // its default configuration when explicitly given properties.
0645:                    if (this .taskExecutor != null) {
0646:                        mergedProps.setProperty(
0647:                                StdSchedulerFactory.PROP_THREAD_POOL_CLASS,
0648:                                LocalTaskExecutorThreadPool.class.getName());
0649:                    } else {
0650:                        mergedProps.setProperty(
0651:                                StdSchedulerFactory.PROP_THREAD_POOL_CLASS,
0652:                                SimpleThreadPool.class.getName());
0653:                        mergedProps.setProperty(PROP_THREAD_COUNT, Integer
0654:                                .toString(DEFAULT_THREAD_COUNT));
0655:                    }
0656:
0657:                    if (this .configLocation != null) {
0658:                        if (logger.isInfoEnabled()) {
0659:                            logger.info("Loading Quartz config from ["
0660:                                    + this .configLocation + "]");
0661:                        }
0662:                        PropertiesLoaderUtils.fillProperties(mergedProps,
0663:                                this .configLocation);
0664:                    }
0665:
0666:                    CollectionUtils.mergePropertiesIntoMap(
0667:                            this .quartzProperties, mergedProps);
0668:
0669:                    if (this .dataSource != null) {
0670:                        mergedProps.put(
0671:                                StdSchedulerFactory.PROP_JOB_STORE_CLASS,
0672:                                LocalDataSourceJobStore.class.getName());
0673:                    }
0674:
0675:                    // Make sure to set the scheduler name as configured in the Spring configuration.
0676:                    if (this .schedulerName != null) {
0677:                        mergedProps.put(
0678:                                StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME,
0679:                                this .schedulerName);
0680:                    }
0681:
0682:                    ((StdSchedulerFactory) schedulerFactory)
0683:                            .initialize(mergedProps);
0684:                }
0685:            }
0686:
0687:            /**
0688:             * Create the Scheduler instance for the given factory and scheduler name.
0689:             * Called by afterPropertiesSet.
0690:             * <p>Default implementation invokes SchedulerFactory's <code>getScheduler</code>
0691:             * method. Can be overridden for custom Scheduler creation.
0692:             * @param schedulerFactory the factory to create the Scheduler with
0693:             * @param schedulerName the name of the scheduler to create
0694:             * @return the Scheduler instance
0695:             * @throws SchedulerException if thrown by Quartz methods
0696:             * @see #afterPropertiesSet
0697:             * @see org.quartz.SchedulerFactory#getScheduler
0698:             */
0699:            protected Scheduler createScheduler(
0700:                    SchedulerFactory schedulerFactory, String schedulerName)
0701:                    throws SchedulerException {
0702:
0703:                // StdSchedulerFactory's default "getScheduler" implementation
0704:                // uses the scheduler name specified in the Quartz properties,
0705:                // which we have set before (in "initSchedulerFactory").
0706:                return schedulerFactory.getScheduler();
0707:            }
0708:
0709:            /**
0710:             * Expose the specified context attributes and/or the current
0711:             * ApplicationContext in the Quartz SchedulerContext.
0712:             */
0713:            private void populateSchedulerContext() throws SchedulerException {
0714:                // Put specified objects into Scheduler context.
0715:                if (this .schedulerContextMap != null) {
0716:                    this .scheduler.getContext()
0717:                            .putAll(this .schedulerContextMap);
0718:                }
0719:
0720:                // Register ApplicationContext in Scheduler context.
0721:                if (this .applicationContextSchedulerContextKey != null) {
0722:                    if (this .applicationContext == null) {
0723:                        throw new IllegalStateException(
0724:                                "SchedulerFactoryBean needs to be set up in an ApplicationContext "
0725:                                        + "to be able to handle an 'applicationContextSchedulerContextKey'");
0726:                    }
0727:                    this .scheduler.getContext().put(
0728:                            this .applicationContextSchedulerContextKey,
0729:                            this .applicationContext);
0730:                }
0731:            }
0732:
0733:            /**
0734:             * Register all specified listeners with the Scheduler.
0735:             */
0736:            private void registerListeners() throws SchedulerException {
0737:                if (this .schedulerListeners != null) {
0738:                    for (int i = 0; i < this .schedulerListeners.length; i++) {
0739:                        this .scheduler
0740:                                .addSchedulerListener(this .schedulerListeners[i]);
0741:                    }
0742:                }
0743:                if (this .globalJobListeners != null) {
0744:                    for (int i = 0; i < this .globalJobListeners.length; i++) {
0745:                        this .scheduler
0746:                                .addGlobalJobListener(this .globalJobListeners[i]);
0747:                    }
0748:                }
0749:                if (this .jobListeners != null) {
0750:                    for (int i = 0; i < this .jobListeners.length; i++) {
0751:                        this .scheduler.addJobListener(this .jobListeners[i]);
0752:                    }
0753:                }
0754:                if (this .globalTriggerListeners != null) {
0755:                    for (int i = 0; i < this .globalTriggerListeners.length; i++) {
0756:                        this .scheduler
0757:                                .addGlobalTriggerListener(this .globalTriggerListeners[i]);
0758:                    }
0759:                }
0760:                if (this .triggerListeners != null) {
0761:                    for (int i = 0; i < this .triggerListeners.length; i++) {
0762:                        this .scheduler
0763:                                .addTriggerListener(this .triggerListeners[i]);
0764:                    }
0765:                }
0766:            }
0767:
0768:            /**
0769:             * Register jobs and triggers (within a transaction, if possible).
0770:             */
0771:            private void registerJobsAndTriggers() throws SchedulerException {
0772:                TransactionStatus transactionStatus = null;
0773:                if (this .transactionManager != null) {
0774:                    transactionStatus = this .transactionManager
0775:                            .getTransaction(new DefaultTransactionDefinition());
0776:                }
0777:                try {
0778:
0779:                    if (this .jobSchedulingDataLocations != null) {
0780:                        ResourceJobSchedulingDataProcessor dataProcessor = new ResourceJobSchedulingDataProcessor();
0781:                        if (this .applicationContext != null) {
0782:                            dataProcessor
0783:                                    .setResourceLoader(this .applicationContext);
0784:                        }
0785:                        for (int i = 0; i < this .jobSchedulingDataLocations.length; i++) {
0786:                            dataProcessor.processFileAndScheduleJobs(
0787:                                    this .jobSchedulingDataLocations[i],
0788:                                    this .scheduler, this .overwriteExistingJobs);
0789:                        }
0790:                    }
0791:
0792:                    // Register JobDetails.
0793:                    if (this .jobDetails != null) {
0794:                        for (Iterator it = this .jobDetails.iterator(); it
0795:                                .hasNext();) {
0796:                            JobDetail jobDetail = (JobDetail) it.next();
0797:                            addJobToScheduler(jobDetail);
0798:                        }
0799:                    } else {
0800:                        // Create empty list for easier checks when registering triggers.
0801:                        this .jobDetails = new LinkedList();
0802:                    }
0803:
0804:                    // Register Calendars.
0805:                    if (this .calendars != null) {
0806:                        for (Iterator it = this .calendars.keySet().iterator(); it
0807:                                .hasNext();) {
0808:                            String calendarName = (String) it.next();
0809:                            Calendar calendar = (Calendar) this .calendars
0810:                                    .get(calendarName);
0811:                            this .scheduler.addCalendar(calendarName, calendar,
0812:                                    true, true);
0813:                        }
0814:                    }
0815:
0816:                    // Register Triggers.
0817:                    if (this .triggers != null) {
0818:                        for (Iterator it = this .triggers.iterator(); it
0819:                                .hasNext();) {
0820:                            Trigger trigger = (Trigger) it.next();
0821:                            addTriggerToScheduler(trigger);
0822:                        }
0823:                    }
0824:                }
0825:
0826:                catch (Throwable ex) {
0827:                    if (transactionStatus != null) {
0828:                        try {
0829:                            this .transactionManager.rollback(transactionStatus);
0830:                        } catch (TransactionException tex) {
0831:                            logger
0832:                                    .error(
0833:                                            "Job registration exception overridden by rollback exception",
0834:                                            ex);
0835:                            throw tex;
0836:                        }
0837:                    }
0838:                    if (ex instanceof  SchedulerException) {
0839:                        throw (SchedulerException) ex;
0840:                    }
0841:                    if (ex instanceof  Exception) {
0842:                        throw new SchedulerException(
0843:                                "Registration of jobs and triggers failed: "
0844:                                        + ex.getMessage(), (Exception) ex);
0845:                    }
0846:                    throw new SchedulerException(
0847:                            "Registration of jobs and triggers failed: "
0848:                                    + ex.getMessage());
0849:                }
0850:
0851:                if (transactionStatus != null) {
0852:                    this .transactionManager.commit(transactionStatus);
0853:                }
0854:            }
0855:
0856:            /**
0857:             * Add the given job to the Scheduler, if it doesn't already exist.
0858:             * Overwrites the job in any case if "overwriteExistingJobs" is set.
0859:             * @param jobDetail the job to add
0860:             * @return <code>true</code> if the job was actually added,
0861:             * <code>false</code> if it already existed before
0862:             * @see #setOverwriteExistingJobs
0863:             */
0864:            private boolean addJobToScheduler(JobDetail jobDetail)
0865:                    throws SchedulerException {
0866:                if (this .overwriteExistingJobs
0867:                        || this .scheduler.getJobDetail(jobDetail.getName(),
0868:                                jobDetail.getGroup()) == null) {
0869:                    this .scheduler.addJob(jobDetail, true);
0870:                    return true;
0871:                } else {
0872:                    return false;
0873:                }
0874:            }
0875:
0876:            /**
0877:             * Add the given trigger to the Scheduler, if it doesn't already exist.
0878:             * Overwrites the trigger in any case if "overwriteExistingJobs" is set.
0879:             * @param trigger the trigger to add
0880:             * @return <code>true</code> if the trigger was actually added,
0881:             * <code>false</code> if it already existed before
0882:             * @see #setOverwriteExistingJobs
0883:             */
0884:            private boolean addTriggerToScheduler(Trigger trigger)
0885:                    throws SchedulerException {
0886:                boolean triggerExists = (this .scheduler.getTrigger(trigger
0887:                        .getName(), trigger.getGroup()) != null);
0888:                if (!triggerExists || this .overwriteExistingJobs) {
0889:                    // Check if the Trigger is aware of an associated JobDetail.
0890:                    if (trigger instanceof  JobDetailAwareTrigger) {
0891:                        JobDetail jobDetail = ((JobDetailAwareTrigger) trigger)
0892:                                .getJobDetail();
0893:                        // Automatically register the JobDetail too.
0894:                        if (!this .jobDetails.contains(jobDetail)
0895:                                && addJobToScheduler(jobDetail)) {
0896:                            this .jobDetails.add(jobDetail);
0897:                        }
0898:                    }
0899:                    if (!triggerExists) {
0900:                        try {
0901:                            this .scheduler.scheduleJob(trigger);
0902:                        } catch (ObjectAlreadyExistsException ex) {
0903:                            if (logger.isDebugEnabled()) {
0904:                                logger
0905:                                        .debug("Unexpectedly found existing trigger, assumably due to cluster race condition: "
0906:                                                + ex.getMessage()
0907:                                                + " - can safely be ignored");
0908:                            }
0909:                            if (this .overwriteExistingJobs) {
0910:                                this .scheduler.rescheduleJob(trigger.getName(),
0911:                                        trigger.getGroup(), trigger);
0912:                            }
0913:                        }
0914:                    } else {
0915:                        this .scheduler.rescheduleJob(trigger.getName(), trigger
0916:                                .getGroup(), trigger);
0917:                    }
0918:                    return true;
0919:                } else {
0920:                    return false;
0921:                }
0922:            }
0923:
0924:            /**
0925:             * Start the Quartz Scheduler, respecting the "startupDelay" setting.
0926:             * @param scheduler the Scheduler to start
0927:             * @param startupDelay the number of seconds to wait before starting
0928:             * the Scheduler asynchronously
0929:             */
0930:            protected void startScheduler(final Scheduler scheduler,
0931:                    final int startupDelay) throws SchedulerException {
0932:                if (startupDelay <= 0) {
0933:                    logger.info("Starting Quartz Scheduler now");
0934:                    scheduler.start();
0935:                } else {
0936:                    if (logger.isInfoEnabled()) {
0937:                        logger.info("Will start Quartz Scheduler ["
0938:                                + scheduler.getSchedulerName() + "] in "
0939:                                + startupDelay + " seconds");
0940:                    }
0941:                    Thread schedulerThread = new Thread() {
0942:                        public void run() {
0943:                            try {
0944:                                Thread.sleep(startupDelay * 1000);
0945:                            } catch (InterruptedException ex) {
0946:                                // simply proceed
0947:                            }
0948:                            if (logger.isInfoEnabled()) {
0949:                                logger
0950:                                        .info("Starting Quartz Scheduler now, after delay of "
0951:                                                + startupDelay + " seconds");
0952:                            }
0953:                            try {
0954:                                scheduler.start();
0955:                            } catch (SchedulerException ex) {
0956:                                throw new SchedulingException(
0957:                                        "Could not start Quartz Scheduler after delay",
0958:                                        ex);
0959:                            }
0960:                        }
0961:                    };
0962:                    schedulerThread.setName("Quartz Scheduler ["
0963:                            + scheduler.getSchedulerName() + "]");
0964:                    schedulerThread.start();
0965:                }
0966:            }
0967:
0968:            //---------------------------------------------------------------------
0969:            // Implementation of FactoryBean interface
0970:            //---------------------------------------------------------------------
0971:
0972:            public Object getObject() {
0973:                return this .scheduler;
0974:            }
0975:
0976:            public Class getObjectType() {
0977:                return (this .scheduler != null) ? this .scheduler.getClass()
0978:                        : Scheduler.class;
0979:            }
0980:
0981:            public boolean isSingleton() {
0982:                return true;
0983:            }
0984:
0985:            //---------------------------------------------------------------------
0986:            // Implementation of Lifecycle interface
0987:            //---------------------------------------------------------------------
0988:
0989:            public void start() throws SchedulingException {
0990:                if (this .scheduler != null) {
0991:                    try {
0992:                        this .scheduler.start();
0993:                    } catch (SchedulerException ex) {
0994:                        throw new SchedulingException(
0995:                                "Could not start Quartz Scheduler", ex);
0996:                    }
0997:                }
0998:            }
0999:
1000:            public void stop() throws SchedulingException {
1001:                if (this .scheduler != null) {
1002:                    try {
1003:                        this .scheduler.standby();
1004:                    } catch (SchedulerException ex) {
1005:                        throw new SchedulingException(
1006:                                "Could not stop Quartz Scheduler", ex);
1007:                    }
1008:                }
1009:            }
1010:
1011:            public boolean isRunning() throws SchedulingException {
1012:                if (this .scheduler != null) {
1013:                    try {
1014:                        return !this .scheduler.isInStandbyMode();
1015:                    } catch (SchedulerException ex) {
1016:                        return false;
1017:                    }
1018:                }
1019:                return false;
1020:            }
1021:
1022:            //---------------------------------------------------------------------
1023:            // Implementation of DisposableBean interface
1024:            //---------------------------------------------------------------------
1025:
1026:            /**
1027:             * Shut down the Quartz scheduler on bean factory shutdown,
1028:             * stopping all scheduled jobs.
1029:             */
1030:            public void destroy() throws SchedulerException {
1031:                logger.info("Shutting down Quartz Scheduler");
1032:                this.scheduler.shutdown(this.waitForJobsToCompleteOnShutdown);
1033:            }
1034:
1035:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.