class MyRouteBuilder extends SpringRouteBuilder {
public void configure() throws Exception {
//initialize camel context here
onException(ChildException.class)
.process(new ChildExceptionHandler())
.handled(true)
.to(errorURI);
onException(ParentException.class)
.process(new ParentExceptionHandler())
.handled(true)
.to(errorURI);
from(startURI)
.processRef("someBeanID")
//other processing here
}
}
Now my "someBeanID" throws ChildException while processing, but ParentExceptionHandler is being invoked for that. Code snippet in "someBeanID" is as below
try {
//some processing
throws new ParentException();
} catch (ParentException e) {
throw new ChildException(e); //being handled by ParentExceptionHandler (why?? should be ChildExceptionHandler??)
throw new ChildException(); //being handled by ChildExceptionHandler (should be)
}
It seems that whenever we wrap any exception, Camel automatically finds the actual wrapped exception and invokes handler for that, instead of invoking handler for wrapper exception. Why is this? Is there any problem in my code ??
Thanks,
Finally resolved....Refer to this
When trapping multiple exceptions, the order of the onException clauses is significant. Apache Camel initially attempts to match the thrown exception against the first clause. If the first clause fails to match, the next onException clause is tried, and so on until a match is found. Each matching attempt is governed by the following algorithm:
If the thrown exception is a chained exception (that is, where an exception has been caught and rethrown as a different exception), the most nested exception type serves initially as the basis for matching. This exception is tested as follows:
If the exception-to-test has exactly the type specified in the onException clause (tested using instanceof), a match is triggered.
If the exception-to-test is a sub-type of the type specified in the onException clause, a match is triggered.
If the most nested exception fails to yield a match, the next exception in the chain (the wrapping exception) is tested instead. The testing continues up the chain until either a match is triggered or the chain is exhausted.
Related
In the following test code, I make a declaration: when the get() method is called with argument 0, then an exception should be thrown out. In my opinion, if the argument is not 0, the exception should not be thrown out. But, the test was passed. That means get(1) has caused an exception was thrown. Is this a bug of Mockito?
#RunWith(MockitoJUnitRunner.class)
public class MockitoTest {
#Mock
private List<Integer> mockedList;
#Test(expected = Exception.class)
public void test() throws Exception {
when(mockedList.get(0)).thenThrow(new Exception());
mockedList.get(1);
}
}
You set up your test incorrectly and misinterpreted the outcome of your test.
The problem lies in the line:
when(mockedList.get(0)).thenThrow(new Exception());
The signature of "get" method does not allow checked excetions.
Thus, when you pass a checked exception to thenThrow, Mockito rightfully reports it with:
org.mockito.exceptions.base.MockitoException:
Checked exception is invalid for this method!
Invalid: java.lang.Exception
Thus the exception reported is MockitoException, not the Exception you passed to thenThrow. It is thrown even if you omit a call to mockedList.get(1);
To fix, use a RuntimeException, preferrably one that can be reported by get.
when(mockedList.get(0)).thenThrow(new IndexOutOfBoundsException());
Note that you stub a call that is not made afterwards, you need to use a lenient mock with #Mock(lenient = true), otherwise Mockito will report a org.mockito.exceptions.misusing.UnnecessaryStubbingException
fun main() = runBlocking {
coroutineScope {
val child = async {
Log.e("+++", "+++ in async{}, throw exception , ${Thread.currentThread().name}")
throw Exception("test exception with await() in async")
}
try {
child.await()
} catch(ex: Throwable) {
Log.e("+++", "+++ child.await() caught exception $ex, ${Thread.currentThread().name}")
}
}
}
The log "+++ child.await() caught exception java.lang.Exception: test exception with await() in aync, main" . shows the exception is caught, but it still crashes the app.
Why the expiation caught is still crashing the app with coroutines?
As per the documentation of coroutineScope:
This function is designed for parallel decomposition of work. When any child coroutine in this scope fails, this scope fails and all the rest of the children are cancelled (for a different behavior see supervisorScope). This function returns as soon as the given block and all its children coroutines are completed.
Remove the coroutineScope and it should function as you are expecting it should.
find this is helpful as well, and here:
whenever a coroutine created by async() throws an exception,
the same exception is thrown both by its Deferred.await()
and inside the body of the parent coroutine as well!
This means that, no matter if we catch the exception by surrounding await() with try/catch,
our app is still going to crash because the exception is not thrown just
from the await() suspension point
Exception thrown by the child coroutine bubbles up to its immediate parent. You must try catching exceptions in parent coroutines. This way application won't crash.
I have this scenario in which some tests can throw different exceptions.
#Test
public void addDevice(){
device.addDevice(); // this may throw exception 1
device.verifyStatus("Ready");
device.open(); // this may throw exception 2
device.verifyStatus("Open");
}
#Test
public void otherTest(){
device.act(); // this may throw exception 3
device.verifyStatus("Ready");
}
#After
public void tearDown(){
// handle the exception here
}
I want to handle those exceptions in the #After section without wrapping the test with try, catch.
Is that possible?
No, it is not possible.
You could wrap the test anyway with a try-catch-block. Then you could store the exception to a member variable instead of handling it.
In the #After method you can check whether the exception is null or not.
Due to your comment that you have hundreds of tests with this code I assume that this is set up logic which should actually be in an #Before method.
Thus, you could specify an external resource rule with a before and after method: https://github.com/junit-team/junit/wiki/Rules#externalresource-rules
In the before() method you perform the set up, catch and store the exceptions and in the after() method you handle them.
But does it make sense to handle the exception later? Can you run your test cases successfully if the set up fails?
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?
There are many Try/Catch blocks in my app to catch exceptions. I would like to read such handled exceptions and log them to a file. Is it possible to read handled exceptions with PostSharp?
no. PostSharp works by wrapping your methods in try/catch blocks of its own and then just rethrowing the exception. Any exceptions handled in your method would be an inner try/catch while postsharp would only have outer try/catch blocks. You would either 1) have to rethrow the exception or 2) Handle those exceptions using an aspect. Neither of which I recommend.
One way to handle this (!) is to have a method that you call within the catch that will log the parameters passed into the exception. Simply pass the exception in and the logger will log the information.
[LogParameters(LogLevel.Error)]
private static void Error(Exception ex) { }
public class LogParameters : OnMethodBoundaryAspect {
public override void OnEntry(MethodExcutionArgs args) {
for (int i=0; i<args.Arguments.Count; i++) {
// Get argument from args.Arguments.GetArgument(i)
}
}
}
Using the OnEntry method of a customized OnMethodBoundaryAspect, you can log the exception information by calling a method and passing in the exception. The method doesn't need to actually DO anything, it just is a dummy for the aspect to wrap around and log the exception parameter.