Quartz retain state of existing trigger on redeploy - java

I have a Quartz trigger created through Spring Framework which I occasionally need to pause (TRIGGER_STATE=PAUSED). However, if I do a deploy of the application while the trigger is paused it gets un-paused due to the trigger being recreated. Is there a Quartz setting to retain the trigger state if the trigger already exists?
<bean id="updateJobQuartzTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="name" value="updateTrigger" />
<property name="group" value="updateDaily" />
<property name="jobDetail" ref="updateJob" />
<property name="cronExpression" value="0 0 4 * * ?" />
</bean>
<bean name="updateJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="name" value="updateJob" />
<property name="group" value="updateDaily" />
<property name="jobClass" value="com.project.quartz.SendMessageJob" />
<property name="jobDataMap">
<map>
<entry key="messageContent">
<map>
<entry key="job" value="UpdateLoad"/>
</map>
</entry>
</map>
</property>
<property name="durability" value="true"/>
</bean>

Related

Spring Integration Atomikos transaction issue

I'm trying to integrate Atomikos transaction manager into a Spring Integration program that forwards JMS from ActiveMQ to a WebMethods ESB.
The spring integration part only retrieves JMs from local ActiveMQ broker and sends them to a distant ESB broker.
When I test the nominal case, JMS is sent well and passes through the ESB and is dispatched to the subscribers then.
When I test the case where ESB sending fails, I have an issue : the JMS is never published back. I suppose it's a transaction issue because the transaction should have been rolled back when program tried to publish on ESB broker but it seems not.
Here's my spring config :
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="AtomikosTransactionManager" />
<property name="userTransaction" ref="AtomikosUserTransaction" />
</bean>
<!-- Atomikos Transaction Manager Defintion (JTA) -->
<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close" depends-on="atomikosConnectionFactorySource,connectionFactoryDestination">
<property name="transactionTimeout" value="300" />
<property name="forceShutdown" value="false" />
</bean>
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
<bean id="jmsXaConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="${source.java.naming.provider.url}" />
<property name="userName" value="${source.username}" />
<property name="password" value="${source.passwd}" />
</bean>
<bean id="atomikosConnectionFactorySource" class="com.atomikos.jms.AtomikosConnectionFactoryBean"
init-method="init" destroy-method="close">
<property name="poolSize" value="1" />
<property name="uniqueResourceName" value="activemq" />
<property name="xaConnectionFactory" ref="jmsXaConnectionFactory" />
</bean>
<bean id="connectionFactorySource"
class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="jmsXaConnectionFactory" />
<property name="clientId" value="CustomerOrderForwarderID" />
<property name="reconnectOnException" value="true" />
</bean>
<!-- Destination JNDI Context -->
<bean id="jndiTemplateDestination" class="org.springframework.jndi.JndiTemplate"
lazy-init="true">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${destination.java.naming.factory.initial}</prop>
<prop key="java.naming.provider.url">${destination.java.naming.provider.url}</prop>
<prop key="java.naming.factory.url.pkgs">${destination.java.naming.factory.url.pkgs}</prop>
</props>
</property>
</bean>
<!-- Destination Connection factory -->
<bean id="customerOrderXAConnectionFactoryDestination" class="org.springframework.jndi.JndiObjectFactoryBean"
lazy-init="true">
<property name="jndiTemplate" ref="jndiTemplateDestination" />
<property name="jndiName"
value="${destination.java.naming.factory.connection}" />
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.XAConnectionFactory" />
</bean>
<bean id="connectionFactoryDestination" class="com.atomikos.jms.AtomikosConnectionFactoryBean"
init-method="init" destroy-method="close">
<property name="poolSize" value="100" />
<property name="uniqueResourceName" value="esb" />
<property name="xaConnectionFactory" ref="customerOrderXAConnectionFactoryDestination" />
<property name="localTransactionMode" value="true" />
</bean>
<bean id="ddr" class="com.adeo.transverse.jms.forwarder.customerorder.DynamicDestinationResolver" />
<bean id="userCredentialsConnectionFactoryDestination"
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter" lazy-init="true">
<property name="targetConnectionFactory">
<ref bean="connectionFactoryDestination" />
</property>
<property name="username" value="${destination.username}" />
<property name="password" value="${destination.passwd}" />
</bean>
Here's the integration part :
<!-- In bridge -->
<jms:message-driven-channel-adapter
id="StoreStockMotionSourceJmsAdapter" channel="bridgeChannelStoreStockMotionEnricher"
container="jmsContainerSourceStoreStockMotion" />
<!-- Channel -->
<si:channel id="bridgeChannelStoreStockMotionEnricher" />
<jms:outbound-channel-adapter id="StoreStockMotionDestinationJmsAdapter"
channel="bridgeChannelStoreStockMotionEnricher" jms-template="jmsTemplateStoreStockMotionDestination" />
<bean id="jmsTemplateStoreStockMotionDestination" class="org.springframework.jms.core.JmsTemplate">
<property name="transactionManager" ref ="transactionManager"/>
<property name="connectionFactory" ref="userCredentialsConnectionFactoryDestination" />
<property name="defaultDestinationName" value="${StoreStockMotion.destination.topic}" />
<property name="defaultDestination" ref="StoreStockMotionDestinationTopic" />
<property name="pubSubDomain" value="true"/>
</bean>
<!-- Topic JMS for published message -->
<bean id="StoreStockMotionDestinationTopic" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true">
<property name="jndiTemplate">
<ref bean="jndiTemplateDestination" />
</property>
<property name="jndiName">
<value>${StoreStockMotion.destination.topic}</value>
</property>
</bean>
<!-- Topic JMS for Subscribing Message -->
<bean id="jmsContainerSourceStoreStockMotion"
class="org.springframework.jms.listener.DefaultMessageListenerContainer"
lazy-init="true">
<property name="connectionFactory" ref="connectionFactorySource" />
<property name="destinationName" value="${StoreStockMotion.source.topic}" />
<property name="subscriptionDurable" value="true" />
<!-- 2 is client acknowledge -->
<property name="sessionAcknowledgeMode" value="2" />
<property name="durableSubscriptionName" value="${StoreStockMotion.source.subname}" />
<property name="sessionTransacted" value="false" />
<property name="pubSubDomain" value="true"/>
</bean>
Source and Destination are both encapsulated in XA connection factories and transactionManager handles the two transactions. Any idea what's missing ?

How do I set priorities quartz triggers in Spring MVC

I use Quartz scheduler with cron expressions for few tasks to be executed on a regular intervals in my Java Spring MVC application. In my root-context.xml file, I have the following:
<!--Quartz Scheduler Beans -->
<bean id="emailNotificationJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="eventsService" />
<property name="targetMethod" value="sendEventEmailNotification" />
<property name="concurrent" value="false" /> <!-- this is the property to prevent concurrent execution -->
</bean>
<bean id="deleteWebContentsJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="webContentDefinitionService" />
<property name="targetMethod" value="deleteWebContents" />
<property name="concurrent" value="false" />
</bean>
<bean id="saveStaticContentsJob"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="webContentDefinitionService" />
<property name="targetMethod" value="saveStaticContents" />
<property name="concurrent" value="false" />
</bean>
<bean id="emailTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="emailNotificationJob" />
<property name="cronExpression" value="0 0/1 * 1/1 * ? *" />
</bean>
<bean id="deleteWebContentsTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="deleteWebContentsJob"/>
<property name="cronExpression" value="0 1 0 1/1 * ? *" />
</bean>
<bean id="staticContentsUploadTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="saveStaticContentsJob" />
<property name="cronExpression" value="0 0/1 * 1/1 * ? *" />
</bean>
<!-- Scheduler factory bean to glue together jobDetails and triggers to Configure Quartz Scheduler -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="emailNotificationJob" />
<ref bean="deleteWebContentsJob" />
<ref bean="saveStaticContentsJob" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="emailTrigger" />
<ref bean="deleteWebContentsTrigger" />
<ref bean="staticContentsUploadTrigger" />
</list>
</property>
</bean>
<!-- Quartz Bean End -->
I use Quartz Scheduler 2.2.1 in my application.
I want to set priorities for various triggers. Here I have two triggers that are set to fire at same time intervals. I am trying to set one of them as priority 1 and the other one as priority 2. Is there a way to do that.
CronTriggerFactoryBean has a property called priority (spring-context-support:4.2.4.RELEASE). This is in turn used to set the priority of the CronTriggerImpl, which has a javadoc that states:
The priority of a Trigger acts as a tie breaker such that if two Triggers have the same scheduled fire time, then Quartz will do its best to give the one with the higher priority first access to a worker thread.
If not explicitly set, the default value is 5.
Then again, if there are enough threads in the thread pool for both processes, I'm not sure if the priority will have any effect (depending on whether the priority is also assigned to the actual worker thread).

Spring batch ItemReader executing multiple times for same record

I am trying to implement Spring batch job for database cleanup.It just delete entry from a table in scheduled way.
First we fetch 10 rows from table.(ItemReader)
Removing these 10 entries from table(ItemWriter)
I have scheduled the batch at 15 minute interval.
When we launch the batch,surprisingly 10 thread tries to read the data from table.
Below is the configuration.
<!-- spring batch context -->
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<property name="transactionManager" ref="batchTransactionManager" />
</bean>
<bean id="batchTransactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<!--<property name="taskExecutor">
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
</property>-->
</bean>
<bean
class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
<property name="jobRegistry" ref="jobRegistry" />
</bean>
<bean id="jobRegistry"
class="org.springframework.batch.core.configuration.support.MapJobRegistry" />
<!-- spring batch context -->
<!--<bean id="completionPolicy" class="org.springframework.batch.repeat.policy.DefaultResultCompletionPolicy"/>-->
<batch:job id="csrfTokenCleanUpBatchJob">
<batch:step id="step">
<tasklet>
<chunk reader="csrfTokenReader" writer="csrfTokenWriter" commit-interval="10"></chunk>
</tasklet>
</batch:step>
</batch:job>
<!-- run every 10 seconds -->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="jobDetail" />
<property name="cronExpression" value="* 0/15 * * * ?" />
</bean>
</property>
</bean>
<bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="com.test.oauth.batch.job.CSRFTokenJobLauncher" />
<property name="group" value="quartz-batch" />
<property name="jobDataAsMap">
<map>
<entry key="jobName" value="csrfTokenCleanUpBatchJob" />
<entry key="jobLocator" value-ref="jobRegistry" />
<entry key="jobLauncher" value-ref="jobLauncher" />
</map>
</property>
</bean>
</beans>
It is all by design you want to process each record. The ItemWriter gets as many records as you want but is bound by the commit-interval. Yours is 1 which means each record is individually committed, I suggest you set it to 50. The processor processes each record by it self until the commit interval is reached then the writer is called. As mentioned yours is 1.
Also, make the read method of ItemReader as synchronised.

what is the use of durability in quartz xml

Here a property mention that durability=true.
<bean name="complexJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.websystique.spring.quartz.ScheduledJob" />
<property name="jobDataMap">
<map>
<entry key="anotherBean" value-ref="anotherBean1" />
<entry key="myBean" value-ref="myBean" />
</map>
</property>
<property name="durability" value="true" />
</bean>
could you please explain what is the use of durability=true.
From here:
Specify the job's durability, i.e. whether it should remain stored in
the job store even if no triggers point to it anymore.

Boundary Event on User Task in Activiti not triggerred

I am using Activiti BPM to implement a simple workflow. This workflow sends email to users and awaits user feedback. If feedback is not received for 24 hrs, it will again send the email and await for response.
I used boundary event like this:
<boundaryEvent id="boundarytimer1" name="Timer" attachedToRef="userTask" cancelActivity="true">
<timerEventDefinition>
<timeDuration>PT24H</timeDuration>
</timerEventDefinition>
</boundaryEvent>
I can see timer job created in ACT_RU_JOB table. However this job is not triggerred.
Probably you didn't set jobExecutorActivate=true inside your Activiti configuration.
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="jobExecutorActivate" value="true" />
<property name="history" value="activity"/>
</bean>
Hope it helps.
From activiti 6.0.0 Version
need to use springConfiguration.setAsyncExecutorActivate(true);
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="asyncExecutorActivate" value="true" />
<property name="history" value="activity"/>
</bean>

Categories