Handle JobExecutionException in Quartz.net
Probably a stupid question... but here goes anyway...
I have set up quartz, and can schedule jobs, and I can confirm that jobs (implementing the IJob interface) are working.
Looking at the documentation on the site, (Lesson 3 of the tutorial):
The only type of exception that you are allowed to throw from the execute method is JobExecutionException
.
I would like that when an exception occurs that I haven't explicitly handled, it should throw a JobExecutionException, so that I can log it in the 'parent' application. I have wrapped my code in a try catch, and have thrown the JobExecutionException, but now where to handle it?
I don't call the execute method anywhere, that is handled by Quartz (on a separate thread). So, how do I handle that error when it occurs. I don't really want to swallow the error in the Job
33 Answers
I solved this problem by using a base class to catch all the exceptions:
public abstract class JobBase : IJob { protected JobBase() { } public abstract void ExecuteJob(JobExecutionContext context); public void Execute(JobExecutionContext context) { string logSource = context.JobDetail.FullName; try { ExecuteJob(context); } catch (Exception e) { // Log exception } } }
Your Job class should like this:
public class SomeJob : JobBase { public SomeJob() { } public override void ExecuteJob(JobExecutionContext context) { // Do the actual job here } }
10Typically you would set up the execute method of your job as follows:
try { // the work you want to do goes here } catch (ExceptionTypeYouWantToHandle1 ex1) { // handle exception } catch (ExceptionTypeYouWantToHandle2 ex2) { // handle exception } // and so on catch (Exception ex) { // something really unexpected happened, so give up throw new JobExecutionException("Something awful happened", ex, false); // or set to true if you want to refire }
At this point the scheduler itself will log the exception to wherever it is logging (based on the configuration).
6As already mentioned, the correct way to "detect" JobExecutionException's on a global level is to implement and register an IJobListener and check if the JobExecutionException parameter in the JobWasExecuted() method is != null.
However, the problem I had (and judging from the additional comment of the OP, he faced this too) was that Quartz did not handle the JobExecutionException (as it should) which resulted in an unhandled exception killing the application.
So far, I was using the precompiled DLL from the Quartz.NET 2.0.1 release (.NET3.5) package. To get to the bottom of the problem, i referenced the Quartz project/sourcecode and to my astonishment it was suddenly working?!
As a point of interest, this is the Quartz library code that executes the IJob and handles the JobExecutionException:
try { if (log.IsDebugEnabled) { log.Debug("Calling Execute on job " + jobDetail.Key); } job.Execute(jec); endTime = SystemTime.UtcNow(); } catch (JobExecutionException jee) { endTime = SystemTime.UtcNow(); jobExEx = jee; log.Info(string.Format(CultureInfo.InvariantCulture, "Job {0} threw a JobExecutionException: ", jobDetail.Key), jobExEx); } catch (Exception e) { // other stuff here... }
The next thing was to reference my freshly compiled DLL direcly and this was working as well. Sadly i can't tell you why this works and i currently don't have any time to get into it any further, but maybe this helps someone. Maybe some else can confirm this and even contribute an explanation. It may have something to do with different target platforms (x86/64bit)?
5ncG1vNJzZmirpJawrLvVnqmfpJ%2Bse6S7zGiorp2jqbawutJoamtsZmeEeHvHmqWdpJVit7CuxLGcnK2knryvsdecnKmsmaS7brXNZqiumaKpx266xK0%3D