Announcement Announcement Module
Collapse
No announcement yet.
ConcurrentModificationException on Spring Batch Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • ConcurrentModificationException on Spring Batch

    Hi,
    I'm using Spring Batch with 20 threads on parallel execution.
    The threads are modifying a Queue (LinkedBlockingQueue) which is thread safe, but I have sometimes a ConcurrentModificationException.
    The threads are launched by a cronned quartz jobs. Every Job launchs 20 threads the same time, when 2 jobs are executing threads together the exception appears otherwise it's all ok.
    does someone have an issue for this problem ?
    Thanks,

    Regards,
    Ahmed

  • #2
    ConcurrentModificationException indicates that the database shows that two peers (jobs, threads, etc.) have updated some shared data without co-ordinating the effort.

    There are a number of possible causes, so we don't really have enough information to suggest which you have encountered. It might be your platform (e.g. MySQL), or you might be launching the same job by mistake at the same time, or it might be that you have misconfigured or misunderstood the transactions in your job. I tend to suspect the latter, since you talk about jobs "launching threads" without saying exactly how that is handled (transactions are thread bound, so there are limits to what you can do with low level threading APIs). You could find many threads in this forum discussing teh same problem, and all have resolutions in the end.

    Comment


    • #3
      Can you post the stacktrace of the exception?

      Normally a ConcurrentModificationException doesn't need to indicate concurrent access (they name of the exception is bad because it is misleading). A ConcurrentModificationException can be thrown when a thread gets an iterator of a map, does an update on a map and then uses the iterator.

      Comment


      • #4
        Context of the execution

        Thank you for the fast response,
        I read some threads discussing the same exception but I didn't find a solution to my problem.
        For more explanation :
        Every job launches the 20 threads which do a poll on my queue to take a String (file name) for a treatment (parsing the file, Database transactions, etc.)
        The jobs are cronned to run every 2 minutes
        Sometimes the 20 threads take more than 2 minutes to finish
        The threads of the 2 jobs don't co-ordinate on the queue
        Exception appears

        Issues taken :
        I synchronized the method executeInternal(..) of the job. the exception still appears.

        Comment


        • #5
          We still can't really tell what you mean without a stacktrace. Ignore what I said about the database - this is a java.util.Collection issue.

          Comment


          • #6
            Stack trace

            This is the stack trace of the Exception,

            Code:
            org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'readFile' defined in class path resource [rechargeFileJob.xml]: Cannot resolve reference to bean 'rechargeItemWr
            iter' while setting bean property 'itemWriter'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rechargeItemWriter' defined in class path re
            source [rechargeFileJob.xml]: Initialization of bean failed; nested exception is java.util.ConcurrentModificationException
                    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:275)
                    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:104)
                    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1244)
                    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1008)
                    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:470)
                    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
                    at java.security.AccessController.doPrivileged(Native Method)
                    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
                    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
                    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:220)
                    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
                    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
                    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
                    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:423)
                    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729)
                    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381)
                    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
                    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:105)
                    at xxx.xxxxxxx.xxxxxxxx.batch.ClassPathXmlApplicationContextJobFactory.createJob(ClassPathXmlApplicationContextJobFactory.java:62)
                    at org.springframework.batch.core.configuration.support.MapJobRegistry.getJob(MapJobRegistry.java:81)
                    at xxx.xxxxxxx.xxxxxxxx.batch.Runner.executeInternal(Runner.java:106)
                    at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:86)
                    at org.quartz.core.JobRunShell.run(JobRunShell.java:195)
                    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)

            Comment


            • #7
              What version of Spring are you using? Did you paste in the whole stack trace (it looks like we might be missing the "caused by")?

              Comment


              • #8
                Spring version

                I'm using spring-core version 2.5.4 and spring-batch version 1.1.0-DEV-SNAPSHOT.

                stacktrace :
                Code:
                org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'readFile' defined in class path resource [rechargeFileJob.xml]: Cannot resolve reference to bean 'rechargeItemWriter' while setting bean property 'itemWriter'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rechargeItemWriter' defined in class path resource [rechargeFileJob.xml]: Initialization of bean failed; nested exception is java.util.ConcurrentModificationException
                        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:275)
                        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:104)
                        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1244)
                        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1008)
                        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:470)
                        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
                        at java.security.AccessController.doPrivileged(Native Method)
                        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
                        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
                        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:220)
                        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
                        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
                        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
                        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:423)
                        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729)
                        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381)
                        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>ClassPathXmlApplicationContext.java:139)
                        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>ClassPathXmlApplicationContext.java:105)
                        at xxx.xxxxxxx.xxxxxxxx.batch.ClassPathXmlApplicationContextJobFactory.createJob(ClassPathXmlApplicationContextJobFactory.java:62)
                        at org.springframework.batch.core.configuration.support.MapJobRegistry.getJob(MapJobRegistry.java:81)
                        at xxx.xxxxxxx.xxxxxxxx.batch.Runner.executeInternal(Runner.java:106)
                        at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:86)
                        at org.quartz.core.JobRunShell.run(JobRunShell.java:195)
                        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)
                Caused by: org.springframework.beans.factory.BeanCreationException: Error reating bean with name 'rechargeItemWriter' defined in class path resource [rechargeFileJob.xml]: Initialization of bean failed; nested exception is java.util.ConcurrentModificationException
                        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:478)
                        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
                        at java.security.AccessController.doPrivileged(Native Method)
                        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
                        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
                        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:220)
                        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
                        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
                        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
                        at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:269)
                        ... 23 more
                Caused by: java.util.ConcurrentModificationException
                        at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
                        at java.util.HashMap$KeyIterator.next(HashMap.java:828)
                        at org.springframework.beans.TypeConverterDelegate.convertToTypedCollection(TypeConverterDelegate.java:451)
                        at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:190)
                        at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:138)
                        at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:832)
                        at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:651)
                        at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:78)
                        at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:59)
                        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1274)
                        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1008)
                        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:470)
                        ... 32 more

                Comment


                • #9
                  So your ItemWriter has a collection injected into it? It seems to be shared between instances because someone is modifying it while it is being iterated. Can we see the configuration?

                  Comment


                  • #10
                    Collection causes CME

                    Thank you for your replies.

                    Problem resolved.
                    My itemWriter has a collection (Set) injected into it, when I remove it from the bean, all goes ok.
                    I'll use another issue for replacement
                    or is there a solution to use collection without having CME ?

                    Thanx for all.
                    Ahmed
                    Last edited by Chribicus; Jul 3rd, 2008, 10:54 AM.

                    Comment


                    • #11
                      Originally posted by Chribicus View Post
                      or is there a solution to use collection without having CME ?
                      Yes: don't modify it concurrently. It's hard to understand why you'd need to share a set instance between two beans if the set was mutable. Can't you simply inject a different instance of teh set into each of the beans that requires it?

                      Comment


                      • #12
                        Use of the Set

                        The Set should be shared between threads because it synchronizes the transaction with the database. The threads write records on the database, sometimes write new record, sometimes update an existent record.
                        If 2 threads are using the same record, they will write it together but I have to write one then update it. so comes the Set to synchronize this issue.

                        this is how we use the set :
                        Code:
                        if (theSet.contains(theString)) {     
                               for (i = 0; i < MAX_ITERATION; i++) {
                                   record = recordDao.getRecord(theString);
                                        if (record != null) {
                                            break;
                                        }
                                        try {
                                            Thread.sleep(WAIT_INTERVAL);
                                        } catch (InterruptedException ignore) {
                                            log.warn("sleep interrupted while waiting for: " + record);
                                        }
                                    }
                                }
                                recordDao.updateRecord(record);
                        } else {
                                theSet.add(theString);
                                record = recordDao.getRecord(theString);
                                if (record == null) {
                                     record = new Record(theString);
                                     recordDao.createSubscriber(record);
                                } else {
                                     record.setString(theString);
                                     recordDao.updateRecord(record);
                                }
                        }
                        NB : The Set is ThreadSafe (synchronized)
                        Last edited by Chribicus; Jul 4th, 2008, 05:33 AM.

                        Comment


                        • #13
                          This is not going to work.

                          You check modify (contains,add) is not atomic. And it is not possible to make multiple actions on a synchronized collection atomic if the lock is not exposed (and with a synchronized wrapper around a set, the lock is not exposed).

                          Another reason when this isn't going to work is when you have multiple vm's, because the locks inside the set are not shared.

                          What you should do is coordinate concurrency through the database or through a clustering technology like Terracotta.

                          Comment


                          • #14
                            Hi,

                            I'm beginner with spring quartz and i have a problem for my project.

                            I'would whan my job is failed or sleep, the scheduler relance it and the job can retake
                            where it has stopped.

                            This is a differents steps how i was did :
                            In the first i have m y class scheduler:

                            Code:
                            @DisallowConcurrentExecution
                            public class JobLauncherDetails extends QuartzJobBean /*implements JobExecutionListener*/ {
                            
                            	private static final String JOB_DATA_MAP_MAX_RETRY = "maxRetry";
                            	//private static final String JOB_DATA_MAP_NB_RETRIES = "nbRetries";
                            	private final static String JOB_LOCATOR_CONTEXT_KEY = "jobLocator";
                            	private final static String JOB_LAUNCHER_CONTEXT_KEY = "jobLauncher";
                            	private static final String JOB_DATA_MAP_START_DATE = "startDate";
                            	private static final String JOB_PARAM_LISTENER_DELAY_KEY = "listenerDelay";
                            	private static final long JOB_PARAM_DEFAULT_LISTENER_DELAY = 1000;
                            
                            	private static Logger log = LoggerFactory.getLogger(JobLauncherDetails.class);
                            
                            	/**
                            	 * Special key in job data map for the name of a job to run.
                            	 */
                            	private static final String JOB_NAME = "jobName";
                            
                            	private JobLocator jobLocator;
                            	private JobLauncher jobLauncher;
                            	private String jobName;
                                private JobListener MyjobListener;
                            	/**
                            	 * Method called by Quartz trigger. The given {@link JobExecutionContext}
                            	 * gives info on the Job to run.
                            	 */
                            	protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
                            		try {
                            			jobLocator = (JobLocator) context.getScheduler().getContext().get(JOB_LOCATOR_CONTEXT_KEY);
                            			jobLauncher = (JobLauncher) context.getScheduler().getContext().get(JOB_LAUNCHER_CONTEXT_KEY);
                            			MyjobListener=(JobListener)context.getScheduler().getContext().get(MyjobListener);
                            			
                            		
                            		} catch (SchedulerException se) {
                            			log.error("Unable to get jobLocator and jobLauncher from scheduler context.", se);
                            		}
                            
                            		if (jobLocator == null || jobLauncher == null) {
                            			log.error("Unable to run a job without valids jobLocator and jobLauncher.");
                            		} else {
                            			JobDetail jobDetail = context.getJobDetail();
                            			Map<String, Object> jobDataMap = context.getMergedJobDataMap();
                            			
                            			if (jobDataMap == null || jobDataMap.size() == 0) {
                            				log.error("Unable to run a job without a valid jobDataMap (no job name provided...).");
                            			} else {
                            				
                            				jobName = (String) jobDataMap.get(JOB_NAME);
                            
                            				if (jobName == null || jobName.isEmpty()) {
                            					log.error("Unable to run a job: no job name provided...");
                            				} else {
                            					
                            					if(context.getRefireCount()==0) {
                            						// Add a date to the jobDataMap so that the job is unique.
                            						// It is useful to distinguish 2 instances of the same trigger.
                            						// Otherwise, a JobExecutionAlreadyRunningException will be launched
                            						// (no need to modify this parameter for a refired job)
                            						jobDataMap.put(JOB_DATA_MAP_START_DATE, new Date());
                            					}
                            
                            					JobParameters jobParameters = getJobParametersFromJobMap(jobDataMap);
                            					Scheduler sched= context.getScheduler();
                            					try {
                            						sched.getListenerManager().addJobListener(new NcaJobListener());
                            						
                            					} catch (SchedulerException e) {
                            						// TODO Auto-generated catch block
                            						e.printStackTrace();
                            					}	
                            					
                            					if (log.isInfoEnabled())
                            						log.info("\n**********************************************************************\n" 
                            								+ "* Quartz trigger - start job: {}. Key: {}\n"
                            								+ "* Firing unique ID: {}\n" 
                            								+ "* Refire count: {}\n" 
                            								+ "* Job parameters: {}\n"
                            								+ "* isConcurrentExectionDisallowed: {}\n"
                            								+ "**********************************************************************\n",
                            								new Object[] { jobName, jobDetail==null?"":jobDetail.getKey(), context.getFireInstanceId(), 
                            												context.getRefireCount(), jobParameters==null?"":jobParameters.toString(), 
                            												context.getJobDetail().isConcurrentExectionDisallowed() });
                            					
                            					JobExecution jobExec = null;
                            					BatchStatus jobStatus = BatchStatus.UNKNOWN;
                            
                            					try {
                            						jobExec = jobLauncher.run(jobLocator.getJob(jobName), jobParameters);
                            						log.info("Job Id: {}", jobExec.getId());
                            
                            					}
                            
                            					} catch (Exception ex) {
                            						if(!(ex instanceof JobExecutionException)) {
                            							log.error("Error while running Job [{}]. Rescheduling if possible.\nError: {}\n******************************", jobName, ex.toString());
                            							// TODO: retirer ce log...
                            							log.error("Error full stack:", ex);
                            							
                            						} else {
                            							throw (JobExecutionException) ex;
                            						}
                            					}
                            
                            					if (log.isInfoEnabled())
                            						log.info("\n**********************************************************************\n" 
                            								+ "* Quartz trigger - end job: {}\n"
                            								+ "* Firing unique ID: {}\n" 
                            								+ "* Refire count: {}\n" 
                            								+ "* Job parameters: {}\n"
                            								+ "* Start date: {}\n"
                            								+ "* End date: {}\n"
                            								+ "* Status: {}\n"
                            								+ "**********************************************************************\n",
                            								new Object[] { jobName, context.getFireInstanceId(), context.getRefireCount(), 
                            												jobParameters==null?"":jobParameters.toString(),
                            												jobExec==null?"":jobExec.getStartTime(),
                            												jobExec==null?"":jobExec.getEndTime(),
                            												jobStatus });
                            				}
                            			}
                            		}
                            	}
                            
                            	/**
                            	 * Copy parameters that are of the correct type over to
                            	 * {@link JobParameters}, ignoring jobName.
                            	 * 
                            	 * @return a {@link JobParameters} instance
                            	 */
                            	private JobParameters getJobParametersFromJobMap(Map<String, Object> jobDataMap) {
                            
                            		JobParametersBuilder builder = new JobParametersBuilder();
                            
                            		for (Entry<String, Object> entry : jobDataMap.entrySet()) {
                            			String key = entry.getKey();
                            			Object value = entry.getValue();
                            			if (value instanceof String && !key.equals(JOB_NAME)) {
                            				builder.addString(key, (String) value);
                            			} else if (value instanceof Float || value instanceof Double) {
                            				builder.addDouble(key, ((Number) value).doubleValue());
                            			} else if (value instanceof Integer || value instanceof Long) {
                            				builder.addLong(key, ((Number) value).longValue());
                            			} else if (value instanceof Date) {
                            				builder.addDate(key, (Date) value);
                            			} else {
                            				log.debug("JobDataMap contains values which are not job parameters (ignoring).");
                            			}
                            		}
                            
                            		return builder.toJobParameters();
                            	}
                            
                            	/*@Override
                            	public void afterJob(JobExecution jobExecution) {
                            		// TODO Auto-generated method stub
                            		log.info("*************************** Job ended with status: {} ********************", jobExecution.getExitStatus());
                            
                            		if (ExitStatus.FAILED.equals(jobExecution.getExitStatus())) {
                            			log.error("******************************\nJob [{}] failed. Reschedule if possible.\n******************************", jobName);
                            
                            			// rescheduleJob(jobExecution);
                            		}
                            	}
                            
                            	@Override
                            	public void beforeJob(JobExecution jobExecution) {
                            		log.info("************** Before running job {} **************", jobName);
                            	}*/
                            
                            }

                            Comment


                            • #15
                              In the second i have a class jobfaileur:

                              Code:
                              public class JobFailureListener implements JobExecutionListener {
                              	private static Logger log = LoggerFactory.getLogger(JobFailureListener.class);
                              	private static final String JOB_DATA_MAP_MAX_RETRY = "maxRetry";
                              	private static final String JOB_NAME = "jobName";
                              	private String jobName;
                              	public void beforeJob(JobExecution jobExecution) {
                              	// nothing to do
                              		log.info("*************************** Job ended with status: {} ********************", jobExecution.getExitStatus());
                              	}
                              
                              	public void afterJob(JobExecution jobExecution, JobExecutionContext context) throws JobExecutionException {
                              	
                              		if( jobExecution.getStatus() == BatchStatus.COMPLETED ){
                              			System.out.println("!!!!!!!!!!!!!!!!!  sa	 marche !!!!!!!!!!!!!!!!");
                              	    }
                              		
                              		else
                              		
                              			if (!jobExecution.getAllFailureExceptions().isEmpty()) {
                              	ExitStatus exitStatus = ExitStatus.FAILED;
                              	log.error("******************************\nJob [{}] failed. Reschedule if possible.\n******************************");
                              	
                              	//rescheduler if possible
                              	rescheduleJob(jobExecution, context);
                              	
                              	for (Throwable e : jobExecution.getAllFailureExceptions()) {
                              
                              	exitStatus = exitStatus.addExitDescription(e);
                              
                              	}
                              
                              	jobExecution.setExitStatus(exitStatus);
                              
                              	}
                              
                              	}
                              
                              	private void rescheduleJob(JobExecution jobExec, JobExecutionContext context) throws JobExecutionException {
                              		rescheduleJob(jobExec, context, null);
                              	}
                              
                              	private void rescheduleJob(JobExecution jobExec, JobExecutionContext context, Throwable excep) throws JobExecutionException {
                              		// TODO: Gérer la politique de réessai, ex :
                              		// http://stackoverflow.com/questions/4408858/quartz-retry-when-failure
                              	
                              		if(jobExec == null)
                              			throw new IllegalArgumentException("jobExec cannot be null.");
                              		
                              		if(context == null)
                              			throw new IllegalArgumentException("context cannot be null.");
                              		
                              		String fireInstanceId =   context.getFireInstanceId();
                              		int refireCount = context.getRefireCount();
                              		
                              		if (log.isInfoEnabled())
                              			log.info("\n**********************************************************************\n" 
                              					+ "* Quartz trigger - rescheduling job: {}\n"
                              					+ "* Firing unique ID: {}\n" 
                              					+ "* Refire count: {}\n" 
                              					+ "**********************************************************************\n",
                              					new Object[] { jobName, fireInstanceId, refireCount});
                              		
                              		JobDataMap dataMap = context.getJobDetail().getJobDataMap();
                              		int maxRetry = dataMap.getIntValue(JOB_DATA_MAP_MAX_RETRY);
                              		
                              		JobExecutionException jobExecutionException = null;
                              		
                                      if(maxRetry>0 && refireCount<maxRetry) {        	
                                      	jobExecutionException = new JobExecutionException("Error: the job [" + jobName + "] didn't end properly, refire it immediately.", excep);
                                      	jobExecutionException.setRefireImmediately(true);
                                      	//boolean refireImmediatelyResult = jobExecutionException.refireImmediately();
                                      	
                                      	log.info("************** Job Id: {} - rescheduled. ", jobExec.getId());
                                      	
                                      	throw jobExecutionException;
                                      } else {
                                      	//jobExecutionException = new JobExecutionException("Error: the job [" + jobName + "] didn't end properly. No more retry possible, sending alarm.", excep);
                                      	
                                      	log.error("\n**********************************************************************\n" 
                              					+ "* Quartz trigger - No more retry possible for job: {}\n"
                              					+ "* Firing unique ID: {}\n" 
                              					+ "* UNSCHEDULING TRIGGER + SENDING EXPLOIT ALARM...\n"
                              					+ "**********************************************************************\n",
                              					jobName, fireInstanceId);
                                      	
                                      	AlarmDef alarmDef = AlarmExploit.searchBatchFailedAlarmDefByBatchName(jobName);
                                      	AlarmExploit.generateAlarmWithoutTemplate(alarmDef, "Batch failed", "The following batch failed (no more retry possible): " + jobName, Locale.ENGLISH.toString(), null);
                                      }
                              	}
                              
                              	@Override
                              	public void afterJob(JobExecution jobExecution) {
                              		// TODO Auto-generated method stub
                              			}
                              	
                              }
                              I also add an sleep for my job and when i run i have a message who said that my job is finished or it's nnot there but juste sleep.
                              Please can i have a response, exemple or others suggestions , i need some one to help me please

                              Thanks a lot

                              Comment

                              Working...
                              X