I am trying to handle exceptions in a Neo4j try transaction.
try(Transaction tx = graphDb.beginTx()) {
// more code
tx.sucess();
}
The code I posted is standard, it keeps the transaction in variable tx and upon the end of the try block tx.close() will automatically be called.
Hows does one handle exceptions in this type of block? I know the following works:
Transaction tx = graphDb.beginTx();
try{
// more code
tx.sucess(); // must always be called like so
} catch(Exception e) {
tx.failure(); // as an exception arised, would be best to call this.
} finally {
tx.close(); // is tx.close called automatically, or must I call it like I did here?
}
So really I have two questions, the first sample of code: how does one handle exceptions in that one?
Second sample of code: what must I call explicitly and what is automatically called?
Simply add the exception handling, but omit the finally:
try(Transaction tx = graphDb.beginTx()) {
// more code
tx.sucess();
} catch(Exception e) {
// ..
}
Related
For some reasons, I have to intercept send and receive messages. (Wrap up the message and parse the message when it is received).
I know MessagePostProcessor is a form of interceptor, but it will influence current code. So, I am considering using Spring AOP.
For sending messages, I can simply intercept RabbitTemplate’s send and convertAndSend methods, Like the following code:
#Around("execution(* org.springframework.amqp.rabbit.core.RabbitTemplate.send(..))")
But for receiving messages, Which method is best to intercept? In most cases, RabbitListener is used to receive messages.
Any help is appreciated.
Add an Advice to the listener container's adviceChain. See https://docs.spring.io/spring-amqp/docs/2.2.10.RELEASE/reference/html/#containerAttributes
EDIT
#Bean
public MethodInterceptor advice() {
return invocation -> {
Message message = (Message) invocation.getArguments()[0];
try {
// before
invocation.proceed();
// after
}
catch (Exception e) {
// ...
throw e;
}
finally {
// ...
}
return null;
};
}
i am unable to end response in case of some condition
eg below (in Upload Action Method), if Logerror method invoked i just want to return view(browser) without further action. i.e return from Upload Action Method.
Plase find modified question what i am trying to achive,
In case of error i want to return view by stopping all further opeartion
public ActionResult Index()
{
return View();
}
public ActionResult Upload()
{
int i=1;
DoSomethingFirst();
//if LogError i dont want execute code below, rather it should end responce
//should not reach here
string s="This should not be executed in case of LogError()";
return View("Index");
}
public void DoSomethingFirst()
{
try{
DoSomethingSecond();
}
catch(exception ex)
{
LogError();
}
}
public void DoSomethingSecond()
{
try{
DoSomethingThird();
}
catch(exception ex)
{
LogError();
}
}
public void DoSomethingThird()
{
try{
DoSomethingother();
}
catch(exception ex)
{
LogError();
}
}
private LogError()
{
Viewbag.Error="Error details";
return View("Index");
}
This doesn't return a result from the current method:
DoSomething();
But this does:
return DoSomething();
If you want to end execution of the current method, you need to do something which exits the method. Basically, either return from the method or throw an exception. Since DoSomething returns a result, presumably you want to return that result. So simply add a return statement when invoking the method.
i tried wit RedirectToAction("Index");
Same issue. You'd need to return the result:
return RedirectToAction("Index");
Edit: Based on your edit to the question, the overall concept still remains. Focusing on this part of your code here:
var s = DoSomethingFirst();
//if true i dont want execute code below, rather it should end responce
//should not reach here
In order to exit the method, any method in C#, you need to either return or throw. So the first question is... Which do you want to do here? If you want to return a redirect, for example, then return a redirect:
return RedirectToAction("SomeAction");
If you want to return the default view, return that:
return View();
If you want to throw an exception:
throw SomeException("Some Message");
The choice is yours. You just need to define:
What you want this method to return or throw under this condition.
How will you know the condition.
For that second point, your code comment says:
//if true ...
Does this mean DoSomethingFirst() returns a bool indicating success or failure? Then that would be a simple if statement:
if (!DoSomethingFirst())
return View();
Another Edit: Based on your comment below:
Inside LogError mehod called by any child method in action method, i want to update view with error message and end the operation without further operation
How will your Update method know that something it invoked internally called LogError()? What information does DoSomethingFirst() return to indicate this fact? Currently it doesn't. Your various DoSomething methods are all swallowing exceptions, which means they are internally handling exceptions so that consuming code doesn't know about them.
If you want consuming code to know about an exception, re-throw that exception. For example:
public void DoSomethingFirst()
{
try
{
DoSomethingSecond();
}
catch(exception ex)
{
LogError();
throw; // <-- this will re-throw ex without modifying it
}
}
This returns information from DoSomethingFirst(), specifically the fact that an error occurred. Your consuming code can then check for that error:
try
{
DoSomethingFirst();
}
catch (Exception ex)
{
// You should *probably* do something with ex too. So far all of your "logging" has been ignoring the actual error.
return View();
}
Regardless of the structure you build, the basics don't change. In order for consuming code to know something about the code it invokes, that invoked code has to expose that information. In order to end execution of a method, you have to either return or throw. Don't hide exceptions from consuming code if you want consuming code to respond to those exceptions.
In old-fashioned sync code, you can always assure your program won't crash completely by encapsulation your source code to the one big try catch block as in example:
try {
// Some piece of code
} catch (e) {
logger.log(e); // log error
}
However in Dart, when using Futures and Streams, it is not so easy. Following example will crash your application completely
try {
doSomethingAsync().then((result) => throw new Exception());
} catch (e) {
logger.log(e);
}
It doesn't matter that you have code inside the try-catch block.
Yes, you can always use Future.catchError, unfortunately, this won't help you if you are using third-party library function as following:
void someThirdPartyDangerousMethod() {
new Future.value(true).then((result) => throw new Exception());
}
try {
// we can't use catchError, because this method does not return Future
someThirdPartyDangerousMethod();
} catch (e) {
logger.log(e);
}
Is there a way to prevent the untrusty code to break whole your application? Something like global error handler?
You can use the brand new Zones. Just run your code inside the Zone and attach error handler to it.
void someThirdPartyDangerousMethod() {
new Future.value(true).then((result) => throw new Exception());
}
runZoned(() {
// we can't use catchError, because this method does not return Future
someThirdPartyDangerousMethod();
}, onError: (e) {
logger.log(e);
});
This should just work as expected! Every uncatched error will be handled by the onError handler. One thing is different to the classical example with try-catch block. The code running inside the Zone won't stop when error occurs, error is handled by onError callback and the application continues.
I'm trying to implement exception handling for Optimistic lock type exceptions that are thrown by Hibernate but I've encountered a strange issue. It seems I'm unable to catch any Gorm exceptions.
For example I have this code in my service:
try {
User user = User.get(1);
Thread.sleep(10000);
user.viewedAt(new Date());
user.save(flush:true);
} catch (OptimisticLockingException ex) {
log.error("Optimistic lock exception");
} catch (StaleObjectStateException ex) {
log.error("Optimistic lock exception");
}
When I hit this block with two threads, it blows up and the exception propagates to Grails' standard exception handler. The catch blocks are never invoked even though the reported exception is StaleObjectStateException.
I've noticed that I can catch the exception if I let it propagate to the controller and catch it there, but it seems I can't implement exception handling in the service which is weird.
What am I missing?
I got to the bottom of this and I'm posting it in case anyone else runs into this. The issue occurred because the try/catch block was in a transactional service. Although grails reported that the exception was thrown during the save() call, in reality it was called AFTER the entire method, when the transaction was committed.
So it seems that:
flush: true has no effect on transactional services
It's not possible to catch GORM related exceptions in transactional services, at least not without some work
I finally worked around this by manually managing the transaction myself i.e.
try {
User.withNewTransaction {
User user = User.get(id); // Must reload object
.. // do stuff
user.save(flush:true)
}
} catch (OptimisticLockingException ex) {
...
}
I hope this is of use to someone else!
I spent some time working on this problem and have written a more complete solution to handle the case of an optimistic locking exception in Grails.
Firstly, though the exception reported in the stack trace is StaleObjectStateException, the actual exception that gets thrown is HibernateOptimisticLockingFailureException (not "OptimisticLockingException"). Secondly, if you want to generalize this to handle arbitrary closures which modify domain objects, you need to rethrow exceptions thrown inside the closure.
The following static function will take an object and a closure that operates on the object, save it, and if it fails, retry again until it succeeds:
public static retryUpdate(Object o, Closure c) throws Exception {
def retVal
int retryCount = 0
while (retryCount < 5) {
try {
Model.withTransaction { status ->
retVal = c(status)
o.save()
}
return retVal
} catch (HibernateOptimisticLockingFailureException e) {
log.warn "Stale exception caught saving " + o
if (++retryCount >= 3) { // if retry has failed three times, pause before reloading
Thread.sleep(1000)
}
o.refresh()
} catch (UndeclaredThrowableException e2) {
// rethrow exceptions thrown inside transaction
throw e2.getCause()
}
}
return null
}
Model in this case is any GORM model class, doesn't matter which one. In particular it doesn't matter if it is the class of the passed-in object.
Example of use:
AnotherModelClass object = AnotherModelClass.get(id)
retryUpdate(object) {
object.setField("new value")
}
How to catch duplicate key exceptions in Grails . when trying to save existing integer for a unique column constraint, the error is generating while saving/updating a record .
Also used
try{
object.save(flush:true)
}
catch(org.springframework.dao.DataIntegrityViolationException e){
println e.message
}
catch(org.hibernate.exception.ConstraintViolationException ex){
println e.message
}
catch(Exception e){
println e.message
}
But unable to catch this issue .
23:41:13,265 ERROR [JDBCExceptionReporter:101] Duplicate entry '1' for
key 2 23:41:13,281 ERROR [AbstractFlushingEventListener:324]
Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not
execute JDBC batch update at
org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
at
org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at
org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at
org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at
org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
at
org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at
org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
Could you please share the solution to solve this .
You're trying to save a record with an id that already exists.
If id is auto-generated, don't set it manually
If id is not auto-generated, set it to something else, for example max(id) + 1
surely no Exception should be thrown for constraint violation, but rather object.save() should return null? i.e.
if(object.save() == null) {
// save failed
} else {
// save succeeded
}
If you defined the uniqueness through a Grails constraint, you have to look for a ValidationException. This is thrown when object.validate() fails; Validation is done before any object.save().
try {
object.save(failOnError: true)
}
catch(ValidationException ve) {
// Do something ...
}
But remember: Any constraint violation, for any member variable can cause a ValidationException ... so you have to distinguish yourself.
Edit:
This applies, if you use the Grails 1.2 failOnError feature ...
I am looking for the same problem so maybe not a complete answer but what you can do is to force validation and look in the errors, identify the case and place the actions you want:
if(instance.validate()) {
//everything ok
} else {
instance.errors.each {
//identify the case and place actions
}
}
Also note that error is: className.propertyName.unique
Possibly it should work:
import org.springframework.dao.DuplicateKeyException
try {
domainInstance.save(flush: true)
} catch(DuplicateKeyException e) {
// ...
}