Handle JobExecutionException in Quartz.net - c#

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

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
}
}

Typically 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).

As 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)?

Related

C# Cannot catch exceptions from another project within same solution

Got a strange problem: in a complex camera control program I'm working on, I use an SDK with a C# wrapper that was programmed by someone else. I include the wrapper as a separate project within the same solution. My own code is a WPF project that uses numerous calls into the SDK.
Everything synchronous works fine. However, depending on camera responses, the SDK occasionally sends asynchronous responses, usually in the form of throwing a custom exception with info about an error the camera reports. I implemented this using
try { ... } catch (ThisExceptionType) { ... }
However, NO exception ever gets caught. When an exception situation occurs, VisualStudio breaks, shows me the code where the SDK throws it and reports "ThisExceptionType was unhandled by user code", also showing the details of the exception condition (meaning it was apparently thrown properly). I verified that the exception corresponds with the error condition I created, so I'm sure I'm not looking at the wrong part of my code.
For testing purposes, I also replaced the line in the SDK where it throws ThisExceptionType with a standard exception, such as throw new ArgumentException("Test"); Same result: when changing my catch to catch (ArgumentException), I still cannot catch the condition and get a similar unhandled-by-user-code error.
Here's how the SDK throws the exception:
void CallEntryPoint( ...)
{
eNkMAIDResult result = _md3.EntryPoint(...);
switch (result)
{
// Note: Ignore these return values
case eNkMAIDResult.kNkMAIDResult_NoError:
case eNkMAIDResult.kNkMAIDResult_Pending:
break;
default:
throw new NikonException(...);
}
}
What am I missing here? Sorry if this is a simple issue - I'm pretty experienced in general programming but have not worked much with VisualStudio, and not a whole lot in C#, either.
UPDATE: According to the wrapper's author (this is actually Thomas Dideriksen's Nikon SDK wrapper), "when you're writing WPF or WinForms application, the C# wrapper relies on the inherent windows message queue to fire events on the UI thread."
He also states that the wrapper processes all camera tasks sequentially, so I guess my statement was incorrect about the wrapper throwing asynchronous exceptions - all code examples for the wrapper use the same try { ... } catch (ThisExceptionType) { ... } approach. For good measure, I tried some of your suggestions, for instance by hooking a handler to AppDomain.CurrentDomain.UnhandledException, but that approach failed to catch the exception, as well.
Any other ideas why this may be happening?
This article on MSDN may help. https://msdn.microsoft.com/en-us/library/dd997415(v=vs.110).aspx
There are differences in handling exceptions using Tasks in C#. Hopefully that will give a run down on different techniques you can use to handle the exceptions appropriately.
From the MSDN article:
Unhandled exceptions that are thrown by user code that is running
inside a task are propagated back to the calling thread, except in
certain scenarios that are described later in this topic. Exceptions
are propagated when you use one of the static or instance Task.Wait or
Task.Wait methods, and you handle them by enclosing the call
in a try/catch statement. If a task is the parent of attached child
tasks, or if you are waiting on multiple tasks, multiple exceptions
could be thrown.
And there are a couple solutions provided:
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );
try
{
task1.Wait();
}
catch (AggregateException ae)
{
foreach (var e in ae.InnerExceptions) {
// Handle the custom exception.
if (e is CustomException) {
Console.WriteLine(e.Message);
}
// Rethrow any other exception.
else {
throw;
}
}
}
}
}
public class CustomException : Exception
{
public CustomException(String message) : base(message)
{}
}
// The example displays the following output:
// This exception is expected!
Or you can do this:
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
var task1 = Task.Run( () => { throw new CustomException("This exception is expected!"); } );
while(! task1.IsCompleted) {}
if (task1.Status == TaskStatus.Faulted) {
foreach (var e in task1.Exception.InnerExceptions) {
// Handle the custom exception.
if (e is CustomException) {
Console.WriteLine(e.Message);
}
// Rethrow any other exception.
else {
throw e;
}
}
}
}
}
public class CustomException : Exception
{
public CustomException(String message) : base(message)
{}
}
// The example displays the following output:
// This exception is expected!
I hope that helps!

function that recalls itself upon a catch of non-critical error

I got a function named inner_logic() that can throw many types of exception , each of one of two types: critical and non-critical. The logic of inner_logic() includes an "infinite" loop, so in case of a non-critical exception I'd wish to step back in to it. At that point you can ask why not catching the non-critical exception within the loop, and the reason is that it's an abstract class with a few inheritors, each have a unique loop. for clarification, what I want to do is something like:
public void logic()
{
try
{
inner_logic();
}
catch (non_critical e)
{
// log
logic();
}
catch(critical e)
{
// log
return;
}
public virtual void inner_logic(){}
As far as I can tell, I seems that it should work, and that all calls are "catchable", but it feels kinda hackish.
My Question is: Is there a better way for doing that, or a reason I should reconsider my suggestion?
I did something similar in the past. I try to avoid recursion so I did a loop instead.
public void logic()
{
bool running = true;
while(running)
{
running = false;
try
{
inner_logic();
}
catch(non_critical e)
{
running = true;
}
}
}
Actually, I did it a bit diffrently. Instead of a boolean, I counted the number of non_critical errors. If the number exceded 3 then I handled it as a critical error.
You should not do it this way, as if the current state of the application means that the non- critical exception is thrown repeatedly, a stack overflow exception will occur.
Catch the exception outside the method and repeat if needed.
It feels to me like it should just be looping:
while (true) // Or probably have a maximum number of retries
{
try
{
// Logic
// Break out of the loop by returning if we succeed
return;
}
catch (NonCriticalException e)
{
// Log, then let the loop continue
}
catch (CriticalException e)
{
// Log, then rethrow (in preference to returning)
}
}
With your original approach, if the non-critical exception just keeps happening, you'll get a StackOverflowException. I would definitely suggest adding a maximum retry count though. (Keeping track of the number of retries is good for logging, too.)

Problems with the Using Statement and WCF client

I've been wrapping all the code that invoke WCF calls within an using statement in a thought that the object will be disposed properly. When I'm googling for an exception "Http service located at .. is too busy" I found this link http://msdn.microsoft.com/en-us/library/aa355056.aspx that says should not use using statement in typed proxies. Is that really true? I think I got a big code change (sigh). Is this problem comes only in typed proxies?
Sample code:
private ServiceClient proxy;
using(proxy = new ServiceClient("ConfigName", "http://serviceaddress//service.svc")){
string result = proxy.Method();
}
The core of the problem is: at the end of your using block (which generally is a very good idea to have!), the WCF proxy will be disposed. However, during disposing of the WCF proxy, exceptions can occur - and those will cause the app to misbehave. Since this is done implicitly at the end of the using block, you might not even really see where the error occurs.
So typically, Microsoft recommends a pattern something like this:
private ServiceClient proxy;
try
{
proxy = new ServiceClient("ConfigName", "http://serviceaddress//service.svc");
string result = proxy.Method();
proxy.Close();
}
catch (CommunicationException e)
{
// possibly log error, possibly clean up
proxy.Abort();
}
catch (TimeoutException e)
{
// possibly log error, possibly clean up
proxy.Abort();
}
catch (Exception e)
{
// possibly log error, possibly clean up
proxy.Abort();
throw;
}
You need to call the proxy.Close() method explicitly and be prepared to handle any exceptions that might occur from that call, too.
Wrap the proxy operation and instantiation calls up in a class implementing IDisposable. When disposing, check the state property of the proxy and tidy up the channel before closing.
public void Dispose()
{
if (this.MyProxy != null && this.MyProxy.State == CommunicationState.Faulted)
{
this.MyProxy.Abort();
this.MyProxy.Close();
this.MyProxy = null;
}
// ...more tidyup conditions here
}
I like the approach from the comment from "Eric" on this blog (which is similar to another article: http://redcango.blogspot.com/2009/11/using-using-statement-with-wcf-proxy.htm):
"Personally, I like to create my own partial class for the client and override the Dispose() method. This allows me to use the ‘using’ block as I normally would.
public partial class SomeWCFServiceClient : IDisposable
{
void IDisposable.Dispose()
{
if (this.State == CommunicationState.Faulted)
{
this.Abort();
}
else
{
this.Close();
}
}
}

Programmatically suppressing exceptions in C#

I have the following try-catch statement and I do not want to not throw the exception if the message property contains 'My error' in the text.
How can I programmatcially accomplish this? Also, would this be considered code-smell?
try
{
}
catch(Exception e)
{
if(e.Messages.Contains("My error"))
{
//want to display a friendly message and suppress the exception
}
else
{
throw e;
}
}
You shouldn't catch errors based on the error test. You should make your own exception class that extends exception:
class MyErrorException : Exception { }
and throw and catch those. (Excuse my syntax if it's wrong, I haven't done C# in a while).
That being said, throwing and catching your own Exceptions instead of propagating them is perfectly normal, and it is how you actually should do exception handling.
You should be catching the specific exception you're looking for. Quite frankly, that code is shocking. You should have something like ...
public class MyCoolException : Exception {
public MyCoolException(string msg) : base(msg) {}
}
public void MyCoolMethod() {
// if bad things happen
throw new MyCoolException("You did something wrong!");
}
Then later in your code you can use it like ...
try {
MyCoolMethod();
} catch (MyCoolException e) {
// do some stuff
}
Your code creates maintainability issues because a simple text change can have strange side effects. You can have your own exception class which inherits from System.Exception. Then instead of having an if you could do the following:
try
{
}
catch(MyException myException) //or just catch(MyException)
{
//display a friendly message
}
also you don't want to do throw e because it doesn't preserver the Stack, just throw; will do.
When I throw Exception rather than a derived class I always mean a failed assertion. I don't like failing out the backend because we are still able to receive a request (just not that one again). If we're really toast it will just error out on the next request anyway.
When the back end needs to generate an error message I have a ErrorMessage class that inherits from Exception and takes ErrorMessage and ErrorMessageTitle as constructor arguments.

Can a scope block with the "using" keyword react to exceptions?

I have the need to do some logging within my code. I'm required to use an internal company-developed library to record some information. Here's how it works.
Recorder recorder = Recorder.StartTiming();
DoSomeWork();
recorder.Stop(); // Writes some diagnostic information.
To ensure that Stop() is always called, I created a wrapper class that allows a clean "using" block.
using (RecorderWrapper recorderWrapper = new RecorderWrapper) // Automatically calls Recorder.StartTiming() under the covers
{
DoSomeWork();
} // When the recorderWrapper goes out of scope, the 'using' statement calls recorderWrapper.Dispose() automatically - which calls recorder.Stop() under the covers
it's worked well so far. However, there's a change my company is requiring, that would look something like this on the original code:
Recorder recorder = Recorder.StartTiming();
try
{
DoSomeWork();
}
catch (Exception ex)
{
recorder.ReportFailure(ex); // Write out some exception details associated with this "transaction"
}
recorder.Stop(); // Writes some diagnostic information.
I'd like to avoid try/catches in all my 'using' scope blocks with RecorderWrapper. Is there a way I can accomodate the "ReportFailure()" call and still leverage the 'using' scope block?
Specifically, I want everyone on my team to "fall into a pit of success", i.e. make it easy to do the right thing. To me, this means making it really hard to forget to call recorder.Stop() or forget the try/catch.
Thanks!
You might be able to create a method on the recorder to hide this:
public void Record(Action act)
{
try
{
this.StartTiming();
act();
}
catch(Exception ex)
{
this.ReportFailure(ex);
}
finally
{
this.Stop();
}
}
So your example would then just be:
recorder.Record(DoSomeWork);
You could always try something like:
Edit by 280Z28: I'm using a static StartNew() method here similar to Stopwatch.StartNew(). Make your Recorder class IDisposable, and call Stop() from Dispose(). I don't think it gets any more clear than this.
using (Recorder recorder = Recorder.StartNew())
{
try
{
DoSomeWork();
}
catch (Exception ex)
{
recorder.ReportFailure(ex);
}
}
You could continue to use the RecorderWrapper you have, but add a TryExecuting method that accepts a lambda of what you want to happen add runs it in a try/catch block. eg:
using (RecorderWrapper recorderWrapper = new RecorderWrapper) // Automatically calls Recorder.StartTiming() under the covers
{
recorderWrapper.TryExecuting(() => DoSomeWork());
}
Inside RecorderWrapper:
public void TryExecuting(Action work)
{
try { work(); }
catch(Exception ex) { this.ReportFailure(ex); }
}
You could copy the pattern used by TransactionScope, and write a wrapper that must be actively completed - if you don't call Complete(), then the Dispose() method (which gets called either way) assumes an exception and does your handling code:
using(Recorder recorder = Recorder.StartTiming()) {
DoSomeWork();
recorder.Complete();
}
Personally, though, I'd stick with try/catch - it is clearer for maintainers in the future - and it provides access to the Exception.
No, a using block is only syntactic sugar for a try/finally block. It doesn't deal with try/catch. At that point you're going to be left with handling it yourself since it looks like you need the exception for logging purposes.
A using block is effectively a try/finally block that calls dispose on the object in question.
So, this:
using(a = new A())
{
a.Act();
}
is (i think, exactly) equivalent to this:
a = new A();
try
{
a.Act();
}
finally
{
a.Dispose();
}
And you can tack your catches onto the end of the try block.
Edit:
As an alternative to Rob's solution:
Recorder recorder = Recorder.StartNew()
try
{
DoSomeWork();
}
catch (Exception ex)
{
recorder.ReportFailure(ex);
}
finally
{
recorder.Dispose();
}
Oops, I hadn't noticed that a new instance of Recorder was being created by StartTiming. I've updated the code to account for this. The Wrap function now no longer takes a Recorder parameter but instead passes the recorder it creates as an argument to the action delegate passed in by the caller so that the caller can make use of it if needed.
Hmmm, I've needed to do something very similar to this pattern, lambdas, the Action delegate and closures make it easy:
First define a class to do the wrapping:
public static class RecorderScope
{
public static void Wrap(Action<Recorder> action)
{
Recorder recorder = Recorder.StartTiming();
try
{
action(recorder);
}
catch(Exception exception)
{
recorder.ReportFailure(exception);
}
finally
{
recorder.Stop();
}
}
}
Now, use like so:
RecorderScope.Wrap(
(recorder) =>
{
// note, the recorder is passed in here so you can use it if needed -
// if you never need it you can remove it from the Wrap function.
DoSomeWork();
});
One question though - is it really desired that the catch handler swallows the exception without rethrowing it? This would usually be a bad practice.
BTW, I'll throw in an addition to this pattern which can be useful. Although, it doesn't sound like it applies to what you're doing in this instance: Ever wanted to do something like the above where you want to wrap some code with a set of startup actions and completion actions but you also need to be able to code some specific exception handling code. Well, if you change the Wrap function to also take an Action delegate and constrain T to Exception, then you've got a wrapper which allows user to specify the exception type to catch, and the code to execute to handle it, e.g.:
public static class RecorderScope
{
public static void Wrap(Action<Recorder> action,
Action<Recorder, T1> exHandler1)
where T1: Exception
{
Recorder recorder = Recorder.StartTiming();
try
{
action(recorder);
}
catch(T1 ex1)
{
exHandler1(recorder, ex1);
}
finally
{
recorder.Stop();
}
}
}
To use.. (Note you have to specify the type of exception, as it obviously cannot be inferred. Which is what you want):
RecorderScope.Wrap(
(recorder) =>
{
DoSomeWork();
},
(recorder, MyException ex) =>
{
recorder.ReportFailure(exception);
});
You can then extend this pattern by providing multiple overloads of the Wrap function which take more than one exception handler delegate. Usually five overloads will be sufficient - it's pretty unusual for you to need to catch more than five different types of exceptions at once.
Don't add another level of indirection. If you need to catch the Exception, use try..catch..finally and call Dispose() in the finally block.

Categories