Exception Handling in Java to have Java best practices - java

I have a Java method like below:
private boolean getBooleanProperty(String property, String defaultValue) {
boolean result = false;
try {
result = Boolean.parseBoolean(properties.getProperty(property, defaultValue));
} catch (IllegalArgumentException | NullPointerException e) {
}
return result;
}
I know that the way I am handling the exceptions in above method is not correct and looking for the way to have those more aligned with the Java standards and best practices.
Similarly for the method below:
public void getStatusAndAnnotation(ITestResult result) {
try {
HashMap<Object, Object> map = new HashMap<>();
Method method = result.getMethod().getConstructorOrMethod().getMethod();
TestInfo annotation = method.getAnnotation(TestInfo.class);
try {
//add id removing the first character of the annotation (e.g. for C12034, send 12034)
if(annotation!=null) {
map.put("id",annotation.id().substring(1));
}
}catch (NullPointerException e){
e.printStackTrace();
}
if (result.getStatus() == ITestResult.SUCCESS) {
map.put("result", 1);
} else if (result.getStatus() == ITestResult.FAILURE) {
map.put("result", 9);
} else if (result.getStatus() == ITestResult.SKIP) {
map.put("result", 10);
}
if (annotation != null) {
if(annotation.trDeploy() && !map.get("id").equals(null) && !map.get("id").toString().isEmpty())
{
ApiIntegration.addTestResult(map);
}
else System.out.println("Deploying result was canceled, because test has annotation \"trDeploy: false\" or \"id\" has no value");
}
} catch (SecurityException | IOException
| ApiException | NullPointerException e) {
e.printStackTrace();
}
}
How do I handle these different exceptions to align with the best practices?

What I typically do is let the compiler/IDE tell me what exceptions I need to catch unless you want to catch an exception for a specific reason. That way, I can code without catching unnecessary exceptions and my code is cleaner.
These type of Exceptions are called Checked Exceptions
"In the Java class hierarchy, an exception is a checked exception if
it inherits from java.lang.Exception, but not from
java.lang.RuntimeException. All the application or business logic
exceptions should be checked exceptions."
Example:
try
{
// open a file (Compiler will force to either catch or throw)
}
catch (IOException ioe)
{
ioe.printStackTrace();
// need to make a decision on what to do here
// log it, wrap it in a RuntimeException, etc.
}
As for Unchecked Exceptions
"Unchecked, uncaught or runtime exceptions are exceptions that can be
thrown without being caught or declared"
Example:
String x = null;
// this will throw a NullPointerException
// However, you don't need to catch it as stated in some the comments
x.toString();
What you should do is prevent it
if (x == null)
{
x = "some default value"; // prevent the exception from happening.
}
x.toString();
Does this mean you should never catch a RuntimeException
No, of course not. It depends on the scenario.
Take this example:
String number = "12345";
// You don't know if number is a valid integer until you parse it
// If the string is not a valid number, then this code will
// throw an Exception
int i = Integer.parseInt(number);
Instead you can catch a NumberFormatException. Again, this is a form of prevention.
int i = 0; // some default
try
{
i = Integer.parseInt(number);
}
catch (NumberFormatException nfe)
{
// Good practice to log this, but the default int is fine.
}
Some Best Practices
Do not catch exceptions unless the compiler forces you to.
If you are catching a checked exception, then log it. You can also wrap it in a RuntimeException if you want it to percolate up the call stack.
If you want to catch a RuntimeException, then do so with a purpose (i.e. you can set a default and prevent the error all together.)
Don't have a chain of methods all throwing a checked Exception up the stack trace. This is very messing and forces all calling methods to either catch or throw the checked exception.
Catching a RuntimeException just to log it really doesn't have much of a purpose. Unless you are logging it in a catch all location.
Catch-All Example:
try
{
// entry point to application
}
catch (Throwable t)
{
// let all exceptions come here to log them
}

Related

What is an elegant way to wrap an error an rethrow in both cases?

There is a method which can:
throw an error
return null
I need to throw a user friendly exception to upper level in the both cases. What is the most elegant way for it? The brute force is:
try {
result = callMethod();
} catch (SomeException e) {
throw new UserFiendlyException("cannot process you, try again pls");
}
if (result == null) {
throw new UserFiendlyException("cannot process you, try again pls");
}
UPD 1: kotlin is accepted and preferable (but I'm also curious how could it be in Java)
UPD 2: Please, don't suggest the use of exceptions for control flow is an anti-pattern: https://softwareengineering.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why
If callMethod() is your own method, you could update that to perform the null check internally and throw the error...
function callMethod() {
const responseFromService = null;
if (responseFromService == null)
throw new SomeException(`Expected a valid response from the service but got null.`);
}
try {
result = callMethod();
}
catch (SomeException e) {
throw new UserFiendlyException("cannot process you, try again pls");
}
You can also try the null coalescing operator...
try {
result = callMethod() ?: throw new SomeException(`Escape!`);
}
catch (SomeException e) {
throw new UserFiendlyException("cannot process you, try again pls");
}
Or just keep it simple and check for null within the try...
try {
result = callMethod();
if (result == null) throw new SomeException(`Escape!`);
}
catch (SomeException e) {
throw new UserFiendlyException("cannot process you, try again pls");
}
Edit: Answer originally had the nullish coalescing operator as an option, but the question is for Java, not JavaScript. My bad.
Edit (2): Turns out there is a nullish coalescing operator in Kotlin; option restored.
try...catch and throw are expressions in Kotlin, so you can do:
val result =
try {
callMethod()
} catch (e: SomeException) {
null
} ?: throw UserFiendlyException("cannot process you, try again pls")
The try...catch will produce null if either callMethod returns null. or if an exception occurred. We check if it is null using ?:, and if it is, we throw the user friendly exception.
result will end up having a non nullable type.

Java 1.6 : Learn how to handle exceptions

I did extensive research on exceptions, but I'm still lost.
I'd like to know what is good to do or not.
And I'd also like you to give me your expert opinion on the following example :
public void myprocess(...) {
boolean error = false;
try {
// Step 1
try {
startProcess();
} catch (IOException e) {
log.error("step1", e);
throw new MyProcessException("Step1", e);
}
// Step 2
try {
...
} catch (IOException e) {
log.error("step2", e);
throw new MyProcessException("Step2", e);
} catch (DataAccessException e) {
log.error("step2", e);
throw new MyProcessException("Step2", e);
}
// Step 3
try {
...
} catch (IOException e) {
log.error("step3", e);
throw new MyProcessException("Step3", e);
} catch (ClassNotFoundException e) {
log.error("step3", e);
throw new MyProcessException("Step3", e);
}
// etc.
} catch (MyProcessException mpe) {
error = true;
} finally {
finalizeProcess(error);
if (!error) {
log.info("OK");
} else {
log.info("NOK");
}
}
}
Is it ok to throw a personnal exception (MyProcessException) in each step in order to manage a global try...catch...finally ?
Is it ok to manage each known exception for each step ?
Thank you for your help.
EDIT 1 :
Is it a good practice like this ? log directly in global catch by getting message, and try...catch(Exception) in upper level....
The purpose is to stop if a step fail, and to finalize the process (error or not).
In Controller
public void callProcess() {
try {
myprocess(...);
} catch (Exception e) {
log.error("Unknown error", e);
}
}
In Service
public void myprocess(...) {
boolean error = false;
try {
// Step 1
try {
startProcess();
log.info("ok");
} catch (IOException e) {
throw new MyProcessException("Step1", e);
}
// Step 2
try {
...
} catch (IOException e) {
throw new MyProcessException("Step2", e);
} catch (DataAccessException e) {
throw new MyProcessException("Step2", e);
}
// Step 3
try {
...
} catch (IOException e) {
throw new MyProcessException("Step3", e);
} catch (ClassNotFoundException e) {
throw new MyProcessException("Step3", e);
}
// etc.
} catch (MyProcessException mpe) {
error = true;
log.error(mpe.getMessage(), mpe);
} finally {
finalizeProcess(error);
if (!error) {
log.info("OK");
} else {
log.info("NOK");
}
}
}
Thank you.
Edit 2 :
Is it a real bad practice to catch (Exception e) in lower level and to throws a personnal exception ?
Doesn't exist a generic rule,it depends on your needs.
You can throw a personal exception, and you can manage each known exception.
But pay attention, it is important what you want.
try{
exec1();
exec2(); // if exec1 fails, it is not executed
}catch(){}
try{
exec1();
}catch(){}
try{
exec2(); // if exec1 fails, it is executed
}catch(){}
In your example above it may well be acceptable to throw your own custom exception.
Imagine I have some data access objects (DAO) which come in different flavours (SQL, reading/writing to files etc.). I don't want each DAO to throw exceptions specific to their storage mechansim (SQL-related exceptions etc.). I want them to throw a CouldNotStoreException since that's the level of abstraction that the client is working at. Throwing a SQL-related or a File-related exception would expose the internal workings, and the client isn't particular interested in that. They just want to know if the read/write operation worked.
You can create your custom exception using the originating exception as a cause. That way you don't lose the original info surrounding your problem.
In the above I probably wouldn't handle each exception in each step as you've done. If processing can't continue after an exception I would simply wrap the whole code block in an exception handling block. It improves readability and you don't have to catch an exception and then (later on) check the processing status to see if you can carry on as normal (if you don't do this you're going to generate many exceptions for one original issue and that's not helpful).
I would consider whether multiple catch {} blocks per exception add anything (are you doing something different for each one?). Note that Java 7 allows you to handle multiple exception classes in one catch{} (I realise you're on Java 6 but I note this for completeness).
Finally perhaps you want to think about checked vs unchecked exceptions.
The main point of the exception mechanism is to reduce and group together handling code. You are handling them in the style typical for a language without excptions, like C: every occurrence has a separate handling block.
In most cases the best option is to surround the entire method code with a catch-all:
try {
.... method code ...
}
catch (RuntimeException e) { throw e; }
catch (Exception e) { throw new RuntimeException(e); }
The only times where this is not appropriate is where you want to insert specific handling code, or wrap in a custom exception that will be specifically handled later.
Most exceptions, especially IOExcption in your case, represent nothing else but failure and there will be no handling beyond logging it and returning the application to a safe point, where it can process further requests. If you find yourself repeating the same handling code over and over, it's a signal that you are doing it wrong.
One very important rule: either handle or rethrow; never do both. That is what you are doing in your example: both logging and rethrowing. Most likely the rethrown exception will be caught further up in the call stack and logged again. Reading through the resulting log files is a nightmare, but unfortunately quite a familiar one.
int step = 0;
try
{
step = 1;
...
step = 2;
...
step = 3;
...
}
catch (Exception1 e)
{
log ("Exception1 at step " + step);
throw new MyException1 ("Step: " + step, e);
}
catch (Exception2 e)
{
log ("Exception2 at step " + step);
throw new MyException2 ("Step: " + step, e);
}
...
I'd say it depends on your needs...
If step2 can execute correctly even if step1 failed, you can try/catch step1 separately.
Otherwise, I would group all steps in one try/catch block and made sure that the individual steps produce a log message when they fail.
That way you don't litter your code and still know what went wrong
It's ok to catch each known exception, so you can log what exception occure, and why it did.
Here some links to exception handling patterns/anti-patterns:
Do:
http://www.javaworld.com/jw-07-1998/jw-07-techniques.html
Don't:
http://today.java.net/article/2006/04/04/exception-handling-antipatterns
http://nekulturniy.com/Writings/RebelWithoutAClause/Rebel_without_a_clause.html
About creating your own exceptions, it's certainly useful if you're creating an API, a framework or another piece of reusable code, but in a regular application, it's more debatable and I personally would suggest to stick to existing exceptions.

How to avoid printing exception and assign another action when exception was encountered? My attempt don't work right

I am encountering an error when user doesn't type anything into input statement. I thought of using Try/Catch blocks to instead throw exception to set boolAskRepeat to true which should skip to the end of the code and repeat the loop.
This doesn't work, and I believe I'm missing something but I'm not sure what... It still throws exception saying:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.lang.String.charAt(Unknown Source)
at ITSLab03.main(ITSLab03.java:34)
Which is this line of code: inputStatus = input.readLine().toLowerCase().charAt(0);
What am I doing wrong here?
while (boolAskStatus == true)
{
System.out.print("Employment Status (F or P): ");
try
{
inputStatus = input.readLine().toLowerCase().charAt(0);
if (inputStatus == "f".charAt(0))
{
boolAskStatus = false;
String stringCheckSalary = null;
boolean boolCheckSalary = true;
while (boolCheckSalary == true)
{
// some code
}
outputData(inputName, inputStatus, calculateFullTimePay(inputSalary));
}
else if (inputStatus == "p".charAt(0))
{
// some code
outputData(inputName, inputStatus, calculatePartTimePay(inputRate, inputHours));
}
else boolAskStatus = true;
}
catch (IOException e) { boolAskStatus = true; }
}
You need to catch StringIndexOutOfBoundsException as well (If you observe the stack trace properly this is the exception you are getting)
catch (StringIndexOutOfBoundsException e) {
boolAskStatus = true;
}
(or)
catch Exception which catches all runtime exceptions
catch (Exception e) {
boolAskStatus = true;
}
The normal try catch pattern should look like this:
try
{
// code that is vulnerable to crash
}
catch (Specific-Exception1 e1)
{
// perform action pertaining to this exception
}
catch (Specific-Exception2 e2)
{
// perform action pertaining to this exception
}
....
....
catch (Exception exp) // general exception, all exceptions will be caught
{
// Handle general exceptions. Normally i would end the program or
// inform the user that something unexpected occurred.
}
By using .charAt(0), you are assuming that the String has a length > 0.
You could simplify this a bunch by just doing:
String entry = input.readLine().toLowerCase();
if (entry.startsWith("f")) {
...
}
else if ("entry".startsWith("p")) {
...
}
Your code doesn't work the way you want because input.readLine().toLowerCase().charAt(0) throws a StringIndexOutOfBoundsException, which is not an IOException, so the catch block never gets hit. You can make it work by changing the catch to
catch (StringIndexOutOfBoundsExceptione e) { boolAskStatus = true; }
But...
It's generally not a good idea to base your program's normal behaviour on exception handling. Think of exception throwing as something that could happen, but usually won't. Why not use something like:
final String STATUS_F = "f";
final String STATUS_P = "p";
String fromUser = null;
do {
String rawInput = input.readLine().toLowerCase();
if (rawInput.startsWith(STATUS_F)) {
fromUser = STATUS_F;
} else if (rawInput.startsWith(STATUS_P)) {
fromUser = STATUS_P;
}
} while (fromUser == null);
if (STATUS_F.equals(fromUser)) {
// do something
} else if (STATUS_P.equals(fromUser)) {
// do something else
} else {
// Shouldn't be able to get here!
throw new Exception("WTF!?");
}
It much easier for another person reading this to understand why the program loops and how the loop is controlled, in part because the code that figures out what the user is inputting and the code that decides what to do with that information are separated. Plus, you don't need to deal with exceptions.

How to continue with If-Conditions in Try-Catch

I have this line of Code
try {
String txtText = article.getTxtText().toString();
if (StringUtils.hasText(article.getTxtText().toString())){
textPropertyList.add(txtText);
}
String txtLongText = article.getObjLongTextData().toString();
if (StringUtils.hasText(txtLongText)){
textPropertyList.add(txtLongText);
}
String txtShortText = article.getObjShortTeaserData().toString();
if (StringUtils.hasText(txtShortText)) {
textPropertyList.add(txtShortText);
}
} catch (NullPointerException e) {
}
It is possible, that only one of the three properties are set. But if one property isnt set, I get this NullpointerException. I catch it, but then the try-Block isnt continued.
So e.g. if the article.getTxtText() method returns null, I dont get the txtLongText and txtShortText Strings either, although at least one of them has a not empty String set.
So the question is, how can I continue the try-block although there's is an Exception caught?
Thanks a lot.
You should either use 3 try-catch blocks or just use a null-check around every case.
if (article.getTxtText() != null) {
// do part 1
}
if (article.getObjLongTextData() != null) {
// do part 2
}
I would imagine that the correct approach to this is to have three try/catch blocks around each point of code. The whole point of a try block is that you are trying the code as a lump and if it fails anywhere you abandon it. For what you are describing you would need three try/catches around each possible point of failure.
That having been said you are probably better off testing for null rather than relying on exception handling to do that. Exception handling should be for exceptionalm unforeseen events, not for flow control in a program.
If you must do this with exceptions (and I don't think you should), then you need to have 3 separate try/catch blocks:
try {
String txtText = article.getTxtText().toString();
if (StringUtils.hasText(article.getTxtText().toString())){
textPropertyList.add(txtText);
}
} catch (NullPointerException e) {}
try {
String txtLongText = article.getObjLongTextData().toString();
if (StringUtils.hasText(txtLongText)){
textPropertyList.add(txtLongText);
}
} catch (NullPointerException e) {}
try {
String txtShortText = article.getObjShortTeaserData().toString();
if (StringUtils.hasText(txtShortText)) {
textPropertyList.add(txtShortText);
}
} catch (NullPointerException e) {}
Once an exception is thrown in your code you cannot restart execution in the middle of the try block.
Having said that I would always prefer to detect the null pointer with an if test rather than relying on exception handling for this non-exceptional condition.
do defensive programming ,check for nulls.
if ( variable != null ){
...
}
The simplest and better approach from my point of view would be break the try - catch block in three different try-catch block, something like the following :
try {
String txtText = article.getTxtText().toString();
if (StringUtils.hasText(article.getTxtText().toString())){
textPropertyList.add(txtText);
}
} catch (NullPointerException e) {
//Handle Exception
}
try {
String txtLongText = article.getObjLongTextData().toString();
if (StringUtils.hasText(txtLongText)){
textPropertyList.add(txtLongText);
}
} catch (NullPointerException e) {
//Handle Exception
}
try {
String txtShortText = article.getObjShortTeaserData().toString();
if (StringUtils.hasText(txtShortText)) {
textPropertyList.add(txtShortText);
}
} catch (NullPointerException e) {
//Handle Exception
}
I'd recommend a different design:
private void addProperty(Object property, Collection<String> properties) {
if (property == null) {
return;
}
String textProperty = property.toString();
if (StringUtils.hasText()) {
properties.add(textProperty);
}
}
Usage:
addProperty(article.getTxtText());
// ...
Why are you doing this in a try / catch, just use simple if
if ( txtText != null ){
...
}
if ( txtLongText != null ){
...
}

Catching some exceptions but ignoring others - why doesn't this work?

I have something similar to this.
void func() {
try {
//socket disconnects in middle of ..parsing packet..
} catch(Exception ex) {
if(!ex.getMessage().toString().equals("timeout") || !ex.getMessage().toString().equals("Connection reset")) {
debug("Exception (run): " + ex.getMessage());
ex.printStackTrace();
}
}
Why is it that when I get a connection reset exception or a timeout exception, it still goes inside the condition. I tried without toString and with no luck.
You shouldn't catch all exceptions and then test the error message of the exception. Instead only catch those exceptions that you intend to handle - for example SocketTimeoutException.
catch (SocketTimeoutException ex)
{
// Do something...
}
With your current code you may be catching some other type of exception that you weren't expecting. Currently you will just ignore this exception, not even logging it. This can make it very difficult to debug what is going on. If you have an exception that you can't handle you should either rethrow it or log it.
I want to catch all exceptions
If you really want to do that then you can write your code as follows:
catch (SocketTimeoutException ex)
{
// Do something specific for SocketTimeoutException.
}
catch (Exception ex)
{
// Do something for all other types of exception.
}
Regarding your specific error, you have written:
!a.equals(b) || !a.equals(c)
This expression always evaluates to true. What you meant was:
!a.equals(b) && !a.equals(c)
Or equivalently:
!(a.equals(b) || a.equals(c))
Note that by rewriting your code as I suggested above you completely avoid having to write this complicated boolean expression.
It's really not safe to rely on exceptions messages to know what is the cause of your exception.
In your case you can try to catch more specific exceptions, such as SocketTimeoutException and the classic IOException :
void func() {
try {
//socket disconnects in middle of ..parsing packet..
} catch(SocketTimeoutException ex) {
//In case of Time out
} catch(IOException ex){
//For other IOExceptions
}
}
Sources :
[Socket.connect()][3]
Even if you prefer to seek informations in exceptions messages, you shouldn't check if the message simply is equal to "timeout" but if the message contains "timeout"
[3]: http://download-llnw.oracle.com/javase/6/docs/api/java/net/Socket.html#connect(java.net.SocketAddress, int)

Categories

Resources