How to avoid throwing exception from finally block - java

I don't want toJson to throw an Exception, but the finally block might throw it.
Would it be preferable to wrap the bas.close() in a try/catch block or should this be re-written using try-with-resources
public String toJson() {
String json = null;
ByteArrayOutputStream bas = null;
try {
bas = new ByteArrayOutputStream();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValue(bas, this);
json = new String(bas.toByteArray());
} catch (Exception e) {
log.trace("Unable to parse JSON", e);
} finally {
if (bas != null) {
bas.close();
}
}
return json;
}

You should do it using the try-with-resources statement. Given below is an excerpt from the Oracle's tutorial on The try-with-resources Statement which clearly states the benefit of using it:
Prior to Java SE 7, you can use a finally block to ensure that a
resource is closed regardless of whether the try statement completes
normally or abruptly. The following example uses a finally block
instead of a try-with-resources statement:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
However, in this example, if the methods readLine and close both throw
exceptions, then the method readFirstLineFromFileWithFinallyBlock
throws the exception thrown from the finally block; the exception
thrown from the try block is suppressed. In contrast, in the example
readFirstLineFromFile, if exceptions are thrown from both the try
block and the try-with-resources statement, then the method
readFirstLineFromFile throws the exception thrown from the try block;
the exception thrown from the try-with-resources block is suppressed.
In Java SE 7 and later, you can retrieve suppressed exceptions; see
the section Suppressed Exceptions for more information.
Using the try-with-resources statement, you can write your method as follows:
public String toJson() throws Exception {
String json = null;
try (ByteArrayOutputStream bas = new ByteArrayOutputStream()) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValue(bas, this);
json = new String(bas.toByteArray());
}
return json;
}

I'd proabably go with something along the lines of:
public String toJson() {
try (var bas = new ByteArrayOutputStream()) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValue(bas, this);
return new String(bas.toByteArray());
}
catch (Exception ie) {
throw new MyCustomJsonConverterException("Failed to render to JSON");
}
}
i.e. map to a RuntimeException type if you expect failure to serialize to JSON to be exceptional (a programming error). This is an instance method, after all, and all invariants of the class should already be enforced elsewhere. This way, you take the burden of checking for null from the caller.

Related

Using Two nested Try blocks and a Single Catch block in Java

I'm learning about Java and exception handling and the try/catch blocks. And I'm doing an example from YouTube, and I want to ask you if this is a pattern or something when you use 2 try blocks and one catch block:
private List<User> parseCSVFile(final MultipartFile file) throws Exception {
final List<User> users = new ArrayList<>();
try {
try (final BufferedReader br = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
String line;
while ((line = br.readLine()) != null) {
final String[] data = line.split(",");
final User user = new User();
user.setName(data[0]);
user.setEmail(data[1]);
user.setGender(data[2]);
users.add(user);
}
return users;
}
} catch (final IOException e) {
logger.error("Failed to parse CSV file {}", e);
throw new Exception("Failed to parse CSV file {}", e);
}
}
I try to understand why this approach is better than using a try and a catch block like this:
try (final BufferedReader br = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
String line;
while ((line = br.readLine()) != null) {
final String[] data = line.split(",");
final User user = new User();
user.setName(data[0]);
user.setEmail(data[1]);
user.setGender(data[2]);
users.add(user);
}
return users;
} catch (final IOException e) {
logger.error("Failed to parse CSV file {}", e);
throw new Exception("Failed to parse CSV file {}", e);
}
Two nested try-blocks in the first code snippet are redundant. When an exception occurs, it would be propagated until the point where it can be handled (or otherwise the execution would terminate).
Regarding the usage of try-blocks, you need to understand that it doesn't make sense having try without catch or finally (and compiler will not allow that).
Note that in case of try-with-resources try(myResource){}, you do have an implicit finally-block, therefore even without a catch-block try-with-resources can be useful and perfectly valid from the compiler perspective of view.
For more information on exception-handling refer to the official tutorial provided by Oracle.
EDIT
Looks like java changed behavior of try-with-resource, so my answer is no longer valid.
It did explains why you can see double try in some old tutorials.
ORIGINAL POST
Try with resources is syntactic sugar.
try(A a = foo()){
bar();
} catch (E e) {
}
is equivalent of
A a = foo();
try {
bar();
} catch (E e) {
} finally {
a.close();
}
Which mean exception thrown from foo won't be caught. therefore you need another try ... catch.

Java Serialization: close streams in try or in a finally block?

I was looking at Java Serialization articles and stumbled a number of times across examples where the streams are closed in the try block instead of in a finally block. Can someone explain to me why is that?
Example:
import java.io.*;
public class DeserializeDemo {
public static void main(String [] args) {
Employee e = null;
try {
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
} catch(IOException i) {
i.printStackTrace();
return;
} catch(ClassNotFoundException c) {
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
Source: http://www.tutorialspoint.com/java/java_serialization.htm
The try-with-resources Statement
The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
The following example reads the first line from a file. It uses an instance of BufferedReader to read data from the file. BufferedReader is a resource that must be closed after the program is finished with it:
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
In this example, the resource declared in the try-with-resources statement is a BufferedReader. The declaration statement appears within parentheses immediately after the try keyword. The class BufferedReader, in Java SE 7 and later, implements the interface java.lang.AutoCloseable. Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly (as a result of the method BufferedReader.readLine throwing an IOException).
Prior to Java SE 7, you can use a finally block to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. The following example uses a finally block instead of a try-with-resources statement:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
Source =>http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
From documentation:
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs.
The runtime system always executes the statements within the finally block regardless of what happens within the try block. So it's the perfect place to perform cleanup.
So it means if you have some connection, stream or some other resources opened you have to be sure that they will be closed after your code block will be executed.
To avoid such ugly blocks you can use utility methods:
public void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ex) {
// handle block
}
}
}
Since Java 8 (but it is not required) you can provide your own Exception handler with closing resource:
public void close(Closeable closeable, Consumer<? extends Throwable> handler) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException ex) {
handler.accept(ex);
}
}
}
Also, just for knowledge, there are two cases when finally block is not called. It means that in most cases it will be called.
If you are Java 7 or above…
Don't close in finally block
The close method can throw an IOException and FileInputStream/ObjectInputStream can be null. When you use .close in finally, you must check null and try/catch again.
Use "try-with-resources Statement" instead
Using try-with-resources your code looks like this:
try(
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn)
) {
e = (Employee) in.readObject();
// in.close();
// fileIn.close();
}
The try-with-resources syntax guarantees the resources implementing AutoCloseable interface will be closed automatically. So you don't need to call a close method on your code.
You should close connection in finally. As finally always going to execute whether it goes in try or catch.
Also we need to close every connection once it created.
try{
// statements
}catch (){
// statements
}
finally {
in.close();
fileIn.close();
}
I was looking at Java Serialization articles and stumbled a number of times across examples where the streams are closed in the try block instead of in a finally block.
Examples that do it that way are poor examples. While closing a stream within a try block will work for simple one-shot examples, doing this in a case where the code might be executed multiple times is liable to lead to resource leaks.
The other Answers to this Question do a good job of explaining the right way(s) to close streams.
Can someone explain to me why is that?
It comes down to poor quality control on the tutorial sites; i.e. inadequate code reviewing.
The accepted answer certainly has a bug.
The close method can throw an IOException too. If this happens when
in.close is called, the exception prevents fileIn.close from getting
called, and the fileIn stream remains open.
It can implemented as below when multiple streams are involved:
} finally {
if ( in != null) {
try { in .close();
} catch (IOException ex) {
// There is nothing we can do if close fails
}
}
if (fileIn != null) {
try {
fileIn.close();
} catch (IOException ex) {
// Again, there is nothing we can do if close fails
}
}
}
Or, take advantage of Closeable Interface
} finally {
closeResource(in);
closeResource(fileIn);
}
Method:
private static void closeResource(Closeable c) {
if (c != null) {
try {
c.close();
} catch (IOException ex) {
// There is nothing we can do if close fails
}
}
}
You should close in finally block.
It's a bad habit to close in try block.
try {
e = (Employee) in.readObject(); //Possibility of exception
} catch(IOException i) {
} catch(ClassNotFoundException c) {
} finally {
in.close();
fileIn.close();
}
When someone is writing a code by knowing it will throw an exception,he/she has to close the opened resources
You should always close in a finally block.
However, you can use try with resources.
Here's the link: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}

Creating Custom Exception

I am using this link as a reference for creating custom exceptions. For my class practice, if no file is selected or passed in, my custom UnknownFileException should occur, but when I go and run my driver and put in an invalid filename I get a nullpointerexception instead?
My driver which has Adventure adventure = new Adventure(args[0]).
My custom exception:
import java.io.FileNotFoundException;
public class UnknownFileException extends FileNotFoundException {
public UnknownFileException() {
super("We couldn't tell what file this is");
}
public UnknownFileException(String message) {
super(message);
}
}
Code:
public class practice {
public String[] array;
public String line;
public PrintWriter outputStream = null;
public Scanner inputStream = null;
public practice(String fileName) throws UnknownFileException {
array = new String[100];
try {
inputStream = new Scanner(new FileReader(fileName));
line = inputStream.nextLine();
array[0] = line;
for (int i = 1; i < array.length; i++) {
array[i] = inputStream.nextLine();
}
outputStream = new PrintWriter(new
FileOutputStream("newFile.txt"));
} catch(UnknownFileException e) {
System.out.println(e.getMessage());
} catch (FileNotFoundException e) {
throw new UnknownFileException(e.getMessage());
} finally {
inputStream.close();
}
}
}
You probably got a stack trace, which should have pointed you to the line throwing the NullPointerException. I'm guessing it was this line:
inputStream.close();
The problem is that if you put in an invalid file name, new Scanner(new FileReader(fileName)) will throw, and inputStream will never be assigned. Because you have a finally block, however, before it throws your custom exception, it will try to execute the finally. But this gives a NullPointerException because inputStream is null, and that exception takes precedence, I believe (I'd have to check the language rules to make sure of what happens in this case).
Fix your finally block to test whether inputStream is null.
More: It's §14.20.2 of the JLS. This is pretty complicated, but basically if any exception is thrown from the finally block, any earlier exception thrown or caught is discarded.
inputstream is still null
Make the following change:
} finally {
if (inputStream != null) {
inputStream.close();
}
}
or use try-with-resources instead.

Junit Test case of method that already has a try-catch clause

I'm trying to write a test case for the method setTrailer() within the class ErParser. setTrailer() has try-catch clauses, and in one of its catch clauses, it catches NullPointerException. I'm trying to write a Junit test for the case where setTrailer() throws and catches a NullPointerException, but the test case keeps failing. Is it because I already caught the exception in the method itself? Should I be catching the exception in the test case instead?
The test case:
public class TestERParser {
#Test(expected=NullPointerException.class)
public void nullSetTrailer() {
ERParser recCurrParse = new ERParser();
recCurrParse.setTrailer(null);
}
}
setTrailer() method within the ERParser Class:
public class ERParser {
private static final String TRAILER_E = "GRAND TOTAL";
private static final String TRAILER_R = "TRAILER";
public String trailerRecord;
/**
* Constructs an ERParser object.
*/
public ERParser() {
this.trailerRecord = null;
this.trailerVals = null;
}
/**
* Populates the trailerRecord field with the summary (trailer) record of the input file.
* #param file Input file
* #throws NullPointerException, FileNotFoundException, IOException
*/
public void setTrailer(File file) {
try {
FileReader fReader = new FileReader(file);
BufferedReader bReader = new BufferedReader (fReader);
String currLine = new String();
readLoop:
while (bReader.ready()) {
currLine = bReader.readLine();
if (currLine.contains(TRAILER_E) || currLine.contains(TRAILER_R)) {
break readLoop;
}
}
this.trailerRecord = currLine.trim();
System.out.println("From setTrailer(): " + this.trailerRecord);
fReader.close();
bReader.close();
} catch (NullPointerException exception) {
exception.printStackTrace();
} catch (FileNotFoundException exception) {
exception.printStackTrace();
} catch (IOException exception) {
exception.printStackTrace();
}
}
}
As you suspected you are catching the NPE inside of your code and it is not being propagated. If you expected your users to catch this exception you should remove this code and adorn your method with throws, to the appropiate classes.
public void setTrailer(File file) throws Exception {
FileReader fReader = new FileReader(file);
BufferedReader bReader = new BufferedReader (fReader);
String currLine = new String();
readLoop:
while (bReader.ready()) {
currLine = bReader.readLine();
if (currLine.contains(TRAILER_E) || currLine.contains(TRAILER_R)) {
break readLoop;
}
}
this.trailerRecord = currLine.trim();
System.out.println("From setTrailer(): " + this.trailerRecord);
fReader.close();
bReader.close();
}
As your code now throws a checked Exception, you will need to update your Junit method slightly, to catch the checked exceptions
#Test(expected=NullPointerException.class)
public void nullSetTrailer() throws Exception {
ERParser recCurrParse = new ERParser();
recCurrParse.setTrailer(null);
}
We can argue about whether or not this catch block means the exception is handled. I would argue that merely printing the stack trace is not handling anything. It might be better to add a throws clause to the method signature and let clients decide what to do with exceptions.
If the method is written that way, it's up to you to test it as-written. You wouldn't have a choice if this was a 3rd party library.
Write the test that throws the exception; succes means trailerRecord is set to null.
Your code has another flaw: close the streams in a finally block. You risk not closing the input stream properly as written.
In your test case are expecting a NullPointerException class. If you catch it, the caller class will not get it. Hence, either you can remove the try/catch blocks or you can rethrow the exception after printing stacktrace :
catch (NullPointerException exception) {
exception.printStackTrace();
throw new NullPointerException();
}

try-with-resources or close() dilemma

I have a function that can throw IOException, so I don't catch the exception internally. however I've some resources to close. Is it correct to do in that way, using try-with-resource (without any catch block):
public void workOnFiles() throws IOException {
try(FileInputStream fis = new FileInputStream("bau.txt");) {
// Do some stuff
}
}
Or I should do something like that:
public void workOnFiles() throws IOException {
FileInputStream fis = new FileInputStream("bau.txt");
// Do some stuff
fis.close();
}
In 2nd one, if the exception is thrown, your fis won't be closed. An option is to enclose the statement that can throw th exception in a try block, and close the fis in a finally block.
But, since you are already on Java 7, you should use try-with-resource.
If you are keen on using the second method , then close the resource in finally block.
public void workOnFiles() throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream("bau.txt");
// Do some stuff
}
finally {
try {
fis.close();
}
catch(Exception e) {
//logger.error(e);
// e.printStackTrace();
}
}
try-with-resources always closes(Closeable resources) the resource whether exception raises or not(Work only java7 onwards).
Where as your second code do not close resource if exception raises.
So you can use try-with-resources if you are using java7 or else edit your code with try and finally block.
finally block guarantees execution irrespective of exception raises or not

Categories

Resources