With bluebird, let's say I want to catch an error and throw a different error.
DAO.getById('AccessTokens', token).then(function(matchingToken) {
return matchingToken;
}).catch(NotFoundError, function(err) {
Logging.error("caught a not found error"); // or some kind of logger...
throw err;
}).catch(function(err) {
throw ['DB Error - Tokens', err];
});
If I run this and a NotFoundError is thrown, I observe that the NotFoundError handler runs, then the generic error handler runs. I would like only the NotFoundError handler to run/propagate for a NotFoundError.
Is there a way to catch some errors and propagate them without also hitting the catchall error handler?
I could remove the catchall, but then it's possible for unknown errors to propagate. I could check for NotFoundErrors in the catchall, but that seems like duplicated behavior.. is there another option?
No, but let's talk about why
Currently - no, it was considered in the past but the use case was not convincing enough at the moment. Petka Gorgi and I discussed it in IRC at a point and generally agreed that using .catch(function(){ (a catch all) is not the greatest idea - not knowing what might fail is problematic and typically if you fail for a reason you don't know - you want to restart the server since it is unclear how you'd recover.
Personally, I'd just remove the catch-all - especially since it throws something that is not an error (so no stack trace, which is problematic and deteriorating in terms of debugging anyway). You can log errors globally and shut down gracefully.
I'm an adult and you're not the boss of me
Fine, you're right. The library is opinionated towards what I think are good error handling practices. Your opinion may vary and you can write a catch-all in the way you'd like. Sadly, I've been coding Haskell all day, so this might seem a little functional in style - you can always just catch types in the catch-all:
function typeT(type){
return function(item){ return item instanceof type; };
}
function not(fn){
return function(){ return !(fn.apply(this, arguments); };
}
DAO.getById('AccessTokens', token).then(function(matchingToken) {
return matchingToken;
}).catch(NotFoundError, function(err) {
Logging.error("caught a not found error"); // or some kind of logger...
throw err;
}).catch(not(typeT(NotFoundError)), function(err) { // predicate function catch clause
throw ['DB Error - Tokens', err];
});
Related
I have following code
IAsyncOperation<bool> trythiswork()
{
bool contentFound{ false };
try
{
auto result = co_await someAsyncFunc();
winrt::check_bool(result)
if (result)
{
contentFound = true;
}
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
}
co_return contentFound;
}
When the result is false, it fails and throws but catch goes to fail fast and program terminates. How does log function terminate the program? Isn't it supposed to only log the exception? I assumed that I am handling this exception so program won't crash but it is crashing.
So how to throw and catch so that program does not terminate? I do want to throw. And also catch and preferably log the exception as well.
Thanks
The issue can be reproduced using the following code:
IAsyncOperation<bool> someAsyncFunc() { co_return false; }
IAsyncOperation<bool> trythiswork()
{
auto contentFound { false };
try
{
auto result = co_await someAsyncFunc();
winrt::check_bool(result);
// throw std::bad_alloc {};
contentFound = true;
}
catch (...)
{
LOG_CAUGHT_EXCEPTION();
}
co_return contentFound;
}
int main()
{
init_apartment();
auto result = trythiswork().get();
}
As it turns out, everything works as advertised, even if not as intended. When running the code with a debugger attached you will see the following debug output:
The exception %s (0x [trythiswork]
Not very helpful, but it shows that logging itself works. This is followed up by something like
FailFast(1) tid(b230) 8007023E {Application Error}
causing the process to terminate. The WIL only recognizes exceptions of type std::exception, wil::ResultException, and Platform::Exception^. When it handles an unrecognized exception type it will terminate the process by default. This can be verified by commenting out the call to check_bool and instead throwing a standard exception (such as std::bad_alloc). This produces a program that will log exception details, but continue to execute.
The behavior can be customized by registering a callback for custom exception types, giving clients control over translating between custom exception types and HRESULT values. This is useful in cases where WIL needs to interoperate with external library code that uses its own exception types.
For C++/WinRT exception types (based on hresult_error) the WIL already provides error handling helpers that can be enabled (see Integrating with C++/WinRT). To opt into this all you need to do is to #include <wil/cppwinrt.h> before any C++/WinRT headers. When using precompiled headers that's where the #include directive should go.
With that change, the program now works as desired: It logs exception information for exceptions that originate from C++/WinRT, and continues to execute after the exception has been handled.
mSubscriptions.add(api.signIn(phoneNumber, otp)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError(throwable -> Timber.e(throwable.getMessage()))
.onErrorResumeNext(throwable -> Observable.empty())
.subscribe(user -> {
// Handle user object logic here
}
}));
I generally use this pattern in all my apps for the schedulers and to handle exceptions, but sometimes i get an illegal state exceptions like this : Exception thrown on Scheduler.Worker thread. Add onError handling. Caused by rx.exceptions.OnErrorNotImplementedException, so i was wondering if this is right.
Thanks in advance.
As #yosriz mentioned - the right way is to implement onError callback in every subscriber. In your case, you're getting OnErrorNotImplementedException most likely due to your "Handle user object logic" throws.
Simple examples:
Exception in the stream:
Observable.just("value")
.flatMap(s -> Observable.error(new IllegalStateException()))
.onErrorResumeNext(t -> Observable.empty())
.doOnCompleted(() -> System.out.println("Completed"))
.subscribe(s -> {});
Completed
Exception in onNext callback:
Observable.just("value")
.onErrorResumeNext(t -> Observable.empty())
.doOnCompleted(() -> System.out.println("Completed"))
.subscribe(s -> {
throw new IllegalStateException();
});
rx.exceptions.OnErrorNotImplementedException
...
Caused by: java.lang.IllegalStateException
Exception in onNext callback, subscriber's onError implemented:
Observable.just("value")
.onErrorResumeNext(t -> Observable.empty())
.doOnCompleted(() -> System.out.println("Completed"))
.subscribe(s -> {
throw new IllegalStateException();
}, t -> {
System.out.println("Subscriber's onError triggered");
});
Subscriber's onError triggered
Arranging Schedulers has nothing to do with this type of error you get. The problem can happen if you don't have onError() handling on your subscriber (at the subscribe() method), and you get error somewhere in the stream without any handling.
doOnError() will not solve this, as it's just a side effect operator that will perform some operation with any onError().
In fact, In your example onErrorResumeNext() will handle the error as it will swallow any error, so probably you have other scenarios, where you do not handle all errors scenarios and thus got the on error not implemented exception.
As a general pattern, it's always better to prepared to any case and implement onError() at the subscriber to avoid cases where error was not handled down the stream.
i have a simlple asynchronious reader in a node-script reading firefox-json-bookmarks.
when i remove the first parameter (err) in the callback function, i got an error.
what is the reason? And why is err different from e?
app.js
var fs = require('fs'), obj;
fs.readFile(__dirname + '/bookmarks.json', 'utf8', handleFile);
function handleFile( err, data ) { // why is the first parameter needed?
try {
obj = JSON.parse( JSON.stringify(data) );
console.log(obj);
} catch (e) {
console.log(e);
//console.log(err);
}
}
Each time you call a function, that function is pushed onto a stack of functions known as the call stack. When that function returns a value, it is popped off the stack. The call stack describes where you are in your program and how you got there.
Synchronous Code
Imagine the call stack through out the course of this program.
function a() { return b() }
function b() { return c() }
function c() { throw new Error() }
a();
First, a is called, so we add it to the stack.
[ a ]
Then a calls b, so we add that to the stack too.
[ a, b ]
Then b calls c.
[ a, b, c ]
Then c throws an error. At this point, the debugger can tell you that c was the function that threw the error and that you ended up at c, via a then b. This works fine for regular synchronous code, like JSON.parse.
Asynchronous Code
Asynchronous code continues to run after the function has returned. For instance:
function a() {
setTimeout(function() { console.log(2); }, 10000);
return 1;
}
If you call a, then it will be pushed onto the call stack, then return 1 and be popped off the call stack. About 10 seconds later 2 will be printed into the console.
What would happen if the timeout did this instead?
function a() {
setTimeout(function() { throw new Error(); }, 10000);
return 1;
}
The error would be thrown, but the call stack would be empty. As you can imagine, this isn't very useful for developers.
This is also a problem if we want to return a value asynchronously. By the time the async stuff happens (timeout, read/write, network etc), the function has already returned.
Instead, we can use a form of what's known as Continuation-Passing Style, mostly referred to as callbacks. As well as calling our asynchronous function, we also pass it function (a continuation), which we ask it to run when it has finished. Remember, this can be after the function has returned a value!
In Node.js, these callbacks serve two purposes:
Errors
If an error occurs whilst doing the asynchronous work, standard practice is to call the callback with the error as the first argument. You'll often see the following code.
foo.doAsyncBar(function(err, baz) {
if(err) throw err;
// do something with baz
});
By passing the error the callback rather than throwing it, we are able to make our own decisions about how best to handle it. We can just throw it, as shown above, or we can handle it in a more graceful way.
Return
Hopefully, the function won't error, in which case, the general practice is to pass null as the first argument to the callback. This lets the developer writing the handling code know that the function didn't error and that the return value is in one of the next arguments.
For a more in depth article on Node.js error handling, see Joyent's Production Practices document for Errors.
I have a service method which does some operation inside a transaction.
public User method1() {
// some code...
Vehicle.withTransaction { status ->
// some collection loop
// some other delete
vehicle.delete(failOnError:true)
}
if (checkSomething outside transaction) {
return throw some user defined exception
}
return user
}
If there is a runtime exception we dont have to catch that exception and the transaction will be rolled back automatically. But how to determine that transaction rolled back due to some exception and I want to throw some user friendly error message. delete() call also wont return anything.
If I add try/catch block inside the transaction by catching the Exception (super class) it is not getting into that exception block. But i was expecting it to go into that block and throw user friendly exception.
EDIT 1: Is it a good idea to add try/catch arround withTransaction
Any idea how to solver this?? Thanks in advance.
If I understand you question correctly, you want to know how to catch an exception, determine what the exception is, and return a message to the user. There are a few ways to do this. I will show you how I do it.
Before I get to the code there are a few things I might suggest. First, you don't need to explicitly declare the transaction in a service (I'm using v2.2.5). Services are transactional by default (not a big deal).
Second, the transaction will automatically roll back if any exception occurs while executing the service method.
Third, I would recommend removing failOnError:true from save() (I don't think it works on delete()... I may be wrong?). I find it is easier to run validate() or save() in the service then return the model instance to the controller where the objects errors can be used in a flash message.
The following is a sample of how I like to handle exceptions and saves using a service method and try/catch in the controller:
class FooService {
def saveFoo(Foo fooInstance) {
return fooInstance.save()
}
def anotherSaveFoo(Foo fooInstance) {
if(fooInstance.validate()){
fooInstance.save()
}else{
do something else or
throw new CustomException()
}
return fooInstance
}
}
class FooController {
def save = {
def newFoo = new Foo(params)
try{
returnedFoo = fooService.saveFoo(newFoo)
}catch(CustomException | Exception e){
flash.warning = [message(code: 'foo.validation.error.message',
args: [org.apache.commons.lang.exception.ExceptionUtils.getRootCauseMessage(e)],
default: "The foo changes did not pass validation.<br/>{0}")]
redirect('to where ever you need to go')
return
}
if(returnedFoo.hasErrors()){
def fooErrors = returnedFoo.errors.getAllErrors()
flash.warning = [message(code: 'foo.validation.error.message',
args: [fooErrors],
default: "The foo changes did not pass validation.<br/>${fooErrors}")]
redirect('to where ever you need to go')
return
}else {
flash.success = [message(code: 'foo.saved.successfully.message',
default: "The foo was saved successfully")]
redirect('to where ever you need to go')
}
}
}
Hope this helps, or gets some other input from more experienced Grails developers.
Here are a few other ways I've found to get exception info to pass along to your user:
request.exception.cause
request.exception.cause.message
response.status
A few links to other relevant questions that may help:
Exception handling in Grails controllers
Exception handling in Grails controllers with ExceptionMapper in Grails 2.2.4 best practice
https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html
I have an if condition which checks for value and the it throws new NumberFormatException
Is there any other way to code this
if (foo)
{
throw new NumberFormatException
}
// ..
catch (NumberFormatException exc)
{
// some msg...
}
If you are doing something such as this:
try
{
// some stuff
if (foo)
{
throw new NumberFormatException();
}
}
catch (NumberFormatException exc)
{
do something;
}
Then sure, you could avoid the exception completely and do the 'do something' part inside the conditional block.
If your aim is to avoid to throw a new exception:
if(foo)
{
//some msg...
} else
{
//do something else
}
Don't throw exceptions if you can handle them in another, more elegant manner. Exceptions are expensive and should only be used for cases where there is something going on beyond your control (e.g. a database server is not responding).
If you are trying to ensure that a value is set, and formatted correctly, you should try to handle failure of these conditions in a more graceful manner. For example...
if(myObject.value != null && Checkformat(myObject.Value)
{
// good to go
}
else
{
// not a good place to be. Prompt the user rather than raise an exception?
}
In Java, you can try parsing a string with regular expressions before trying to convert it to a number.
If you're trying to catch your own exception (why???) you could do this:
try { if (foo) throw new NumberFormatException(); }
catch(NumberFormatexception) {/* ... */}
if you are trying to replace the throwing of an exception with some other error handling mechanism your only option is to return or set an error code - the problem is that you then have to go and ensure it is checked elsewhere.
the exception is best.
If you know the flow that will cause you to throw a NumberFormatException, code to handle that case. You shouldn't use Exception hierarchies as a program flow mechanism.