How to force play framework to log exceptions which are thrown in another thread? - exception

I have a function which is running in the separate thread. The code which calls this function not waits for result of it.
def sendEmail(email: String): Future[Unit] = {
...
}
def registration: Future[User] = {
...
// I do not want to wait for result of this function, just fire email sending
// in seprate thread and continue
sendEmail(email)
...
// Do another job
}
The problem is that if something went wrong in sendEmail function, I want to see this exception in log file.
Now log file and console output are empty if some exception is thrown there.
Is there a way to log exceptions from that separate thread?
P.S.: I do not want to log exception manually in sendEmail, but force play framework to log it.

In general, you wrap exceptions in the exceptionally block.
In java, it's like :
foobar.thenComposeAsync(arg -> {
sendEmail();
}).exceptionally(throwable -> {
// Do logging
});

Related

C++Winrt how to throw and handle exception without terminating program

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.

How to know exception occurred within grails transaction?

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

Grails UnexpectedRollbackException occurred: Not Sure Why

I have the following code:
class ServiceA {
def save(Object object) {
if (somethingBadComesBack) {
throw new CustomRuntimeException(data)
}
}
}
class ServiceB {
def serviceA
def save(Object object) {
try {
serviceA.save(object)
// do more stuff if good to go
} catch(CustomRuntimeException e) {
// populate some objects with errors based on exception
}
}
}
class ServiceC {
def serviceB
def process(Object object) {
serviceB.save(object)
if (object.hasErrors() {
// do some stuff
}else{
// do some stuff
}
def info = someMethod(object)
return info
}
}
class SomeController {
def serviceC
def process() {
def object = .....
serviceC.save(object) // UnexpectedRollbackException is thrown here
}
}
When ServiceA.save() is called and an exception occurs, ServiceC.save() is throwing an UnexpectedRollbackException when it tries to return.
I did the following:
try {
serviceC.process(object)
}catch(UnexpectedRollbackException e) {
println e.getMostSpecificCause()
}
and I am getting:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
I'm not sure where to start looking for how to fix this.
You're using a runtime exception to roll back the transaction, but that's cheating - it's taking advantage of a side effect. Runtime exceptions roll back transactions automatically since you don't need to catch them so it's assumed that if one is thrown, it wasn't expected and the default behavior is to roll back. You can configure methods to not roll back for specific expected runtime exceptions, but this is somewhat rare. Checked exceptions don't roll back exceptions because in Java they must be caught or declared in the throws, so you have to have either explicitly thrown it or ducked it; either way you had a chance to try again.
The correct way to intentionally roll back a transaction is to call setRollbackOnly() on the current TransactionStatus but this isn't directly accessible in a service method (it is in a withTransaction block since it's the argument to the closure). But it's easy to get to: import org.springframework.transaction.interceptor.TransactionAspectSupport and call TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(). This will required that you rework your code since there won't be an exception to catch, so you'll need to check that it was rolled back with TransactionAspectSupport.currentTransactionStatus().isRollbackOnly().
I'm not sure if it's a Grails issue or standard behavior, but when I was debugging this there were 3 commit calls with 3 different TransactionStatus instances. Only the first had the rollback flag set, but the second was aware of the first and was ok. The third one was considered a new transaction and was the one that triggered the same exception that you were seeing. So to work around this I added this to the 2nd and 3rd service methods:
def status = TransactionAspectSupport.currentTransactionStatus()
if (!status.isRollbackOnly()) status.setRollbackOnly()
to chain the rollback flag. That worked and I didn't get the UnexpectedRollbackException.
It might be easier to combine this with a checked exception. It's still overly expensive since it will fill in the stacktrace unnecessarily, but if you call setRollbackOnly() and throw a checked exception, you will be able to use the same general workflow you have now.
It seems like the default transactionality of services is biting you, and the unchecked exception thrown in Service A is dooming the transaction to rollback only, even once caught.
The above docs say the txn propagation level is PROPAGATION_REQUIRED, which should mean the same transaction is shared from your service C on up to A, if my memory serves me. Can you have Service A's save method throw a checked exception instead of RuntimeException, to avoid the auto-rollback from the latter? Or disable transactions on your services, if that's an option for you?

Main thread exception handler in Groovy script

Having a problem with Groovy, I need to do some clean-up before exiting if uncaught exception was thrown in script, but can't find a way to do that.
I've tried Thread.setDefaultUncaughtExceptionHandler, but seems it's not working for the main thread. Then, I have had a look stack trace, which lead me to GroovyStarter where I found that nice piece of code, which means that Thread.setDefaultUncaughtExceptionHandler is not really supposed to work:
public static void main(String args[]) {
try {
rootLoader(args);
} catch (Throwable t) {
t.printStackTrace();
}
}
just for the sake of example here is what I want to archive (this is not runnable script, just to show the concept):
def process = new ProcessBuilder(command).redirectErrorStream(true).start();
onException = {
process.destroy()
}
Please, do not suggest to use try/catch, that's something I can think of myself :)
PS: I'm a newbie to Groovy, so could be missing some obvious stuff.
You could add a shutdown hook, which will always run (if possible) when the program exits:
def process = new ProcessBuilder(command).redirectErrorStream(true)
boolean success = false
def cleanup = {
success = true
process.destroy()
}
addShutdownHook {
if(!success && process) {
cleanup()
}
}
process.start()
// alternatively, always rely on the shutdown hook
cleanup()
Note that the shutdown hook always runs, even if the program exits cleanly, so you would need to have some way of tracking that you ran your cleanup already if you want to clean up your connections early.
You can also have as many shutdown hooks as you want, so this could be used inside a function if you have multiple things to clean up.

grails rollback db operation on some error

I have a service where to save a lot of data to db.
Using MYSQL
I have used like this
Domain1.withTransaction {text->
def domain1=//Create my domain object to save
if(!domain1.save()){
domain1.errors.each {
println it
}
throw new RuntimeException('unable to save domain1')
}
Domain2.withTransaction {text->
def domain2=//Create my domain object to save
if(!domain2.save()){
domain2.errors.each {
println it
}
throw new RuntimeException('unable to save domain2')
}
My problem if there occurred any problem in saving domain2 i need to roll back domain1 save also.
I need to remove domain1 from db.
Instead of using programatic transaction handling, the Service artifact allows for automatic transaction handling. This typically leads to cleaner and more maintainable code.
You can also use the failOnError:true when you save() to force a RuntimeException to be thrown.
Example below:
class SomeService {
static transactional = false
def serviceMethod() {
def domain1=//Create my domain object to save
def domain2=//Create my domain object to save
domain1.save(failOnError:true)
domain2.save(failOnError:true)
}
}
UPDATE
I'm revisiting this topic, after I read a response to another topic. Grails Integration Test Does NOT Rollback
Please verify that your dialect is setup as InnoDB as MyISAM tables aren't transactional. This is configured in your Config.groovy
dataSource {
dialect= org.hibernate.dialect.MySQLInnoDBDialect
...
}
Try removing the Domain2.withTransaction {text-> part.
You are already inside a transaction with your first call.
If you do further work inside the brackets, you should stay within the same transaction and domain1 should be rolled back if you throw and exception after checking domain2.
Put that Domain2.withTransaction closure inside Domain1.withTransaction closure, so error in Domain2 transaction will rollback both Domain1 and Domain2 transaction
Like this
Domain1.withTransaction {
//....
Domain2.withTransaction {
//....
}
}
If you just want a single transaction which is rolled back when an unhandled unchecked exception is thrown, then don't start a nested transaction. The necessaary code changes are shown below:
Domain1.withTransaction {text->
def domain1=//Create my domain object to save
if (!domain1.save()) {
domain1.errors.each {
println it
}
throw new RuntimeException('unable to save domain1')
}
def domain2=//Create my domain object to save
if (!domain2.save()) {
domain2.errors.each {
println it
}
throw new RuntimeException('unable to save domain2')
}
}