How do I avoid Sonar's "preserve stack trace" violation? - java

Sonar gives a major violation error ("Preserve Stack Trace") for the following code. Following method is used to throw an exception. What are the steps should I take to overcome this violation?
public void exceptionHandler(String exception) throws PhDashException {
String exceptionMsg = exception.replaceAll("-", "_");
ExceptionPhDash pHDashExceptionMapper = new ExceptionPhDash();
try {
pHDashExceptionMapper = new ObjectMapper().readValue(exceptionMsg, ExceptionPhDash.class);
} catch (JsonParseException e) {
LOGGER.info(e.getMessage());
} catch (JsonMappingException e) {
LOGGER.info(e.getMessage());
} catch (IOException e) {
LOGGER.info(e.getMessage());
}
throw new PhDashException(pHDashExceptionMapper.getMessage());
}

You've logged each exception; that should be enough as far as preserving information is concerned like below,
LOGGER.info("Unexpected Exception has occurred", e);
Or You should re throw the PhDashException if you can, because, you should be enough as far as preserving information is concerned
throw new PhDashException(pHDashExceptionMapper);

Related

Why RuntimeException is not caught in catch block if there are multiple catch blocks?

I am able to catch RuntimeException or subclass of it with below code:
try {
//code that throws subclass of RuntimeException
throw new ChildRuntimeException("try");
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
But I am getting error with below code and not able to catch RuntimeException in Exception catch block.
try {
// code that throws subclass of Exception
throw new ChildExceptionClass("try");
} catch (ChildExceptionClass ex) {
throw new RuntimeException(ex.getMessage());
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
I searched for the same type of questions but did not find a suitable answer. Can
anyone explain why the behaviour is different?
In the second example you are throwing a childRuntimeException, which is caught, but then a new runtimeException is thrown. This block has no "catch" clause, so the exception is thrown and not caught.
The second catch is relevant for the "try" block, not for the "catch" block.
What I guess you probably want to do is:
try { // code that throws subclass of Exception
throw new ChildExceptionClass("try");
} catch (ChildExceptionClass ex) {
try {
throw new RuntimeException(ex.getMessage());
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
Do you understand the difference?

Multiple Catch blocks vs Catching in Base Exception class

Assuming we are talking about all the exceptions that extends base Exception class,
is:
try {
some code;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
catch (MyOwnException e)
{
e.printStackTrace();
}
same as:
try {
some code;
}
catch (Exception e) {
e.printStackTrace();
}
I am wondering in which case I MUST use the former one?
In the 2nd option Exception will catch all exception, not only those explicitly listed in the first option.
Use the 1st option if you want to catch only selected exceptions, and respond differently to each.
If you want to catch only selected exceptions, and have the same response to all of them, you could use:
catch (InterruptedException | ExecutionException | MyOwnException e)
{
e.printStackTrace();
}
It is good practice to use Exception sub classes rather than Exception class. If you use Exception then it would be difficult to debug.
Here is a link for reference
http://howtodoinjava.com/best-practices/java-exception-handling-best-practices/#3
If you have multiple exceptions which all are extending from...we'll say IndexOutOfBoundsException, then unless you specifically want to print a different message for StringIndexOutOfBoundsException or another sub-class you should catch an IndexOutOfBoundsException. On the other hand if you have multiple exceptions extending from the Exception class, it is proper format to create a multi-catch statement at least in JDK 1.8:
try {
// Stuff
}catch(InterruptedException | ClassNotFoundException | IOException ex) {
ex.printStackTrace();
}
The former one where you create multiple catch statements is if you were trying to do what I said before.
try {
// Stuff
}catch(StringIndexOutOfBoundsException se) {
System.err.println("String index out of bounds!");
}catch(ArrayIndexOutOfBoundsException ae) {
System.err.println("Array index out of bounds!");
}catch(IndexOutOfBoundsException e) {
System.err.println("Index out of bounds!");
}

Get exception instance class name

I would like to know what the exception instance was in this situation:
try {
// some risky actions
} catch (Exception e) {
System.out.println("Get instance name there");
}
How can I achieve this?
Here you go:
try {
throw new ArithmeticException();
} catch (Exception e) {
System.out.println( e.getClass().getCanonicalName());
}
Output:
java.lang.ArithmeticException
The type of the exception is shown as part of the output of:
e.printStackTrace();
To get it programmatically you can use:
String exceptionClassName = e.getClass().getName();
It is poor form to have logic depending on exception sub types within a catch block. Sonar will flag this as a code violation (squid S1193).
Instead you should add multiple catch blocks to catch different types of exceptions:
try {
readFile(fileName);
}
catch (java.io.IOException e) {
LOG.error("Error accessing file {}", fileName, e);
}
catch (java.lang.IllegalArgumentException e) {
LOG.error("Invalid file name {}", fileName, e);
}
Note: Since Log4j 2 (and SLF4J 1.6+) you can add a throwable as the last parameter and it will be recognized as such. So the above will work!
Since Java 7 you can also do a multi-catch:
}
catch (java.io.IOException | java.lang.IllegalArgumentException e) {
LOG.error("Could not read the file {}", fileName, e);
}
The benefit of the multi-catch is that you can handle multiple exception types within a single catch block without having to revert to a common super class (like java.lang.Exception) that would include exception types you didn't want to handle.
Default exception logging is something like
try
{
//
}
catch (Exception e)
{
e.printStackTrace();
}
This will print the stacktrace of the exception to system.err
If you are looking to add some contextual information, you can take a look at Apache Commons ContextedRuntimeException
public static void main(String[] args) {
try {
doSomething();
} catch (ContextedRuntimeException e) {
System.out.println(e.getMessage());
System.out.println(e.getContextEntries());
}
}
private static void doSomething() {
int divisor = 0;
int dividend = 100;
int result;
try {
result = dividend / divisor; // Just throw an exception to test things....
System.out.print("DIVISION RESULT: "+result);
} catch (ArithmeticException e) {
throw new ContextedRuntimeException("Oops..division by zero not allowed", e)
.addContextValue("Divisor", divisor)
.addContextValue("Dividend", dividend);
}
}
would output:
Oops..division by zero not allowed
Exception Context:
[1:Divisor=0]
[2:Dividend=100]
---------------------------------
[(Divisor,0), (Dividend,100)]

Catch exceptions without a try block?

I have a lot of custom exceptions that I'm throwing in a specific cases in the code, and I'd like to have one catch block at the bottom of the method to handle them all.
All the exceptions are children of the Exception class CribbageException, so I'd like to have:
public void myMethod(){
if (whatever){
throw new CardException();
}
if (something else){
throw new InvalidCardException();
}
if (scenario 3){
throw new TwoCardsException();
}
catch (CribbageException e) {
System.out.println(e.getMessage());
}
}
But I'm getting a catch without try error.
Is there any way to use this type of exception handling?
Wrap all the throws inside a single try.
public void myMethod(){
try {
if (whatever){
throw new CardException();
}
if (something else){
throw new InvalidCardException();
}
if (scenario 3){
throw new TwoCardsException();
}
}
catch (CribbageException e) {
System.out.println(e.getMessage());
}
}

Rethrowing exceptions in Java without losing the stack trace

In C#, I can use the throw; statement to rethrow an exception while preserving the stack trace:
try
{
...
}
catch (Exception e)
{
if (e is FooException)
throw;
}
Is there something like this in Java (that doesn't lose the original stack trace)?
catch (WhateverException e) {
throw e;
}
will simply rethrow the exception you've caught (obviously the surrounding method has to permit this via its signature etc.). The exception will maintain the original stack trace.
You can also wrap the exception in another one AND keep the original stack trace by passing in the Exception as a Throwable as the cause parameter:
try
{
...
}
catch (Exception e)
{
throw new YourOwnException(e);
}
I would prefer:
try
{
...
}
catch (FooException fe){
throw fe;
}
catch (Exception e)
{
// Note: don't catch all exceptions like this unless you know what you
// are doing.
...
}
In Java is almost the same:
try
{
...
}
catch (Exception e)
{
if (e instanceof FooException)
throw e;
}
In Java, you just throw the exception you caught, so throw e rather than just throw. Java maintains the stack trace.
Stack trace is prserved if you wrap the catched excetion into an other exception (to provide more info) or if you just rethrow the catched excetion.
try{
...
}catch (FooException e){
throw new BarException("Some usefull info", e);
}
something like this
try
{
...
}
catch (FooException e)
{
throw e;
}
catch (Exception e)
{
...
}
public int read(byte[] a) throws IOException {
try {
return in.read(a);
} catch (final Throwable t) {
/* can do something here, like in=null; */
throw t;
}
}
This is a concrete example where the method throws an IOException. The final means t can only hold an exception thrown from the try block. Additional reading material can be found here and here.
I was just having a similar situation in which my code potentially throws a number of different exceptions that I just wanted to rethrow. The solution described above was not working for me, because Eclipse told me that throw e; leads to an unhandeled exception, so I just did this:
try
{
...
} catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
throw new RuntimeException(e.getClass().getName() + ": " + e.getMessage() + "\n" + e.getStackTrace().toString());
}
Worked for me....:)

Categories

Resources