What would be the most correct thing to do in a public API that uses Type.GetType(typeName) under the hood?
//inside a message deserializer of a framework...
....
//1. throw TypeLoadException
var type = Type.GetType(typeName,true);
//2. or..
var type = Type.GetType(typeName,false);
if (type == null)
throw new SomeMoreSpecificException("Could not find message type " + typeName +", deserialization failed");
//3. or
Type type;
try
{
type = Type.GetType(typeName,true);
}
catch(TypeLoadException x)
{
throw new SomeMoreSpecificException("some message",x);
}
Which of the above approaches would you consider the most helpful for the end user in this case?
I leaning towards the latter case here, as you get both the real TypeLoadException and some additional information specific for this very usecase.
Or should we just consider the TypeLoadException itself to be enough for the end user?
Thoughts?
[edit] for more context, see
https://github.com/akkadotnet/akka.net/issues/1279
In Akka.NET we can do "remote deployment" of actors.
if the remote system receiving the deploy request does not know about the type that should be deployed, we need to notify this somehow.
Only throwing TypeLoadException feels a bit cheap, as it does not pinpoint the problem to the remote deploy scenario.
There's not a right and wrong answer here. The trade off is having more details available in the thrown exception versus the overhead of having two exceptions throws (the original one and the custom one) instead of one.
The question is - what do you expect the user to do with the exception you're throwing? Does the "some message" you provide give more detail than the original exception? Or does it let the user do something different if it gets that specific exception type? If not, I'd just let the original exception bubble up.
Related
I do realise that this is not the normal way of doing things, so I will explain a little first before asking the full question.
We are connecting to an external restful service which has 8 methods that we use. It returns a BaseResponse with a:
ResponseCode
ResponseDesc
Message
If the response code is -1 the operation was successful if not the code can be any one of about +-40 errors. To alleviate having a massive switch statement in each processor, I created a ResponseCodeHandler which lives in the project for the external service.
This handler interprets the code and throws the relevant fault with the message as follows:
throw new FaultException<OfflineFault>(new OfflineFault(), errorMessage);
Now since it seems* that almost every error can occur on every method I want to avoid having 40 catches in each processor - almost every error will need to be handled differently and I might as well have switch everywhere. I also can't just rethrow the error since certain items need to be set if a fault is thrown.
I would like to know if something like the following is possible (Where I need to find the OfflineFault in the catch):
try
{
throw new FaultException<OfflineFault>(new OfflineFault(), "description");
}
catch (FaultException e)
{
audit.SetStatus(AuditTransactionStatus.Error, e.Message);
throw faultsource.Build<OfflineFault>();
}
The faultsource just ensures that the error is logged everywhere etc.
I realise I could pass the audit and faultsource through but I would prefer not to since it would be a bit hacky in the current setup.
*Still awaiting feedback from external company
EDIT: Example of catch all as requested. I created an enum for all the codes to aid readability.
// all errors which must throw a offline fault
case ResponseCodes.HostUnavailable:
case ResponseCodes.HostTimeout:
throw faultSource.Build<OfflineFault>(operationName, errorMessage);
// Already registered faults
case ResponseCodes.UsernameAlreadyRegistered:
throw faultSource.Build<UsernameAlreadyRegisteredFault>(operationName, errorMessage);
case ResponseCodes.CellNumberAlreadyRegistered:
throw faultSource.Build<CellNumberAlreadyRegisteredFault>(operationName, errorMessage, ServiceFaultCode.CellNumber);
case ResponseCodes.EmailAlreadyRegistered:
throw faultSource.Build<EmailAlreadyRegisteredFault>(operationName, errorMessage, ServiceFaultCode.Email);
From everything I could find the above is NOT possible.
If you catch the base exception you cannot retrieve the original exception type.
i.e. If you catch Exception you won't be able to find out that it was thrown as a OfflineFault.
I have an application with three-tire architecture. And I don't understand how to work with exceptions in this context. I collected some questions:
1 . Do I need to create a generic exceptions, like PersistentException, and make all DAO classes methods to throw exeption only of one type - PersistentException? I.e. inside every DAO method (CRUD) do like this:
public create(Entity instance) {
try {
...// all operations here
} catch(Exception e) {
throw new PersistentException(e);
}
}
2 . It's OK to create one exception class for every EJB service (One exception per EJB interface)?
I.e. suppose I have a EJB beans like PersonManagementBean, OrganizationManagementBean, EmployeeManagementBean with corresponding #local and #remote interfaces. They are exposed to clients, i.e. in fact they are Session Facades (so they are located in service layer). So it's good idea to create corresponding Exception classes for every bean (PersonManagementException,OrganizationManagementException, EmployeeManagementException)?
Or it's better to have only one exception called ServiceException (as in case of DAOs)?
3 . What type of exceptions can throw my service (busyness) level (in common case)? Can I propagate DAO (PersistentException) exceptions to clients? i.e.
public void relocatePerson() {
try {
Person p = personDao.getPerson(); // can throw PersistentException
....
if (someCondition) {
throw new PersonManagementException(); // throwing same PersonManagementException
}
....
} catch(PersonManagementException e) {
throw e; //don't need to rewrap same exception
} catch(PersistentException e) {
throw e; // DO I need to throw it as PersistentException to client? Or it's better to rewrap it as PersonManagementException?
} catch(Exception e) {
throw new PersonManagementException(e) //throwing all exception as service specific exception
}
}
Or I need to rethrow all exceptions (in common case) as service-specific exceptions?
"In common case" I mean here that I know that in some cases some methods can throw additional exceptions with some helpful information (for example ValidationException with information about which objects don't pass validation rules)
Yes, you should make all DAO classes methods to throw exeption only of one type - PersistentException. Because it may help you to catch every kind of DB related exceptions into 1 type. Moreover, you can set messages about the particular exception while setting it into PersistantException using parametrized constructor. i.e. throw new PersistentException("Exception while opening a connection",e);
Your second question totally depends on your requirement. If you want to show different errors and showing different error pages and want to handle them (errors of each bean) separately then you should create separate exception class for each of your beans.
Your third question, as per my point of view its fine. You can propagate PersistentException to the level from where DAO or Helpers are being called first - i.e. ActionBean OR servlet.
There you can set your error messages and then you can throw them to your architecture level handlers (which is generally configured in configuration or xml files)
While working with exceptions dont forget that "to throw early and catch late"
For any exception that signals failure, use just one exception. Rationale: the client can't do anything in this case but log the stacktrace and/or report the error to the user.
I some special circumstances you'll need to throw an exception just to signal that an alternative approach to serving the request is needed. Only these cases need a specific exception.
The remote client will almost never want to know anything else than that a failure occurred; be very careful not to burden your remote interface with redundant exception classes.
Question 1 - practical
I run child process in my C# application using System.Diagnostics.Process. Like the following:
Process process = new Process();
// ... StartInfo initialization here
int timelimit_ms = 30000;
process.Start();
if (!process.WaitForExit(timelimit_ms))
{
// What exception to throw here?
throw new Excpetion(
"An executing method exceeded the time limit of " + timelimit_ms.ToString() + "ms");
}
I'm currently throwing System.ComponentModel.Win32Exception. But I don't sure it is the best choice. The child process is a simple command line utility. So the first question, what exception to throw in this situation?
Question 2 - thoretical
This is not the first time I ask myself about what exception to throw. And I don't know of a simple guidelines on how to pick a certain one. There are so much exceptions in C#, deeply inherited from one namespace to another. The second question, how to decide what exception to throw in a specific situation?
Practically, I'd throw a TimeoutException as it describes what is happening
Theoretically, if a quick google / read of the docs doesn't throw up an exception that already describes what is happening then you can just extend Exception to generate a WeirdThingThatHappensSometimesInMyApplication Exception.
But it depends who or what is going to "read" your exception. If your exception isn't exceptional then maybe you should do things differently :-)
how about a timeout exception?
I would think about throwing InvalidOperationException from the code.
As states MSDN, this exception is:
The exception that is thrown when a method call is invalid for the
object's current state.
So the caller of the function or consumer of the object that runs and waits for the process will be notified about the fact that execution of the function failed.
If you want to be detailed about declaration of the failure reason, you can express it
or in detailed message (if it's enough)
or create yuor own custom exception derived from InvalidOperationException and populate it with additional data you may need outside from the caller.
Exceptions sometimes occur. When they do, they're logged and later analyzed. The log obviously contains the stack-trace and other global information, but often crucial context is missing. I'd like to annotate an exception with this extra information to facilitate post-mortem debugging.
I don't want to try{...}catch{... throw;} since that counts as catching an exception and that makes debugging harder (during development I'd like the app to stop and the debugger to react when the original exception is thrown, and not when the outermost uncaught exception is). First-chance exception handlers aren't a workaround since there are unfortunately too many false positives.
I'd like to avoid excessive overhead in the normal, non-exceptional case.
Is there any way to store key pieces of context (e.g. filename being processed or whatever) in an exception in a way that doesn't catch the exception?
I am taking a shot at this building off of Adam's suggestion of Aop. my solution would be Unity rather than postsharp and the only question I would have is whether the exception is being caught inside of invoke, which it likely is...
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
//execute
var methodReturn = getNext().Invoke(input, getNext);
//things to do after execution
if (methodReturn.Exception != null)
methodReturn.Exception.Data.Add("filename", "name of file");
return methodReturn;
}
}
There is nothing wrong with the following pattern:
try
{
// Do Something
}
catch (GeneralException ex)
{
throw new SpecificException(
String.Format("More specifics ({0}) in message", someData),
moreContext,
new {even, more, context},
ex);
}
This is precisely the pattern to use, for instance, when the "Do Something" is to, say, open a file of some kind. The "SpecificException" might be "can't read configuration file".
I would not use AOP to catch the exceptions. Instead I would use the interception class to LOG the exception + all arguments to the method that threw the exception. And then let the original exception be thrown again
I currently have some code that delibratly throws an exception if the user sends me data that fails validation (see below). I like it because im sure any errors in the application are caught and handled. A am however worried the code being slow as throwing exceptions takes a lot of memory. Im also worried it might be "bad code". Whats your advice? Thanks
public class BTAmendAppointmentRequest
{
public DataLayer.WebserviceMessage AddBTAmendAppointmentRequest(DataLayer.BTAmendAppointmentRequest req)
{
DataLayer.WebserviceMessage rsp = new DataLayer.WebserviceMessage();
try
{
if (!String.IsNullOrEmpty(req.AppointmentReference))
req.AppointmentReference = req.AppointmentReference.Trim();
if (req.OrderRequestID < 1 || string.IsNullOrEmpty(req.AppointmentReference))
{
throw new Exception("Amend appointment failed, you must supply a valid appointment reference and order reference");
}
...Do other stuff
}
catch (Exception ex)
{
rsp = new Service.WebserviceErrorMessage(ex);
}
return rsp;
}
}
If you are expecting these errors, you should return error messages to the user, not throw exceptions.
Reserve exceptions to exceptional situations.
Apart from being expensive, the meaning of an exception, the semantics are that of something exceptional having happened. Validation failing is not exceptional, it is expected.
Having said that, seeing as you are on a web service, an exception is a reasonable thing to do, assuming you also validate before the service call. It is reasonable since a web service can be called by anything - validation may not have happened, and such errors should be exceptional. Additionally, at least with .NET web services, web exceptions are probably the best way to communicate such things back to the client.
Exceptions should be considered as last resort error trap. They should be "exceptional". Data input errors are not exceptions - they are very common, expected events. You shoudl handle validation issues with validation controls or processes, that handle them - display an error message and do not let the processing continue.
Your other problem is that you cannot easily do full form validation if the first error you encounter throws an exception. If I was filling out a form where each error was separately highlighted, I would give up very quickly. You need to be able to validate and display ALL errors on a page, and not permit progress without validation succeeding.
I tend to agree with Oded in that exceptions should only be used for stuff you aren't expecting. The other way to look at it is with using an errors collection, you are able to validate a larger batch instead of throwing an exception on the first problem. This can be more usable for the person consuming your service.
In the case of web services, I would package the entire response in a custom response object, which features a return code. This allows you to have a return code of error, and then encapsulate an errors collection in the response object.