[Spring & Quartz] Jobs in database zetten

Pagina: 1
Acties:

  • Ansur
  • Registratie: Januari 2004
  • Laatst online: 02-04 12:10
Ik heb onlangs de overgang gemaakt van het configureren van onze Quartz Jobs in Spring, waar ze vroeger via Quartz xml werden geconfigureerd.

Op zich geen probleem, tot dat ik de Jobs wil opslagen in de database. Dit is nu eenmaal noodzakelijk.

De fout die ik krijg is:
code:
1
2
3
4
5
6
 java.lang.IllegalStateException: prepare() must be called prior to invoke() on MethodInvoker
    at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:245)
    at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:164)
    at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:66)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:188)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:511)


De jobs worden wél in de database opgeslagen. Het Quartz configuratiescript is ook zeker in orde, aangezien het allemaal gewerkt heeft, voordat de configuratie in Spring gebeurde.

Wat ietswat opmerkelijk is, wanneer ik debug, de prepare method wél aangeroepen wordt, en alles goed instelt.
Echter, wanneer de invoke method opgeroepen wordt, is methodObject null! Kan het zijn dat er op één of andere manier 2 instanties gemaakt worden ipv 1?


Een voorbeeld job:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 <bean id="reportingServiceTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="reportingServiceTarget"/>
        <property name="cronExpression" value="0 30 12 * * ?"/>
        <property name="volatility"><value>true</value></property>
    </bean>
    
    <bean id="reportingServiceTarget" class="com.gudrun.gdp3000.scheduling.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="reportingService"/>
        <property name="targetMethod" value="execute"/>
        <property name="concurrent" value="true"/>
        <property name="group" value="gdp3000"/>
        <property name="name" value="Database Log Reporting Service"/>
    </bean>
        
    <bean id="reportingService" class="com.gudrun.gdp3000.reporting.ReportingService" parent="schedulingService">
        <property name="emailAddress"><value>${logmanager.email.notification.addressees}</value></property>
        <property name="fileLocation"><value>${logmanager.email.file.location}</value></property>
        <property name="communicationDispatcher"><ref bean="communicationDispatcher"/></property>
        <property name="reportGenerator"><ref bean="logReportGenerator"/></property>
    </bean>

De ReportServiceTarget klasse is niks meer dan de gelijknamige Spring klasse, maar deze implementeert de Serializable interface.

De schedulerfactory bean is ook ‘pretty straightforward’:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    <bean id="quartzSchedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <!-- wat weggelaten voor leesbaarheid -->
                <ref bean="reportingServiceTrigger"/>
            </list>
        </property>
        <property name="autoStartup">
            <value>false</value>
        </property>
        <property name="configLocation">
            <value>classpath:quartz.properties</value>
        </property>
    </bean>

Als ik dus de property ‘configLocation’ weglaat, werken alle jobs.

Dan nog de quartz property file:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 org.quartz.scheduler.instanceName = ClusterScheduler
org.quartz.scheduler.instanceId = gdp3000_one

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5

org.quartz.jobStore.misfireThreshold = 3000

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.MSSQLDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true

org.quartz.dataSource.myDS.driver = com.inet.tds.TdsDriver
org.quartz.dataSource.myDS.URL = url
org.quartz.dataSource.myDS.user = user
org.quartz.dataSource.myDS.password = password
org.quartz.dataSource.myDS.maxConnections = 20

org.quartz.plugins.management.ShutdownHookPlugin

org.quartz.plugins.history.LoggingJobHistoryPlugin



De gebruikte versies zijn Spring 1.2.3 en Quartz 4.0
Via Google, als hier op GoT, heb ik niet veel gevonden. Er is wel wat documentatie rond Quartz te vinden, maar niet in samenwerking met Spring.

Alvast bedankt!

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Ik zie dat je een eigen implementatie hebt geleverd van de MethodInvokingJobDetailFactoryBean. Ik zie niet hoe je dit hebt gedaan, misschien heb je de MethodInvokingJobDetailFactoryBean van Spring ge-extend, of volledig zelf hebt geimplementeerd. Misschien dat je daar iets fout hebt gedaan. Post de code eens van jouw implementatie?

  • Ansur
  • Registratie: Januari 2004
  • Laatst online: 02-04 12:10
Daar is niks aan veranderd, behalve dan, serializable gemaakt. Alle methods etc. worden in de Spring versie uitgevoerd.

In de JavaDoc van die klasse staat:
Note: JobDetails created via this FactoryBean are not serializable and thus not suitable for persistent job stores. You need to implement your own Quartz Job as a thin wrapper for each case where you want a persistent job to delegate to a specific service method.