Is there something that starts a cron in java? - java

I have some java written to do a very very simple operation. It needs to happen once every three hours and is not connected to any user action, it's just something that revolves every three hours.
For this reason, I'm having trouble troubleshooting. The operation isn't happening. Assuming the java is intact, is there something that is supposed to "start" the cron? Or should I expect it to just be going once the server is restarted?
<bean id="queueJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.campbiche.pb.service.scheduler.BaseQuartzScheduler" />
<property name="jobDataAsMap">
<map>
<entry key="processorName" value="scheduleListingActions" />
<entry key="methodName" value="revolveQueue" />
</map>
</property>
</bean>
<bean id="queueCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="queueJob" />
<!-- run every 1 miunute -->
<property name="cronExpression" value="*/1 * * * * ?" />
</bean>
Working in SpringSource. The Cron is set to one minute for testing. "" has already been added to a schedulerfactorybean bean as well but I did not include the code here for brevity.

It will be triggered when CronTriggerBean is instantiated.
One more thing I recall, and confirmed after looking in the docs(3.x), that you need to add your queueCronTrigger to SchedulerFactoryBean.

Related

spring batch sleep between steps

How can I make a spring batch job sleep between executions if the next step is itself?
For example
<batch:step id="messages" next="messages">
.....
</batch:step>
I have tried using the parent="simpleJob" with the following configuration only to get unique key constraints. Not sure what I am missing.
<bean id="simpleJob" class="org.springframework.batch.core.job.SimpleJob" abstract="true">
<property name="jobRepository" ref="jobRepository"/>
</bean>
<bean id="runScheduler" class="com.test.boa.scheduler.RunScheduler">
<property name="dataSource" ref="dataSource"/>
</bean>
<task:scheduled-tasks>
<task:scheduled ref="runScheduler" method="run" fixed-delay="500000"/>
</task:scheduled-tasks>
The runScheduler is getting the next key but it seems like that doesn't get incremented upon step completion.
Any help would be appreciated.
You will need to set up listeners to intercept the before and after methods for your steps.
http://docs.spring.io/spring-batch/trunk/reference/html/configureStep.html#interceptingStepExecution

CronTrigger misfire instruction is not set with CronTriggerFactoryBean

I'm creating a Quartz job with the following Spring XML configuration:
<bean class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail">
<bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="name" value="The job"/>
<property name="group" value="The group"/>
<property name="jobClass" value="com.example.myapp.MorningJob"/>
<property name="jobDataMap">
<util:map>
<entry key="key1"
value="val1"/>
<entry key="key2"
value="val2"/>
</util:map>
</property>
</bean>
</property>
<property name="cronExpression" value="0 0 6 * * ? *"/>
<property name="misfireInstruction"
value="#{T(org.quartz.CronTrigger).MISFIRE_INSTRUCTION_FIRE_ONCE_NOW}"/>
<property name="timeZone" ref="timezone"/>
</bean>
My job looks like this
#Configurable
#DisallowConcurrentExecution
#PersistJobDataAfterExecution
public class MorningJob implements Job { ... }
However, misfire instruction set has no effect at all. After long app downtime, when the trigger missed multiple times, Quartz tries to start the job many times.
When I'd tried to check context.getTrigger().getMisfireInstruction() from MorningJob.execute() it gives 0, while CronTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW is 1.
Any ideas why misfire instruction is not set?
The problem was actually in my scheduler configuration. In the declaration of org.springframework.scheduling.quartz.SchedulerFactoryBean I had a property
<property name="overwriteExistingJobs" value="false"/>
Initially, for testing purposes I've configured my trigger to run each few seconds just to see it fires properly. overwriteExistingJobs meant the trigger saved in database wasn't actually updated after change of cron expression and misfireInstruction wasn't actually applied as well. To update the trigger I need either to run scheduler.clear() once or set the mentioned property to true for a while.
I'm sure this should be mentioned more clearly in the documentation as it could be really frustrating to not have a trigger configuration updated after each change. false is the default value of overwriteExistingJobs.

How to change schedule of clustered quartz job?

As far as I tried, I have to manually change the CRON_TRIGGERS table in DB. Dirty...
Any way to make more like this?:
There are 2 apps running, both have in .properties file schedule defined as "every minute" and so works the job
I stop one instance and reconfigure (change in .properties file), so the schedule is "every hour"
I start the instance. Now I would like that instace to check, that such job is already defined in DB and to update the schedule there. It is not happening now using configuration from site http://www.objectpartners.com/2013/07/09/configuring-quartz-2-with-spring-in-clustered-mode/
Or what is the typical solution?
So I guess that when you say .properties file, you actually mean the spring bean XML file(s).
It does not make any sense that you statically configure identical jobs with different schedules. If for whatever reason, one instance restarts, it will automatically apply its own schedule. If statically configured, your job triggers should be the same on all instances
If you properly set <property name="overwriteExistingJobs" value="true"/> in your SchedulerFactoryBean it should automatically updates the schedule of the job.
You should never modify the database manually. Always update the scheduler through its API.
Try sth like this:
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="yourJobDetail" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="yourJobTrigger" />
</list>
</property>
<property name="configLocation" value="file:${HOME}/yourProperties.properties" />
<!-- Commented, because don't work with autocommit = false on spring data source -->
<!-- <property name="dataSource" ref="mainDataSource"/> -->
<property name="transactionManager" ref="mainTransactionManager" />
<property name="autoStartup" value="true" />
<property name="applicationContextSchedulerContextKey" value="applicationContext" />
<property name="jobFactory">
<bean class="FactoryForJobWithInjectionOfSpringBbean" />
</property>
<!-- Will update database cron triggers to what is in this jobs file on each deploy. Replaces all previous trigger and job data that
was in the database. YMMV -->
<!-- dont work properly with cluster -->
<!-- <property name="overwriteExistingJobs" value="true" /> -->
</bean>
Unfortunately i think that:
<property name="overwriteExistingJobs" value="true" />
dosen't work correctly in cluster mode.

How to create prototype instances of "targetObject" using "MethodInvokingJobDetailFactoryBean" in Spring-Quartz?

I've been playing around with Spring-Quartz for a while now, and there is one thing I'm unable to achieve - I want to use the "MethodInvokingJobDetailFactoryBean" in order to execute a method in an class I have, and I want new instance of that object created each time the trigger is triggered.
The part of my application context that is related to Quartz looks like this:
<bean id="myTask" class="com.test.TestImpl" scope="prototype" /> <!-- The bean that does the actual work -->
<bean id="testMethodJobDetailBean" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="myTask"/>
<property name="targetMethod" value="run"/>
<property name="concurrent" value="false"/>
</bean>
<bean id="testTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="testMethodJobDetailBean"/>
<property name="startDelay" value="25000"/>
<property name="repeatInterval" value="5000"/>
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="waitForJobsToCompleteOnShutdown" value="true"/>
<property name="triggers">
<list>
<ref bean="testTrigger"/>
</list>
</property>
</bean>
My objects' names are different in the original file, and I have 2 more jobs (with a trigger for each of them) but they are not relevant for my question.
The above configuration works, and my task is executed every 5 seconds. The problem is, it always uses the same "com.test.TestImpl" instance which is problematic for me since the object have state that affects its behavior.
I've read that Quartz's default behavior is to create a new instance of jobs each time, but when using Spring-Quartz, Spring manages the life-cycle. This indeed seems logical, and that's why I added the scope="prototype" to the "myTask" bean, but it didn't help.
I also tried to set the scope of the JobDetailsFactory bean to prototype, and it didn't help.
I think that the problem is that the JobDetail object created by "MethodInvokingJobDetailFactoryBean" is not defined as prototype, and since is it wrapping my bean, and being created only once - my bean won't be created more than once.
I would like to know if someone else encountered this as I wasn't able to find any useful information regarding this issue, and wasn't able to find anyone that experienced the same behavior.
And of course, if you know how to fix this, I would be happy to hear about it.

configuration of a cronTrigger (with opensymphony quartz)

I have a web app that has to do something every, let's say first day of every month.
It's a GWT application divided into 4 projects (if that ever matters) and I added these jars using Maven (which updated my pom.xml):
opensymphony quartz 1.6.3
commons-collections
Since I am already using Spring, I followed this tutorial (Tutorial in French)
and added what's written in the tutorial in my application-context.xml file.
At compile time, no problem, but at runtime, I have this error :
com.google.gwt.user.client.rpc.StatusCodeException: Error 500 Error creating bean with name 'schedulerFactory' defined in class path resource [application-context.xml]: Cannot resolve reference to bean 'cronTrigger' while setting bean property 'triggers' with key [0];nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cronTrigger' defined in class path resource [application-context.xml]: Error setting property values;nested exception is org.springframework.beans.PropertyBatchUpdateException;nested PropertyAccessExceptions (1) are: PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'cronExpression' threw exception;nested exception is java.text.ParseException: Unexpected end of expression.
Where does it come from ?
A part of my application-context.xml :
<!-- Configuration du crontrigger -->
<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger" />
</list>
</property>
</bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref local="exampleJob" />
</property>
<!-- run every day at 6AM -->
<property name="cronExpression" value="0 0 6 * * ?" />
</bean>
<bean id="exampleJob" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="fr.web.utils.ExampleJob" />
<property name="jobDataAsMap">
<map>
<entry key="timeout" value="5" />
</map>
</property>
</bean>
Issue is you have given reference in Scheduler's trigger cronTrigger which you haven't declare in the XML file.
Provide XML for more detailed answer
Update
Your cronExpression isn't seems to be valid
0 0 6 * * ? make it 0 0 6 * *  ? note the last space before ?

Categories

Resources