Hi

Thanks for getting back. Your Quartz configuration seems fine.

To me this sounds like a bug in Quartz itself as Quartz claims that the
trigger is null/non-existing but when we try to schedule the Job using that
given trigger it blows up with ObjectAlreadyExistsException.

That said there's a race condition between the time window as we ask for a
pre-existing trigger and the point where we try to schedule the Job. What if
in this time window another JVM (a cluster member) schedules a Job using the
same trigger name/group. IMHO what actually would come handy here would be a
*atomic* Quartz-API for this, something like what we already have in Java
itself:

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html#putIfAbsent(K,%20V)

Which as it's Javadoc already says is equivalent to:

if (!map.containsKey(key))
   return map.put(key, value);
else
   return map.get(key);

Except that the action is performed *atomically*.

Maybe you want to ask for help using the Quartz user-forum itself and refer
to this thread?

Babak


lakshmi.prashant wrote
> Hi,
> 
>   Sorry for the delay in response. I did not get notified in my mail box
> and hence had not followed your reply to the mail thread.
> 
> Please find below my answers and the blueprint xml used in the cluster
> with 7 VM's.
> 
> Thanks,
> Lakshmi
> 
>    
>  - Which exact Quartz 1.x version do you make use of? : 
/
> Ans: I am using servicemix quartz 1.8.6_1 bundle.
/
> 
> - Can you reproduce this with the latest Camel 2.12.1 version? 
/
> Ans: Yes. It happens in big clusters. Has any fix been provided with camel
> 2.12.1?
/
> 
> - And CAMEL-5994 is already fixed so this should not cause any problem for
> you 
> - Also looking at the stacktrace I think Quartz has not been setup
> properly in Cluster-Mode (see
> org.apache.camel.component.quartz.QuartzComponent.doAddJob(QuartzComponent.java:232)
> on the call-stack)... Did you set the org.quartz.jobStore.isClustered and
> org.quartz.jobStore.clusterCheckinInterval properties appropriately?
/
> Ans: Please find the blueprint XML that I had used. I have set isClustered
> as true and the logs showed that the route got triggered by quartz in
> different cluster VM's for different runs, till the exception got
> reported. But I was not sure of the right value for the checkin interval
> in the cluster and had not specified any specific value.
/
> 
>  - As you run inside OSGi but assign the id of 
> <camelContext>
>  by yourself (e.g. context4), have you seen the blue-box about this here
> http://camel.apache.org/quartz
/
> Ans: I am assigning an unique id for each bundle with the camel route. As
> of now, I had tested with only 1 bundle deployed in multiple cluster nodes
> & hence I guess that the context id should not be a problem.
> 
> I will also check by removing the context id, as well.
/
> 
> 
> I  had a look at the quartz component source code: The error trace shows
> that existingTrigger is null. It looks like that a race condition is
> occuring between the different VM's. Both of them are likely getting the
> trigger name as null and try to schedule the job..but the job is already
> scheduled
> 
>   private void doAddJob(JobDetail job, Trigger trigger) throws
> SchedulerException {
>         incrementJobCounter(getScheduler());
> 
>         Trigger existingTrigger =
> getScheduler().getTrigger(trigger.getName(), trigger.getGroup());
>         if (existingTrigger == null) {
>             LOG.debug("Adding job using trigger: {}/{}",
> trigger.getGroup(), trigger.getName());
>             
*
> getScheduler().scheduleJob(job, trigger);
*
>         } else if (hasTriggerChanged(existingTrigger, trigger)) {
>             LOG.debug("Trigger: {}/{} already exists and will be updated
> by Quartz.", trigger.getGroup(), trigger.getName());
>             // fast forward start time to now, as we do not want any
> misfire to kick in
>             trigger.setStartTime(new Date());
>             // replace job, and relate trigger to previous job name, which
> is needed to reschedule job
>             scheduler.addJob(job, true);
>             trigger.setJobName(existingTrigger.getJobName());
>             scheduler.rescheduleJob(trigger.getName(), trigger.getGroup(),
> trigger);
>         } else {
>             if (!isClustered()) {
>                 LOG.debug("Trigger: {}/{} already exists and will be
> resumed by Quartz.", trigger.getGroup(), trigger.getName());
>                 // fast forward start time to now, as we do not want any
> misfire to kick in
>                 trigger.setStartTime(new Date());
>                 // replace job, and relate trigger to previous job name,
> which is needed to reschedule job
>                 scheduler.addJob(job, true);
>                 trigger.setJobName(existingTrigger.getJobName());
>                 scheduler.rescheduleJob(trigger.getName(),
> trigger.getGroup(), trigger);
>             } else {
>                 LOG.debug("Trigger: {}/{} already exists and is already
> scheduled by clustered JobStore.", trigger.getGroup(), trigger.getName());
>             }
>         }
>     }
> 
> ____________________________________________________________________________________

> 
*
> Blueprint XML used by me:
*

> 
> <?xml version="1.0" encoding="UTF-8"?>
> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0";
> 
> xmlns:Generator="com.sap.it.gnb.ifl.common.gen.pluggability.api.GeneratorHandler"
>       xmlns:str="http://exslt.org/strings"; 
> xmlns:exsl="http://exslt.org/common";
>       xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0";
>       xmlns:idocsoap="urn:sap-com:document:sap:idoc:soap:messages"
> xmlns:bsn="http://sapcd.com/bsnagt";
>       xmlns:ns="https://bsnschemas.netweaver.neo.com/bsnflow";
> xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws";
>       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> xmlns:sec="http://cxf.apache.org/configuration/security";
>       xmlns:wsrm-policy="http://schemas.xmlsoap.org/ws/2005/02/rm/policy";
>       xmlns:wsrm-mgr="http://cxf.apache.org/ws/rm/manager";
> xmlns:wsa="http://cxf.apache.org/ws/addressing";
>       xmlns:http-conf="http://cxf.apache.org/transports/http/configuration";
>       xmlns:cxfcore="http://cxf.apache.org/blueprint/core";
> xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf";
>       xmlns:camel="http://camel.apache.org/schema/blueprint";
>       xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0
> http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd          
> http://camel.apache.org/schema/blueprint
> http://camel.apache.org/schema/blueprint/camel-blueprint.xsd          
> http://camel.apache.org/schema/blueprint/cxf
> http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd          
> http://cxf.apache.org/blueprint/core
> http://cxf.apache.org/schemas/blueprint/core.xsd          
> http://cxf.apache.org/transports/http/configuration
> http://cxf.apache.org/schemas/configuration/http-conf.xsd          
> http://cxf.apache.org/ws/rm/manager
> http://cxf.apache.org/schemas/configuration/wsrm-manager.xsd          
> http://schemas.xmlsoap.org/ws/2005/02/rm/policy
> http://schemas.xmlsoap.org/ws/2005/02/rm/wsrm-policy.xsd          
> http://cxf.apache.org/configuration/security
> http://cxf.apache.org/schemas/configuration/security.xsd          
> http://cxf.apache.org/blueprint/jaxws
> http://cxf.apache.org/schemas/blueprint/jaxws.xsd
>       http://camel.apache.org/schema/spring
> http://camel.apache.org/schema/spring/camel-spring.xsd";>
> 
>        
>       
> <reference id="dataSource" interface="javax.sql.DataSource"
> filter="(dataSourceName=default)" />
>       
> <bean id="stdSchedulerFactory"
> class="org.quartz.impl.StdSchedulerFactory">
>         
> <argument  type="java.util.Properties" >
>               
> <props>
>                       
> <prop key="org.quartz.jobStore.class">
> org.quartz.impl.jdbcjobstore.JobStoreTX
> </prop>
>                       
> <prop key="org.quartz.dataSource.default.jndiURL">
> osgi:service/javax.sql.DataSource/(dataSourceName=default)
> </prop>
>                               
> <prop key="org.quartz.jobStore.dataSource">
> default
> </prop>
>                               
>                               
> <prop key="org.quartz.scheduler.instanceId">
> AUTO
> </prop>
>                               
> <prop key="org.quartz.jobStore.misfireThreshold">
> 60000
> </prop>
>                               
> <prop key="org.quartz.jobStore.class">
> org.quartz.impl.jdbcjobstore.JobStoreTX
> </prop>
>                               
> <prop key="org.quartz.jobStore.driverDelegateClass">
> org.quartz.impl.jdbcjobstore.StdJDBCDelegate
> </prop>
>                               
> <prop key="org.quartz.dataSource.default.jndiAlwaysLookup">
> false
> </prop>
>                               
>                               
> <prop key="org.quartz.scheduler.skipUpdateCheck">
> true
> </prop>
>                               
> <prop key="org.quartz.jobStore.isClustered">
> true
> </prop>
>                               
> <prop key="org.quartz.threadPool.class">
> org.quartz.simpl.SimpleThreadPool
> </prop>
>                               
> <prop key="org.quartz.threadPool.threadCount">
> 50
> </prop>
>                               
> <prop key="org.quartz.plugin.triggHistory.class">
> org.quartz.plugins.history.LoggingTriggerHistoryPlugin        
> </prop>
>                               
> <prop key="org.quartz.plugin.triggHistory.triggerFiredMessage">
> Trigger {1}.{0} fired job {6}.{5} at {4,date,yyyy-MM-dd HH:mm:ss} 
> </prop>
>                               
> <prop key="org.quartz.plugin.triggHistory.triggerCompleteMessage">
> Trigger {1}.{0} completed firing job {6}.{5} at
>                                       {4,date, yyyy-MM-dd HH:mm:ss} with 
> resulting trigger instructioncode
> {9}
>                               
> </prop>
>                               
>               
> </props>
>         
> </argument>
>     
> </bean>
>       
>       
> <bean id="quartz"
> class="org.apache.camel.component.quartz.QuartzComponent">
>     
>               
> <property name="factory" ref="stdSchedulerFactory"/>
>    
> </bean>
>               
>    
> <bean id="mockProcessor" class="com.sap.test.route.TestProcessor" />
>       

>       
>    
> <camelContext id="context4"
>               xmlns="http://camel.apache.org/schema/blueprint"; >
>                

>                
> <route>
>                       
> <from uri="quartz://schedule3?cron=0+0/1+0-23+*+*+?+*" />
>                       
> <process ref="mockProcessor" />
>                       
>                       
> <camel:to uri="file:data/outbox" />
>               
> </route>
> </camelContext>
> 
> </blueprint>





--
View this message in context: 
http://camel.465427.n5.nabble.com/Camel-quartz-misfires-and-route-not-getting-run-triggered-after-exception-ObjectAlreadyExistsExceptin-tp5739997p5741637.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Reply via email to