001    /**
002     * Copyright 2005-2012 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.ksb.messaging.quartz;
017    
018    import org.kuali.rice.core.api.config.ConfigurationException;
019    import org.kuali.rice.core.api.config.property.ConfigContext;
020    import org.kuali.rice.ksb.service.KSBServiceLocator;
021    import org.kuali.rice.ksb.util.KSBConstants;
022    import org.quartz.Scheduler;
023    import org.quartz.SchedulerException;
024    import org.quartz.SchedulerFactory;
025    import org.springframework.scheduling.quartz.SchedulerFactoryBean;
026    import org.springframework.transaction.PlatformTransactionManager;
027    
028    import javax.sql.DataSource;
029    import javax.transaction.TransactionManager;
030    
031    /**
032     * An implementation of the Quartz SchedulerFactoryBean which uses a database-backed quartz if the useQuartzDatabase property
033     * is set.
034     * 
035     * @author Kuali Rice Team (rice.collab@kuali.org)
036     */
037    public class KSBSchedulerFactoryBean extends SchedulerFactoryBean {
038    
039        private PlatformTransactionManager jtaTransactionManager;
040        private TransactionManager transactionManager;
041        private DataSource dataSource;
042        private DataSource nonTransactionalDataSource;
043        private boolean transactionManagerSet = false;
044        private boolean nonTransactionalDataSourceSet = false;
045        private boolean nonTransactionalDataSourceNull = true;
046        private boolean dataSourceSet = false;
047        private boolean schedulerInjected = false;
048        
049        @Override
050        protected Scheduler createScheduler(SchedulerFactory schedulerFactory, String schedulerName) throws SchedulerException {
051            if (ConfigContext.getCurrentContextConfig().getObject(KSBConstants.Config.INJECTED_EXCEPTION_MESSAGE_SCHEDULER_KEY) != null) {
052                try {
053                        schedulerInjected = true;
054                    Scheduler scheduler = (Scheduler) ConfigContext.getCurrentContextConfig().getObject(KSBConstants.Config.INJECTED_EXCEPTION_MESSAGE_SCHEDULER_KEY);
055                    scheduler.addJobListener(new MessageServiceExecutorJobListener());
056                    return scheduler;
057                } catch (Exception e) {
058                    throw new ConfigurationException(e);
059                }
060            }
061            return super.createScheduler(schedulerFactory, schedulerName);
062        }
063    
064        @Override
065        public void afterPropertiesSet() throws Exception {
066    
067            boolean useQuartzDatabase = new Boolean(ConfigContext.getCurrentContextConfig().getProperty(KSBConstants.Config.USE_QUARTZ_DATABASE));
068            if (useQuartzDatabase && !schedulerInjected) {
069                // require a transaction manager
070                if (jtaTransactionManager == null) {
071                    throw new ConfigurationException("No jta transaction manager was configured for the KSB Quartz Scheduler");
072                }
073                setTransactionManager(jtaTransactionManager);
074                if (!nonTransactionalDataSourceSet) {
075                    // since transaction manager is required... require a non transactional datasource
076                    nonTransactionalDataSource = KSBServiceLocator.getMessageNonTransactionalDataSource();
077                    if (nonTransactionalDataSource == null) {
078                            throw new ConfigurationException("No non-transactional data source was found but is required for the KSB Quartz Scheduler");
079                    }
080                    super.setNonTransactionalDataSource(nonTransactionalDataSource);
081                }
082                if (!dataSourceSet) {
083                    dataSource = KSBServiceLocator.getMessageDataSource();
084                }
085                super.setDataSource(dataSource);
086                if (transactionManagerSet && nonTransactionalDataSourceNull) {
087                    throw new ConfigurationException("A valid transaction manager was set but no non-transactional data source was found");
088                }
089            }
090            super.afterPropertiesSet();
091        }
092        
093        /**
094         * This overridden method is used simply to keep track of whether the transactionManager property has been set
095         * 
096         * @see org.springframework.scheduling.quartz.SchedulerFactoryBean#setTransactionManager(org.springframework.transaction.PlatformTransactionManager)
097         */
098        @Override
099        public void setTransactionManager(PlatformTransactionManager jtaTransactionManager) {
100            transactionManagerSet = jtaTransactionManager != null;
101            this.jtaTransactionManager = jtaTransactionManager;
102        }
103        
104        /**
105         * This overridden method is used to keep track of whether the non transactional data source is null
106         * 
107         * @see org.springframework.scheduling.quartz.SchedulerFactoryBean#setNonTransactionalDataSource(javax.sql.DataSource)
108         */
109        @Override
110        public void setNonTransactionalDataSource(DataSource nonTransactionalDataSource) {
111            nonTransactionalDataSourceSet = true;
112            nonTransactionalDataSourceNull = (nonTransactionalDataSource == null);
113            this.nonTransactionalDataSource = nonTransactionalDataSource;
114        }
115        
116        @Override
117        public void setDataSource(DataSource dataSource) {
118            dataSourceSet = true;
119            this.dataSource = dataSource;
120        }
121    }