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