वसंत में एक क्वार्ट्ज नौकरी में बीन संदर्भ इंजेक्षन?


94

मैं स्प्रिंग में JobStoreTX लगातार स्टोर का उपयोग करके एक क्वार्ट्ज नौकरी को कॉन्फ़िगर और शेड्यूल करने में कामयाब रहा। मैं स्प्रिंग के क्वार्ट्ज नौकरियों का उपयोग नहीं करता हूं, क्योंकि मुझे उन्हें गतिशील रूप से समय पर चलाने की आवश्यकता है, और क्वार्ट्ज के साथ स्प्रिंग को एकीकृत करने के सभी उदाहरण हैं जो मुझे मिला कि वसंत कॉन्फ़िगरेशन फ़ाइलों में श्रेड्यूल्स को हार्ड-कोडिंग किया गया था ... वैसे भी, यहां बताया गया है कि कैसे मैं नौकरी अनुसूची:

JobDetail emailJob = JobBuilder.newJob(EMailJob.class)
.withIdentity("someJobKey", "immediateEmailsGroup")
.storeDurably()
.build();

SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger() 
.withIdentity("someTriggerKey", "immediateEmailsGroup")
.startAt(fireTime)
.build();

// pass initialization parameters into the job
emailJob.getJobDataMap().put(NotificationConstants.MESSAGE_PARAMETERS_KEY,       messageParameters);
emailJob.getJobDataMap().put(NotificationConstants.RECIPIENT_KEY, recipient);

if (!scheduler.checkExists(jobKey) && scheduler.getTrigger(triggerKey) != null)     {                                       
// schedule the job to run
Date scheduleTime1 = scheduler.scheduleJob(emailJob, trigger);
}

EMailJob एक सरल काम है जो स्प्रिंग के JavaMailSenderImpl वर्ग का उपयोग करके ई-मेल भेज रहा है।

public class EMailJob implements Job {
@Autowired
private JavaMailSenderImpl mailSenderImpl;

    public EMailJob() {
    }
    public void execute(JobExecutionContext context)
       throws JobExecutionException {
   ....
    try {
        mailSenderImpl.send(mimeMessage);
    } catch (MessagingException e) {
        ....
        throw new JobExecutionException("EMailJob failed: " +  jobKey.getName(), e);
    }

    logger.info("EMailJob finished OK");

}

समस्या यह है कि मुझे अपने EMailJD कक्षा में इस वर्ग (JavaMailSenderImpl) के उदाहरण का संदर्भ लेने की आवश्यकता है। जब मैं इसे इस तरह इंजेक्ट करने की कोशिश करता हूं:

@Autowired
private JavaMailSenderImpl mailSenderImpl;

यह इंजेक्शन नहीं है - संदर्भ NULL है। मुझे लगता है कि यह हो रहा है क्योंकि यह स्प्रिंग नहीं है जो इमेलजोब वर्ग को तात्कालिक करता है, लेकिन क्वार्ट्ज, और क्वार्ट्ज निर्भरता इंजेक्शन के बारे में कुछ भी नहीं जानता है ...

तो, क्या इस इंजेक्शन को होने के लिए मजबूर करने का कोई तरीका है?

धन्यवाद!

अद्यतन 1: @Aaron: यहाँ स्टार्टअप से स्टैकट्रेस का एक प्रासंगिक हिस्सा है, जो दिखा रहा है कि EMailJob को दो बार त्वरित किया गया था:

2011-08-15 14:16:38,687 [main] INFO     org.springframework.context.support.GenericApplicationContext - Bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler#0' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2011-08-15 14:16:38,734 [main] INFO  org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1328c7a: defining beans [...]; root of factory hierarchy
2011-08-15 14:16:39,734 [main] INFO  com.cambridgedata.notifications.EMailJob - EMailJob() -  initializing ...
2011-08-15 14:16:39,937 [main] INFO  org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor -   Validated configuration attributes
2011-08-15 14:16:40,078 [main] INFO  org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Validated configuration attributes
2011-08-15 14:16:40,296 [main] INFO  org.springframework.jdbc.datasource.init.ResourceDatabasePopulator - Executing SQL script from class path resource ...
2011-08-15 14:17:14,031 [main] INFO  com.mchange.v2.log.MLog - MLog clients using log4j logging.
2011-08-15 14:17:14,109 [main] INFO  com.mchange.v2.c3p0.C3P0Registry - Initializing c3p0-0.9.1.1 [built 15-March-2007 01:32:31; debug? true; trace: 10]
2011-08-15 14:17:14,171 [main] INFO  org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2011-08-15 14:17:14,171 [main] INFO  org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.0.1 created.
2011-08-15 14:17:14,187 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - Using thread monitor-based data access locking (synchronization).
2011-08-15 14:17:14,187 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - JobStoreTX initialized.
2011-08-15 14:17:14,187 [main] INFO  org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.0.1) 'NotificationsScheduler' with instanceId  'NON_CLUSTERED'
 Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
   NOT STARTED.
 Currently in standby mode.
 Number of jobs executed: 0
 Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 3 threads.
 Using job-store 'org.quartz.impl.jdbcjobstore.JobStoreTX' - which supports persistence. and is not clustered.

2011-08-15 14:17:14,187 [main] INFO  org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'NotificationsScheduler' initialized from the specified file : 'spring/quartz.properties' from the class resource path.
2011-08-15 14:17:14,187 [main] INFO  org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.0.1
2011-08-15 14:17:14,234 [main] INFO  com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 2sajb28h1lcabf28k3nr1|13af084, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 2sajb28h1lcabf28k3nr1|13af084, idleConnectionTestPeriod -> 50, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/2010rewrite2, lastAcquisitionFailureDefaultUser -> null, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 5, maxStatements -> 0, maxStatementsPerConnection -> 120, minPoolSize -> 1, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> select 0 from dual, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> true, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
2011-08-15 14:17:14,312 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - Freed 0 triggers from 'acquired' / 'blocked' state.
2011-08-15 14:17:14,328 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - Recovering 0 jobs that were in-progress at the time of the last shut-down.
2011-08-15 14:17:14,328 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - Recovery complete.
2011-08-15 14:17:14,328 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - Removed 0 'complete' triggers.
2011-08-15 14:17:14,328 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - Removed 0 stale fired job entries.
2011-08-15 14:17:14,328 [main] INFO  org.quartz.core.QuartzScheduler - Scheduler NotificationsScheduler_$_NON_CLUSTERED started.
2011-08-15 14:17:14,515 [NotificationsScheduler_QuartzSchedulerThread] INFO  com.cambridgedata.notifications.EMailJob - EMailJob() -  initializing ...

धन्यवाद!

अपडेट # 2: @Ryan:

मैंने निम्नलिखित के रूप में SpringBeanJobFactory का उपयोग करने की कोशिश की:

    <bean id="jobFactoryBean" class="org.springframework.scheduling.quartz.SpringBeanJobFactory">
</bean>

<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="configLocation" value="classpath:spring/quartz.properties"/>
        <property name="jobFactory" ref="jobFactoryBean"/>
</bean>

और मैंने क्वार्टर के बजाय इस कारखाने से शेड्यूलर प्राप्त करने के लिए अपने मुख्य वर्ग को संशोधित किया है: '

    @PostConstruct
public void initNotificationScheduler() {
    try {
        //sf = new StdSchedulerFactory("spring/quartz.properties");
        //scheduler = sf.getScheduler();

        scheduler = schedulerFactoryBean.getScheduler();
        scheduler.start();
            ....

लेकिन जब मैं एप्लिकेशन चलाता हूं - त्रुटियां मिलती हैं, तो नीचे देखें। यहाँ स्प्रिंग स्टार्टअप से स्टैकट्रेस है। शेड्यूलर की तरह ही लगता है कि ठीक बनाया गया है, लेकिन त्रुटि तब आती है जब यह मेरे EMailJob को तुरंत करने की कोशिश कर रहा है:

2011-08-15 21:49:42,968 [main] INFO  org.springframework.scheduling.quartz.SchedulerFactoryBean - Loading Quartz config from [class path resource [spring/quartz.properties]]
2011-08-15 21:49:43,031 [main] INFO  com.mchange.v2.log.MLog - MLog clients using log4j logging.
2011-08-15 21:49:43,109 [main] INFO  com.mchange.v2.c3p0.C3P0Registry - Initializing c3p0-0.9.1.1 [built 15-March-2007 01:32:31; debug? true; trace: 10]
2011-08-15 21:49:43,187 [main] INFO  org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2011-08-15 21:49:43,187 [main] INFO  org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.0.1 created.
2011-08-15 21:49:43,187 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - Using thread monitor-based data access locking (synchronization).
2011-08-15 21:49:43,187 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - JobStoreTX initialized.
2011-08-15 21:49:43,187 [main] INFO  org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.0.1) 'schedulerFactoryBean' with instanceId 'NON_CLUSTERED'
 Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
 NOT STARTED.
 Currently in standby mode.
 Number of jobs executed: 0
 Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 3 threads.
 Using job-store 'org.quartz.impl.jdbcjobstore.JobStoreTX' - which supports persistence. and is not clustered.

2011-08-15 21:49:43,187 [main] INFO  org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'schedulerFactoryBean' initialized from an externally provided properties instance.
2011-08-15 21:49:43,187 [main] INFO  org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.0.1
2011-08-15 21:49:43,187 [main] INFO  org.quartz.core.QuartzScheduler - JobFactory set to: org.springframework.scheduling.quartz.SpringBeanJobFactory@566633
2011-08-15 21:49:43,265 [main] INFO  com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hge13f8h1lsg7py1rg0iu0|1956391, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1hge13f8h1lsg7py1rg0iu0|1956391, idleConnectionTestPeriod -> 50, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/2010rewrite2, lastAcquisitionFailureDefaultUser -> null, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 5, maxStatements -> 0, maxStatementsPerConnection -> 120, minPoolSize -> 1, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> select 0 from dual, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> true, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
2011-08-15 21:49:43,343 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - Freed 0 triggers from 'acquired' / 'blocked' state.
2011-08-15 21:49:43,359 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - Recovering 0 jobs that were in-progress at the time of the last shut-down.
2011-08-15 21:49:43,359 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - Recovery complete.
2011-08-15 21:49:43,359 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - Removed 0 'complete' triggers.
2011-08-15 21:49:43,359 [main] INFO  org.quartz.impl.jdbcjobstore.JobStoreTX - Removed 0 stale fired job entries.
2011-08-15 21:49:43,359 [main] INFO  org.quartz.core.QuartzScheduler - Scheduler schedulerFactoryBean_$_NON_CLUSTERED started.
2011-08-15 21:49:43,562 [schedulerFactoryBean_QuartzSchedulerThread] ERROR org.quartz.core.ErrorLogger - An error occured instantiating job to be executed. job= 'immediateEmailsGroup.DEFAULT.jobFor_1000new1'
org.quartz.SchedulerException: Problem instantiating class  'com.cambridgedata.notifications.EMailJob' -  [See nested exception:  java.lang.AbstractMethodError:  org.springframework.scheduling.quartz.SpringBeanJobFactory.newJob(Lorg/quartz/spi/TriggerFiredBundle;Lorg/quartz/Scheduler;)Lorg/quartz/Job;]
at org.quartz.core.JobRunShell.initialize(JobRunShell.java:141)
at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:381)
Caused by: java.lang.AbstractMethodError: org.springframework.scheduling.quartz.SpringBeanJobFactory.newJob(Lorg/quartz/spi/TriggerFiredBundle;Lorg/quartz/Scheduler;)Lorg/quartz/Job;
at org.quartz.core.JobRunShell.initialize(JobRunShell.java:134)

धन्यवाद!

जवाबों:


129

आप इसे SpringBeanJobFactoryस्वचालित रूप से स्प्रिंग का उपयोग करके क्वार्ट्ज ऑब्जेक्ट को स्वतः प्राप्त करने के लिए उपयोग कर सकते हैं :

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements
    ApplicationContextAware {

    private transient AutowireCapableBeanFactory beanFactory;

    @Override
    public void setApplicationContext(final ApplicationContext context) {
        beanFactory = context.getAutowireCapableBeanFactory();
    }

    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        final Object job = super.createJobInstance(bundle);
        beanFactory.autowireBean(job);
        return job;
    }
}

फिर, इसे अपने साथ संलग्न करें SchedulerBean(इस मामले में, Java-config के साथ):

@Bean
public SchedulerFactoryBean quartzScheduler() {
    SchedulerFactoryBean quartzScheduler = new SchedulerFactoryBean();

    ...

    AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
    jobFactory.setApplicationContext(applicationContext);
    quartzScheduler.setJobFactory(jobFactory);

    ...

    return quartzScheduler;
}

मेरे लिए काम करना, वसंत-3.2.1 और क्वार्ट्ज-2.1.6 का उपयोग करना।

यहां पूरी तरह से देखें ।

मुझे इस ब्लॉग पोस्ट में समाधान मिला


13
आपको इसके लिए एक पुरस्कार जीतना चाहिए, यह शानदार है!
नाथन फ़ेगर

2
समाधान यह वास्तव में बहुत अच्छा है! ब्लॉग पोस्ट के लेखक को सभी श्रेय :)
jelies

3
धन्यवाद - यह मुझे दिन बचा लिया! वसंत ने इस OOB को क्यों नहीं प्रदान किया। वसंत में क्वार्ट्ज का उपयोग करने के लिए यह बहुत बुनियादी आवश्यकता है।
हैंडीमैनडान

4
यह डिफॉल्ट
इम्प्लीमेंटेशन

2
महान समाधान, लेकिन किसी को भी पता नहीं क्यों AutowireCapableBeanFactory beanFactory "क्षणिक" के रूप में चिह्नित है? AutowiringSpringBeanJobFactory को वैसे भी क्रमबद्ध नहीं लगता है, इसलिए न तो बीनफैक्ट्री को कभी भी धारावाहिक बनाने की आवश्यकता नहीं होगी
Marios

57

मैंने SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);अपनी Job.execute(JobExecutionContext context)विधि की पहली पंक्ति के रूप में रखा ।


7
यही वास्तविक समाधान है। स्प्रिंग 3.2.4 के साथ परीक्षण किया गया। कृपया और क्वार्ट्ज 2.2.0। ;)
अलोपोप्लोप85

3
@msangel - ठीक है, दोनों काम करेंगे, लेकिन आपके क्वार्ट्ज नौकरी में स्प्रिंगबैनअटाउटरिंगसुपोर्ट का उपयोग करने के साथ समस्या यह है कि जॉब इंस्टेंस को अब स्प्रिंग के बारे में पता होना चाहिए, जो आईओसी (डिप इंजेक्शन) के पूरे विचार के खिलाफ जाता है। यदि आपको अब उदाहरण के लिए सीडीआई का उपयोग करने की आवश्यकता है, तो आपके सभी क्वार्ट्ज नौकरियों को केवल एक नौकरी कारखाने के बजाय समायोजित करने की आवश्यकता होगी।
दानिक

2
यह मेरे लिए एक इकाई परीक्षण में काम नहीं करता था क्योंकि यह एक वेब अनुप्रयोग संदर्भ के लिए खोज करता है। मुझे @jelies से जवाब का उपयोग करना था
Wim Deblauwe

5
यह समाधान वसंत 4.1.4 और क्वार्ट्ज 2.2.1 के साथ काम नहीं करता है
स्काईवॉकर

1
मुझे भी यह समस्या थी और मैंने इस समाधान की कोशिश की। यह काम कर रहा है लेकिन यह पहले से निर्मित एक (डिफ़ॉल्ट सिंगलटन) का उपयोग करने के बजाय एक नया उदाहरण बनाता है। वैसे भी आप अनुसूचक का उपयोग करके अपनी नौकरी के लिए कुछ भी पारित कर सकते हैं ।gettextxt ()। Put ("objectName", ऑब्जेक्ट);
क्रिज़िस्तोफ़ सेइलीस्की

13

उसी समस्या को लिंक में हल किया गया है :

मुझे स्प्रिंग फ़ोरम पर पोस्ट से अन्य विकल्प मिल सकता है कि आप शेड्यूलर फ़ंक्शंसबैन के माध्यम से स्प्रिंग एप्लिकेशन के संदर्भ को पास कर सकते हैं। नीचे दिखाए गए उदाहरण की तरह:

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<propertyy name="triggers">
    <list>
        <ref bean="simpleTrigger"/>
            </list>
    </property>
    <property name="applicationContextSchedulerContextKey">
        <value>applicationContext</value>
</property>

फिर अपने जॉब क्लास में नीचे दिए गए कोड का उपयोग करके आप एप्लिकेशन कॉन्टेक्स्ट प्राप्त कर सकते हैं और जो भी सेम चाहते हैं वह प्राप्त कर सकते हैं।

appCtx = (ApplicationContext)context.getScheduler().getContext().get("applicationContextSchedulerContextKey");

आशा करता हूँ की ये काम करेगा। आप मार्क म्लेकरन के इंजील से अधिक जानकारी प्राप्त कर सकते हैं


1
धन्यवाद, @ रिपन! बहुत कोशिश और असफल होने के बाद, मैंने एक बहुत ही समान दृष्टिकोण का उपयोग किया है जो आपने सुझाया था: मैंने एप्लिकेशन कॉन्टेक्स्टसॉल्ड्यूलर कॉन्टेक्स्ट की संपत्ति और आवेदन के संदर्भ का उपयोग नहीं किया है, लेकिन मैंने 'कोड' <संपत्ति का नाम = "शेड्यूलरऑनटेक्स्टएप्स"> <मानचित्र> <प्रविष्टि कुंजी = का उपयोग किया है "mailService" value-ref = "mailService" /> </ map> </ संपत्ति>
मरीना

8

आप कक्षा के बारे में स्प्रिंग बनाम क्वार्ट्ज के बारे में अपनी धारणा में सही हैं। हालांकि, वसंत कुछ कक्षाएं प्रदान करता है जो आपको क्वार्ट्ज में कुछ आदिम निर्भरता इंजेक्शन करते हैं। की जाँच करें SchedulerFactoryBean.setJobFactory () के साथ-साथ SpringBeanJobFactory । मूल रूप से, स्प्रिंगबिनजॉबवर्किंग का उपयोग करके, आप सभी नौकरी गुणों पर निर्भरता इंजेक्शन को सक्षम करते हैं, लेकिन केवल उन मूल्यों के लिए जो क्वार्ट्ज शेड्यूलर संदर्भ या नौकरी डेटा मानचित्र में हैं । मुझे नहीं पता कि यह सभी DI शैलियों का समर्थन करता है (निर्माता, एनोटेशन, सेटर ...), लेकिन मुझे पता है कि यह सेटर इंजेक्शन का समर्थन करता है।


हाय, रेयान, आपके सुझाव के लिए धन्यवाद। क्या आपका मतलब है कि मुझे स्प्रिंगबीनफैक्टरीजोब का उपयोग करना होगा, साथ ही पूर्व-कॉन्फ़िगर किए गए ट्रिगर और नौकरियों के साथ जो क्वार्ट्जजॉबियन का विस्तार करते हैं ताकि निर्भरता इंजेक्शन को सक्षम किया जा सके? इस दृष्टिकोण के साथ समस्या यह है कि ट्रिगर्स को स्प्रिंग की कॉन्फिग फाइलों में स्टैटिकली परिभाषित किया जाता है, जहाँ मुझे रनिंग टाइम पर डायनामिक शेड्यूल के साथ ट्रिगर्स को परिभाषित करने में सक्षम होने की आवश्यकता होती है ... अधिक जानकारी के लिए नीचे मेरा अगला उत्तर देखें - पर्याप्त जगह नहीं टिप्पणियाँ क्षेत्र ...
मरीना

@ मरीना: नहीं, यह नहीं है कि यह कैसे काम करता है। SpringBeanJobFactory का उपयोग करें, और इसे जिस तरह से आप करना चाहते हैं, उसे करें। यह सिर्फ काम करेगा। इसके अलावा, एक उत्तर पोस्ट न करें जो आपके प्रश्न के लिए एक अद्यतन है। इसके बजाय अपने प्रश्न को संपादित करें।
रयान स्टीवर्ट

क्षमा करें, मैंने अभी आपकी टिप्पणी पर ध्यान दिया है! जैसा आप सुझाएंगे मैं वैसा ही करने की कोशिश करूंगा और आपको परिणाम बताऊंगा। आपकी मदद के लिए धन्यवाद! ओह, और मैं जवाब देने के बजाय अपने प्रश्न को संपादित करने की कोशिश करूंगा ...
मरीना

7

भविष्य में इसके लिए कौन प्रयास करेगा।

org.springframework.scheduling.quartz.JobDetailBean वस्तुओं के मानचित्र की आपूर्ति करता है और वे वस्तुएं स्प्रिंग बीन्स हो सकती हैं।

की तरह परिभाषित करें

<bean name="myJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
    <property name="jobClass"
        value="my.cool.class.myCoolJob" />
    <property name="jobDataAsMap">
        <map>
            <entry key="myBean" value-ref="myBean" />
        </map>
    </property>
</bean>

और फिर, अंदर

public void executeInternal(JobExecutionContext context)

कॉल करें myBean = (myBean) context.getMergedJobDataMap().get("myBean"); और आप सभी सेट करें। मुझे पता है, यह बदसूरत दिखता है, लेकिन एक वर्कअराउंड के रूप में यह काम करता है


IMHO मैं इस समाधान को क्वार्ट्ज नौकरियों में ऑटोवेयरिंग क्षमता जोड़ने की कोशिश से अधिक स्वच्छ और "प्राकृतिक" महसूस करता हूं, इसलिए मुझे नहीं लगता कि यह एक काम है।
वास्तव में

6
ApplicationContext springContext =

WebApplicationContextUtils.getWebApplicationContext(ContextLoaderListener .getCurrentWebApplicationContext().getServletContext());

Bean bean = (Bean) springContext.getBean("beanName");

bean.method();

4

धन्यवाद, रिपन! मुझे अंततः यह काम मिल गया है, कई संघर्षों के बाद, और मेरा समाधान आपके सुझाव के बहुत करीब है! कुंजी क्वार्ट्जजोबबिन का विस्तार करने के लिए और शेड्यूलरकोटेक्स्टएपस का उपयोग करने के लिए मेरी खुद की नौकरी बनाने के लिए थी।

मैं आवेदन को निर्दिष्ट किए बिना दूर चला गया।

दूसरों के लाभ के लिए, यहाँ अंतिम विन्यास है जो मेरे लिए काम कर रहा है:

    <bean id="quartzScheduler"  class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="configLocation" value="classpath:spring/quartz.properties"/>
        <property name="jobFactory">
            <bean  class="org.springframework.scheduling.quartz.SpringBeanJobFactory" />
        </property>
        <property name="schedulerContextAsMap">
            <map>
                <entry key="mailService" value-ref="mailService" />
            </map>
        </property>
</bean>
<bean id="jobTriggerFactory"
      class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
    <property name="targetBeanName">
        <idref local="jobTrigger" />
    </property>
</bean>
<bean id="jobTrigger"   class="org.springframework.scheduling.quartz.SimpleTriggerBean"
    scope="prototype">
      <property name="group" value="myJobs" />
      <property name="description" value="myDescription" />
      <property name="repeatCount" value="0" />
</bean>

<bean id="jobDetailFactory"
      class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
    <property name="targetBeanName">
        <idref local="jobDetail" />
    </property>
</bean>

<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean"
scope="prototype">
<property name="jobClass" value="com.cambridgedata.notifications.EMailJob" />
<property name="volatility" value="false" />
<property name="durability" value="false" />
<property name="requestsRecovery" value="true" />
</bean> 
<bean id="notificationScheduler"   class="com.cambridgedata.notifications.NotificationScheduler">
    <constructor-arg ref="quartzScheduler" />
    <constructor-arg ref="jobDetailFactory" />
    <constructor-arg ref="jobTriggerFactory" />
</bean>

ध्यान दें कि 'mailService' बीन मेरी अपनी सेवा बीन है, जिसे स्प्रिंग द्वारा प्रबंधित किया गया है।

    public void executeInternal(JobExecutionContext context)
    throws JobExecutionException {

    logger.info("EMailJob started ...");
    ....
    SchedulerContext schedulerContext = null;
    try {
        schedulerContext = context.getScheduler().getContext();
    } catch (SchedulerException e1) {
        e1.printStackTrace();
    }
    MailService mailService = (MailService)schedulerContext.get("mailService");
    ....

और इस विन्यास ने मुझे गतिशील रूप से शेड्यूलर नौकरियों के लिए भी अनुमति दी, ट्रिगर्स और जॉबडेट्स प्राप्त करने के लिए कारखानों का उपयोग करके और उन पर आवश्यक पैरामीटर सेट करने के लिए प्रोग्रामेटिक रूप से:

    public NotificationScheduler(final Scheduler scheduler,
        final ObjectFactory<JobDetail> jobDetailFactory,
        final ObjectFactory<SimpleTrigger> jobTriggerFactory) {
    this.scheduler = scheduler;
    this.jobDetailFactory = jobDetailFactory;
    this.jobTriggerFactory = jobTriggerFactory;
           ...
        // create a trigger
        SimpleTrigger trigger = jobTriggerFactory.getObject();
        trigger.setRepeatInterval(0L);
    trigger.setStartTime(new Date());

    // create job details
    JobDetail emailJob = jobDetailFactory.getObject();

    emailJob.setName("new name");
    emailJob.setGroup("immediateEmailsGroup");
            ...

फिर से मदद करने वाले हर व्यक्ति को बहुत धन्यवाद,

मरीना


4

एक सरल समाधान यह है कि जॉब डेटा मैप में स्प्रिंग बीन सेट करें और फिर उदाहरण के लिए, जॉब क्लास में बीन को पुनः प्राप्त करें

// the class sets the configures the MyJob class 
    SchedulerFactory sf = new StdSchedulerFactory();
    Scheduler sched = sf.getScheduler();
    Date startTime = DateBuilder.nextGivenSecondDate(null, 15);
    JobDetail job = newJob(MyJob.class).withIdentity("job1", "group1").build();
    job.getJobDataMap().put("processDataDAO", processDataDAO);

`

 // this is MyJob Class
    ProcessDataDAO processDataDAO = (ProcessDataDAO) jec.getMergedJobDataMap().get("processDataDAO");

यह देखते हुए कि नौकरी डेटा को ब्लॉब के रूप में संग्रहीत किया जाता है (जब डीबी हठ का उपयोग करते हुए) यह डीबी प्रदर्शन के मुद्दों को जन्म दे सकता है (कल्पना करें कि डेटा वास्तव में बहुत बड़ा है)
सुदीप भंडारी

3

यहाँ @Component के साथ कोड कैसा दिखता है:

मुख्य वर्ग जो काम को निर्धारित करता है:

public class NotificationScheduler {

private SchedulerFactory sf;
private Scheduler scheduler;

@PostConstruct
public void initNotificationScheduler() {
    try {
    sf = new StdSchedulerFactory("spring/quartz.properties");
    scheduler = sf.getScheduler();
    scheduler.start();
            // test out sending a notification at startup, prepare some parameters...
    this.scheduleImmediateNotificationJob(messageParameters, recipients);
        try {
            // wait 20 seconds to show jobs
            logger.info("sleeping...");
            Thread.sleep(40L * 1000L); 
            logger.info("finished sleeping");
           // executing...
        } catch (Exception ignore) {
        }

      } catch (SchedulerException e) {
    e.printStackTrace();
    throw new RuntimeException("NotificationScheduler failed to retrieve a Scheduler instance: ", e);
    }
}


public void scheduleImmediateNotificationJob(){
  try {
    JobKey jobKey = new JobKey("key");
    Date fireTime = DateBuilder.futureDate(delayInSeconds, IntervalUnit.SECOND);
    JobDetail emailJob = JobBuilder.newJob(EMailJob.class)
    .withIdentity(jobKey.toString(), "immediateEmailsGroup")
        .build();

    TriggerKey triggerKey = new TriggerKey("triggerKey");
    SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger() 
        .withIdentity(triggerKey.toString(), "immediateEmailsGroup")
        .startAt(fireTime)
        .build();

    // schedule the job to run
    Date scheduleTime1 = scheduler.scheduleJob(emailJob, trigger);
  } catch (SchedulerException e) {
    logger.error("error scheduling job: " + e.getMessage(), e);
    e.printStackTrace();
      }
}

@PreDestroy
public void cleanup(){
    sf = null;
    try {
        scheduler.shutdown();
    } catch (SchedulerException e) {
        e.printStackTrace();
    }
}

EmailJob मेरी पहली पोस्टिंग में वैसा ही है, जैसे @Component एनोटेशन को छोड़कर:

@Component
public class EMailJob implements Job { 
  @Autowired
  private JavaMailSenderImpl mailSenderImpl;
... }

और स्प्रिंग की कॉन्फ़िगरेशन फ़ाइल में है:

...
<context:property-placeholder location="classpath:spring/*.properties" />
<context:spring-configured/>
<context:component-scan base-package="com.mybasepackage">
  <context:exclude-filter expression="org.springframework.stereotype.Controller"
        type="annotation" />
</context:component-scan>
<bean id="mailSenderImpl" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="host" value="${mail.host}"/>
    <property name="port" value="${mail.port}"/>
    ...
</bean>
<bean id="notificationScheduler" class="com.mybasepackage.notifications.NotificationScheduler">
</bean>

पूरी सहायताके लिए शुक्रिया!

मरीना


जब आपका ऐप शुरू होता है, तो क्या आपको EmailJobइनिशियलाइज़ होता है? चेक करने का एक आसान तरीका यह है कि कंस्ट्रक्टर में एक लॉग लाइन को जोड़ा जाए।
atrain

@ एरॉन: हाँ, मैं करता हूँ - लेकिन जैसा कि मैंने अभी पता लगाया है, इसे दो बार इनिशियलाइज़ किया जा रहा है! एक बार स्वयं स्प्रिंग फ्रेमवर्क द्वारा (और मुझे यकीन है कि इस उदाहरण में मेल सेवा को इंजेक्ट किया गया है ...) और फिर, बाद में, क्वार्ट्ज के बाद ही इनिशियलाइज़ किया गया है - EMailJob को क्वार्ट्ज़ फ्रेमवर्क द्वारा फिर से इनिशियलाइज़ किया जा रहा है - और यह वह है उस सेवा में इंजेक्शन नहीं है ... मैं अपने प्रश्न को संपादित करके स्प्रिंग के स्टार्टअप का एक स्टैक ट्रेस जोड़ने की कोशिश करूंगा, जैसा कि रयान ने सुझाव दिया ...
Marina

2

Mi https://stackoverflow.com/a/37797575/4252764 से एक समाधान बहुत अच्छा काम करता है। यह सरल है, इतने सारे विशेष कारखाने सेम की जरूरत नहीं है, और कई ट्रिगर्स और नौकरियों का समर्थन करते हैं। बस यह जोड़ना चाहूंगा कि क्वार्ट्ज नौकरी को नियमित रूप से स्प्रिंग बीन्स के रूप में लागू विशिष्ट नौकरियों के साथ सामान्य बनाया जा सकता है।

public interface BeanJob {
  void executeBeanJob();
}

public class GenericJob implements Job {

  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    JobDataMap dataMap = context.getMergedJobDataMap();
    ((BeanJob)dataMap.get("beanJob")).executeBeanJob();    
  }

}

@Component
public class RealJob implements BeanJob {
  private SomeService service;

  @Autowired
  public RealJob(SomeService service) {
    this.service = service;
  }

  @Override
  public void executeBeanJob() {
      //do do job with service
  }

}

धन्यवाद। मैंने उस पर भी विचार किया। लेकिन मेरे मामले में, मैं एक पुस्तकालय लिख रहा था जो किसी भी क्वार्ट्ज कार्यान्वयन को अमूर्त करता है। किसी भी ऑब्जेक्ट को पुनः प्राप्त करने के लिए 'कुंजी' नाम को याद रखने के लिए यह आवश्यक है। मैं इसे शुद्ध क्वार्ट्ज तरीके से करने में सक्षम था और बस इसे एक उत्तर के रूप में पोस्ट किया। Pls अपने विचार साझा करें!
कार्तिक आर

2

यह काफी पुरानी पोस्ट है जो अभी भी उपयोगी है। इन दोनों को प्रस्तावित करने वाले सभी समाधानों की स्थिति बहुत कम थी जो सभी के अनुरूप नहीं थे:

  • SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); यह मानता है या इसके लिए एक स्प्रिंग - वेब आधारित परियोजना की आवश्यकता है
  • AutowiringSpringBeanJobFactory पिछले उत्तर में उल्लिखित आधारित दृष्टिकोण बहुत सहायक है, लेकिन यह उत्तर उन लोगों के लिए विशिष्ट है जो शुद्ध वैनिला क्वार्ट्ज एप का उपयोग नहीं करते हैं, बल्कि क्वार्ट्ज के लिए स्प्रिंग के रैपर को भी ऐसा करने के लिए करते हैं।

यदि आप शेड्यूलिंग के लिए शुद्ध क्वार्ट्ज कार्यान्वयन के साथ बने रहना चाहते हैं (क्वार्ट्ज ऑटमायरिंग क्षमताओं के साथ स्प्रिंग), तो मैं इसे निम्नानुसार करने में सक्षम था:

मैं इसे जितना संभव हो सके क्वार्ट्ज करने के लिए देख रहा था और इस तरह थोड़ा हैक मददगार साबित होता है।

 public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory{

    private AutowireCapableBeanFactory beanFactory;

    public AutowiringSpringBeanJobFactory(final ApplicationContext applicationContext){
        beanFactory = applicationContext.getAutowireCapableBeanFactory();
    }

    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        final Object job = super.createJobInstance(bundle);
        beanFactory.autowireBean(job);
        beanFactory.initializeBean(job, job.getClass().getName());
        return job;
    }
}


@Configuration
public class SchedulerConfig {   
    @Autowired private ApplicationContext applicationContext;

    @Bean
    public AutowiringSpringBeanJobFactory getAutowiringSpringBeanJobFactory(){
        return new AutowiringSpringBeanJobFactory(applicationContext);
    }
}


private void initializeAndStartScheduler(final Properties quartzProperties)
            throws SchedulerException {
        //schedulerFactory.initialize(quartzProperties);
        Scheduler quartzScheduler = schedulerFactory.getScheduler();

        //Below one is the key here. Use the spring autowire capable job factory and inject here
        quartzScheduler.setJobFactory(autowiringSpringBeanJobFactory);
        quartzScheduler.start();
    }

quartzScheduler.setJobFactory(autowiringSpringBeanJobFactory);हमें एक नौकरी की आवृत्ति देता है। AutowiringSpringBeanJobFactoryस्पष्ट रूप से लागू होने के बाद से JobFactory, हमने अब एक ऑटो-वियरेबल समाधान सक्षम किया है। उम्मीद है की यह मदद करेगा!


1

ऐसा करने का एक सरल तरीका सिर्फ क्वार्ट्ज जॉब्स को @Componentएनोटेशन के साथ एनोटेट करना होगा , और फिर स्प्रिंग आपके लिए सभी DI जादू करेगा, क्योंकि यह अब स्प्रिंग बीन के रूप में मान्यता प्राप्त है। मुझे एक AspectJपहलू के लिए कुछ ऐसा ही करना था - जब तक मैंने इसे स्प्रिंग @Componentस्टीरियोटाइप के साथ एनोटेट नहीं किया, यह स्प्रिंग बीन नहीं था ।


धन्यवाद, हारून, मैंने बस कोशिश की - लेकिन दुर्भाग्य से वही एनपीई होता है - और मेल सेवा नौकरी बीन में इंजेक्ट नहीं हो रही है ...
मरीना

क्या आपकी EmailJobक्लास एक पैकेज में है जिसे ऐप स्टार्टअप पर स्प्रिंग द्वारा स्कैन किया जाएगा? तथ्य यह है कि आप के साथ एनोटेट @Componentलेकिन इंजेक्शन वर्ग अभी भी अशक्त है इंगित करता है कि इसके स्कैन नहीं किया जा रहा है - अन्यथा एप्लिकेशन स्टार्टअप पर DI एक अपवाद फेंक देंगे।
एट्रेन

हारून: हाँ, इसे स्कैन किया जाना चाहिए - मेरे पास <संदर्भ: घटक-स्कैन बेस-पैकेज = "com.mybasepackage"> जो इसे करना चाहिए ... अपने अगले उत्तर में मैं अपने मुख्य का पूरा कोड प्रदान कर रहा हूं वसंत विन्यास के साथ वर्ग, - बस के मामले में कुछ स्पष्ट देखा जा सकता है ...
मरीना

"@Autowired" के साथ चिह्नित जॉब फील्ड्स इंजेक्ट नहीं हैं, भले ही आप "@Component" के साथ जॉब को चिह्नित करते हों
aloplop85

6
यह काम नहीं करेगा क्योंकि जॉब ऑब्जेक्ट्स बनाने में क्वार्ट्स द्वारा प्रबंधित किया जाता है और इसलिए फ़ील्ड्स को ऑटोवार्ड नहीं किया जाता है और क्लास एनोटेशन अतिरिक्त हैंडलिंग के बिना कुछ भी नहीं करते हैं।
मिसेज़ेल

1

यह सही उत्तर है http://stackoverflow.com/questions/6990767/inject-bean-reference-into-a-quartz-job-in-spring/15211030#15211030 । और अधिकांश लोगों के लिए काम करेगा। लेकिन अगर आपके web.xml को सभी ApplicationContext.xml फ़ाइलों के बारे में पता नहीं है, तो क्वार्ट्ज जॉब उन बीन्स को नहीं दे पाएगा। मुझे अतिरिक्त ApplicationContext फ़ाइलों को इंजेक्ट करने के लिए एक अतिरिक्त परत करनी थी

public class MYSpringBeanJobFactory extends SpringBeanJobFactory
        implements ApplicationContextAware {

    private transient AutowireCapableBeanFactory beanFactory;

    @Override
    public void setApplicationContext(final ApplicationContext context) {

        try {
                PathMatchingResourcePatternResolver pmrl = new PathMatchingResourcePatternResolver(context.getClassLoader());
                Resource[] resources = new Resource[0];
                GenericApplicationContext createdContext = null ;
                    resources = pmrl.getResources(
                            "classpath*:my-abc-integration-applicationContext.xml"
                    );

                    for (Resource r : resources) {
                        createdContext = new GenericApplicationContext(context);
                        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(createdContext);
                        int i = reader.loadBeanDefinitions(r);
                    }

            createdContext.refresh();//important else you will get exceptions.
            beanFactory = createdContext.getAutowireCapableBeanFactory();

        } catch (IOException e) {
            e.printStackTrace();
        }



    }

    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle)
            throws Exception {
        final Object job = super.createJobInstance(bundle);
        beanFactory.autowireBean(job);
        return job;
    }
}

आप अपने संदर्भ के बारे में पता करने के लिए अपने संदर्भ के लिए किसी भी संदर्भ फ़ाइलों को जोड़ सकते हैं।


0

सुनिश्चित करें कि आपका

AutowiringSpringBeanJobFactory extends SpringBeanJobFactory 

निर्भरता से खींचा जाता है

    "org.springframework:spring-context-support:4..."

और से नहीं

    "org.springframework:spring-support:2..."

यह मुझे इस्तेमाल करना चाहता था

@Override
public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler)

के बजाय

@Override
protected Object createJobInstance(final TriggerFiredBundle bundle)

इसलिए नौकरी की मिसाल को विफल करना असफल रहा।


0

जब आप पहले से ही अपनी परियोजना में वास्तविक AspectJ का उपयोग करते हैं, तो आप नौकरी बीन वर्ग के साथ एनोटेट कर सकते हैं @Configurable। फिर वसंत इस वर्ग में इंजेक्ट करेगा, भले ही इसके माध्यम से निर्माण किया गया होnew


0

मैंने निम्नलिखित समस्या का सामना किया और निम्नलिखित दृष्टिकोण के साथ इससे बाहर आया:

<!-- Quartz Job -->
<bean name="JobA" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <!-- <constructor-arg ref="dao.DAOFramework" /> -->
     <property name="jobDataAsMap">
    <map>
        <entry key="daoBean" value-ref="dao.DAOFramework" />
    </map>
</property>
    <property name="jobClass" value="com.stratasync.jobs.JobA" />
    <property name="durability" value="true"/>
</bean>

ऊपर दिए गए कोड में, मैं dao.DAOFramework bean को JobA बीन में इंजेक्ट करता हूं और ExecuteInternal विधि के अंदर आप इंजेक्ट बीन प्राप्त कर सकते हैं जैसे:

  daoFramework = (DAOFramework)context.getMergedJobDataMap().get("daoBean");

मुझे उम्मीद है यह मदद करेगा! धन्यवाद।


0

ऊपर समाधान महान है, लेकिन मेरे मामले में इंजेक्शन काम नहीं कर रहा था। मुझे इसके बजाय ऑटोवेयरबिनप्रोटेक्टी का उपयोग करने की आवश्यकता थी, शायद इस तरह से कि मेरा संदर्भ कॉन्फ़िगर किया गया है:

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements
ApplicationContextAware {

    private transient AutowireCapableBeanFactory beanFactory;

    @Override
    public void setApplicationContext(final ApplicationContext context) {
        beanFactory = context.getAutowireCapableBeanFactory();
    }

    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        final Object job = super.createJobInstance(bundle);
        //beanFactory.autowireBean(job);
        beanFactory.autowireBeanProperties(job, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
        return job;
    }
}

0

उपरोक्त सभी समाधान मेरे लिए स्प्रिंग 5 और हाइबरनेट 5 और क्वार्ट्ज 2.2.3 के साथ काम नहीं करते हैं, जब मैं लेन-देन के तरीकों को कॉल करना चाहता हूं!

इसलिए मैंने इस समाधान को लागू किया जो स्वचालित रूप से अनुसूचक को शुरू करता है और नौकरियों को ट्रिगर करता है। मुझे dzone पर उस कोड का एक बहुत कुछ मिला । क्योंकि मुझे गतिशील रूप से ट्रिगर और जॉब्स बनाने की आवश्यकता नहीं है, मैं चाहता था कि स्टैटिक ट्रिगर्स को स्प्रिंग कॉन्फ़िगरेशन के माध्यम से पहले से परिभाषित किया जाए और केवल स्प्रिंग कंपोनेंट्स के रूप में नौकरियों को उजागर किया जाए।

मेरा मूल विन्यास इस तरह दिखता है

@Configuration
public class QuartzConfiguration {

  @Autowired
  ApplicationContext applicationContext;

  @Bean
  public SchedulerFactoryBean scheduler(@Autowired JobFactory jobFactory) throws IOException {
    SchedulerFactoryBean sfb = new SchedulerFactoryBean();

    sfb.setOverwriteExistingJobs(true);
    sfb.setAutoStartup(true);
    sfb.setJobFactory(jobFactory);

    Trigger[] triggers = new Trigger[] {
        cronTriggerTest().getObject()
    };
    sfb.setTriggers(triggers);
    return sfb;
  }

  @Bean
  public JobFactory cronJobFactory() {
    AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
    jobFactory.setApplicationContext(applicationContext);
    return jobFactory;
  }

  @Bean 
  public CronTriggerFactoryBean cronTriggerTest() {
    CronTriggerFactoryBean tfb = new CronTriggerFactoryBean();
    tfb.setCronExpression("0 * * ? * * *");

    JobDetail jobDetail = JobBuilder.newJob(CronTest.class)
                            .withIdentity("Testjob")
                            .build()
                            ;

    tfb.setJobDetail(jobDetail);
    return tfb;
  }

}

जैसा कि आप देख सकते हैं, आपके पास शेड्यूलर और एक सरल परीक्षण ट्रिगर है जिसे एक क्रोन अभिव्यक्ति के माध्यम से परिभाषित किया गया है। आप स्पष्ट रूप से जो भी शेड्यूलिंग अभिव्यक्ति पसंद करते हैं उसे चुन सकते हैं। फिर आपको ऑटोवेयरिंगस्प्रिंगबीनजोबफैक्टिविटी की आवश्यकता होती है जो इस तरह से जाती है

public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

  @Autowired
  private ApplicationContext applicationContext;

  private SchedulerContext schedulerContext;

  @Override
  public void setApplicationContext(final ApplicationContext context) {
    this.applicationContext = context;
  }


  @Override
  protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
    Job job = applicationContext.getBean(bundle.getJobDetail().getJobClass());
    BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(job);

    MutablePropertyValues pvs = new MutablePropertyValues();
    pvs.addPropertyValues(bundle.getJobDetail().getJobDataMap());
    pvs.addPropertyValues(bundle.getTrigger().getJobDataMap());

    if (this.schedulerContext != null)
    {
        pvs.addPropertyValues(this.schedulerContext);
    }
    bw.setPropertyValues(pvs, true);

    return job;
  }  

  public void setSchedulerContext(SchedulerContext schedulerContext) {
    this.schedulerContext = schedulerContext;
    super.setSchedulerContext(schedulerContext);
  }

}

यहां आप अपने सामान्य एप्लिकेशन संदर्भ और अपनी नौकरी को एक साथ जोड़ते हैं। यह महत्वपूर्ण अंतर है क्योंकि आम तौर पर क्वार्ट्ज शुरू होता है यह श्रमिक धागे हैं जिनका आपके आवेदन के संदर्भ से कोई संबंध नहीं है। यही कारण है कि आप Transactional mehtods निष्पादित नहीं कर सकते। आखिरी चीज गायब होना एक काम है। ऐसा लग सकता है

@Component
public class CronTest implements Job {

  @Autowired
  private MyService s;

  public CronTest() {
  }

  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    s.execute();
  }

}

यह एक सही समाधान नहीं है क्योंकि आप केवल अपनी सेवा पद्धति को कॉल करने के लिए एक अतिरिक्त वर्ग हैं। लेकिन फिर भी यह काम करता है।


0

Jdbc नौकरी की दुकान

यदि आप jdbc जॉबस्टोर का उपयोग कर रहे हैं तो क्वार्ट्ज एक अलग क्लास लोडर का उपयोग करता है। ऑटोरिंग के लिए सभी वर्कअराउंड को रोकता है, क्योंकि वसंत से ऑब्जेक्ट क्वार्ट्ज साइड पर संगत नहीं होंगे, क्योंकि वे एक अलग श्रेणी लोडर से उत्पन्न हुए थे।

इसे ठीक करने के लिए, डिफॉल्ट क्लास लोडर को क्वार्ट्ज प्रॉपर्टी फाइल में इस तरह सेट करना होगा:

org.quartz.scheduler.classLoadHelper.class=org.quartz.simpl.ThreadContextClassLoadHelper

संदर्भ के रूप में: https://github.com/quartz-scheduler/quartz/issues/221


0

बस अपनी नौकरी का विस्तार करें QuartzJobBean

public class MyJob extends QuartzJobBean {

    @Autowired
    private SomeBean someBean;

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("Some bean is " + someBean.toString());
    }

}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.