Will this InputStream be closed properly if an IOException occurs? - java

I'm trying to properly handle an IOException without having to resort to a tonne of nested try/catch statements.
From reading online I've gathered that this might be the correct way to handle it. but I'm not 100% sure. Is this right?
try (InputStream in = blob.getBinaryStream()) {
while (in.read(bytesRead) != -1) {
byteStream.write(bytesRead);
}
}catch(IOException e){
logger.error("An IOException occurred while streaming a blob from the database", e);
}

The InputStream in will be closed, byteStream not.

Related

Potnetial Resource Leak with IOUtils Persists like a Stubborn Mule

I'm using IOUtils to parse JSON from a HttpServletRequest request:
baseRequest.setAuthentication(null);
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
PrintWriter writerResponse = response.getWriter();
-> String data = IOUtils.toString(request.getInputStream(), "UTF-8"); <-
But Eclipse complains of a potential resource leak:
Potential resource leak: '<unassigned Closeable value>' may not be closed
Even when I surround it with a try/finally block and close via IOUtils.closeQuietly() the error persists like a stubborn mule.
String data = "";
try {
data = IOUtils.toString(request.getInputStream(), "UTF-8");
} catch (IOException e) {
} finally {
IOUtils.closeQuietly(request.getInputStream());
}
What is causing this error and how do I fix it?
P.S
While the code below:
try {
String data = IOUtils.toString(request.getInputStream(), "UTF-8");
} catch (IOException e) {
} finally {
IOUtils.closeQuietly(request.getInputStream());
}
does not throw any error, as soon as I try using the value 'data' anywhere in my code (even in the try statement) the error shows up again.
The error is correct. getInputStream may well return a new input stream each time you call getInputStream, so closing a new input stream doesn't help.
Save the input stream in a variable. Best of all, use try-with-resources:
try (InputStream stream = request.getInputStream()) {
data = IOUtils.toString(stream, "UTF-8");
}

Under what circumstances could closing a stream fail? [duplicate]

This question already has answers here:
Does close ever throw an IOException?
(5 answers)
Closed 7 years ago.
According to many tutorials I've read regarding streams and the like, it is considered good practice to close a Stream not inside the try-block, but inside the finally instead, to ensure it's closing with and without an exception.
Of course, this has to be again surrounded by a try-and-catch again, as .close() can throw an IOException. However, as the Javadoc of under what conditions this might happen ("Throws: IOException - if an I/O error occurs.") is extremely vague, I wondered what, specifically, would have to happen for this exception to be thrown at this place. Below is an example code.
FileInputStream fis = null;
try {
fis = new FileInputStream("C:\\TestFiles\\JapaneseFileNames");
// Do some stuff
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fis != null) {
fis.close();
}
} catch(IOException e) {
throw new RuntimeException("Something happened, but what?", e);
}
}
If the stream extends FilterOutputStream, the close() method first calls flush(), which may try some I/O and encounter an IOException, which is thrown to the caller of close(). BufferedOutputStream is the typical case.
If the stream extends FilterOutputStream and is wrapped around another one, calling close() calls close() on the wrapped stream, which behaves as above. new DataOutputStream(new BufferedOutputStream(...)) and new ObjectOutputStream(new BufferedOutputStream(...)) are typical cases.

File locked after uploaded by using HttpServletRequest in JAVA

Here is the scenario, I try to upload a file, and after I uploaded it, I tried to access that file from the new directory (which i just write to), but I received error message:
There was an error opening this document. The file is already open or
in use by another application.
Below is my coding.
try{
conn = this.getConnection();
String getIP = "SELECT IP FROM TABLE WHERE ID='3'";
ps = conn.prepareStatement(getIP);
rs = ps.executeQuery();
Part file = request.getPart("upload");
String fileName = extractFileName(request.getPart("upload"));
String basePath = "//"+ipAdd+"/ns/"+fileName;
File outputFilePath = new File(basePath + fileName);
inputStream = file.getInputStream();
outputStream = new FileOutputStream(outputFilePath);
int read = 0;
final byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
}catch(Exception ex){
ex.printStackTrace();
throw ex;
}finally{
if(!conn.isClosed())conn.close();
if(!ps.isClosed())ps.close();
if(!rs.isClosed())rs.close();
inputStream.close();
outputStream.close();
}
Is it because that I open the file too quick after I start the upload function? I do realize that after 1/2minutes, I'm able to access the file. Is there anyway to solve this bug?
You're not closing the file. Add
outputStream.close();
after the loop.
EDIT And do it first, before closing anything else. You should really use try-with-resources here. If you get any exception closing anything, the other closes won't happen.
In your code above, if an exception occurs whilst closing the JDBC Connection, then none of the other JDBC objects or Streams are closed. The finally block exits at that point.
Since Java 7, closing Streams and JDBC objects (Connections, Statements, ResultSets etc) can be done in a proper exception handling framework nice and easily, since they all implement a common interface AutoCloseable
So you can write a single close() method and handle the exception inside:
public void close(AutoCloseable closeable) {
try {
closeable.close();
} catch (Exception e) {
//Just log the exception. there's not much else you can do, and it probably doesn't
//matter. Don't re-throw!
}
}
So when closing your JDBC objects, you can do this in the finally block:
close(conn);
close(ps);
close(rs);
close(inputStream);
close(outputStream);
Now if an exception occurs whilst closing any of the objects, it is handled and the following objects are still closed.

What to do with exceptions in java?

I am beginner in Java programming. But i have code below
Socket socket = serverSocketObj.accept();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
try {
writer.writeLine();
} catch(IOException e ) {
//write to logger here
} finally {
writer.close(); // this throws IOExceptioin too. What to do with it
// Possible memmory leak?
socket.close();
}
When i try to close writer i should handle another Exception. But i don't know what to do with it. Is this Exception impossible in my case? Can i just ignore it?
If you don't know what to do with them, just catch them and log them.
The simplest way of logging them is e.printStackTrace() This way,
at least you'll always see there's a problem if an exception occurs.
Another approach is to just re-throw the exceptions to upper-level code.
E.g. if your method (in which your sample code is) declares to throw IOException,
then there's nothing you should worry about. Let upper-level code worry about it.
Just check if the writer and socket are not null.
Socket socket = serverSocketObj.accept();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
try {
writer.writeLine();
} catch(IOException e ) {
//write to logger here
} finally {
if(writer != null)
writer.close(); // this throws IOExceptioin too. What to do with it
// Possible memmory leak?
if(socket != null)
socket.close();
}
Unfortunately, to make the compiler happy you must catch the potential IOExceptions from the close statements (assuming you don't add IOException to your method's throws clause). (Thank you Mr Goodenough!)
But there's nothing you can really do to "handle" the exception once you have it, other than to log it.
(I'm thinking that the new "try with resources" structure in Java may handle this all a bit cleaner.)

javax.imageio.ImageIO Problem creating ImageInputStream

I have a Servlet in Tomcat 5.5 that reads local images sitting on a folder. The image is then sent back to an Applet.
I'm getting this "javax.imageio.IIOException: Can't create an ImageInputStream!" error and not sure whats causing it.
Has anyone had this problem before? Could this be a Thread issue in the ImageIO? I can't reproduce this issue since it occurs about 3 times for every 1000 requests.
EDIT: This is the Servlet code that reads the image. I just use the ImageIO.read(File) in its static form inside the Servlet's doPost method the same way below:
doPost(req,resp){
...
BufferedImage image = ImageIO.read(imageFile);
...
}
Here is the source code for javax.imageio.ImageIO.read(File):
public static BufferedImage read(File input) throws IOException {
if (input == null) {
throw new IllegalArgumentException("input == null!");
}
if (!input.canRead()) {
throw new IIOException("Can't read input file!");
}
ImageInputStream stream = createImageInputStream(input);
if (stream == null) {
throw new IIOException("Can't create an ImageInputStream!");
}
BufferedImage bi = read(stream);
if (bi == null) {
stream.close();
}
return bi;
}
If the sole functional requirement is to read images from local disk and return it unmodified to the HTTP response using a servlet, then you do not need the ImageIO at all. It only adds unnecessary overhead and other problems like you're having now.
Get rid of the ImageIO stuff and just stream the raw image straight from disk to HTTP response, along a set of proper response headers. For example,
String name = request.getParameter("name");
File file = new File("/path/to/images", name);
response.setContentType(getServletContext().getMimeType(file.getName()));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
InputStream input = null;
OutputStream output = null;
try {
input = new BufferedInputStream(new FileInputStream(file));
output = new BufferedOutputStream(response.getOutputStream());
byte[] buffer = new byte[8192];
for (int length; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
} finally {
if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
}
That's all. You only need ImageIO whenever you would like to manipulate the image in server's memory before returning it, e.g. resizing, transforming or something.
Another, more robust, example of such a servlet can be found here and a more advanced one here.
The source I have (Java5 but I doubt it has changed a lot) states that if there are no ImageInputStream service providers registered, the createImageInputStream method returns null and thus you get that exception.
From the JavaDoc on IIORegistry.getDefaultInstance() which is used by ImageIO:
Each ThreadGroup will receive its own instance; this allows different Applets in the same browser (for example) to each have their own registry.
Thus it might actually be a threading problem in that you get a plain new instance of IIORegistry.
Edit: digging deeper into the source I found the following:
Most likely you'd get a FileImageInputStream, since you pass in a file. However, if an exception occurs the service provider returns null. Thus there might be a FileNotFoundException or any other IOException being thrown which causes the stream not to be created.
Unfortunately, there's no logging in the code, thus you'd have to debug somehow. It's probably due to missing file permissions, a corrupted/incomplete file or the file missing.
Here's the Java5 source for FileImageInputStreamSpi#createInputStreamInstance()
public ImageInputStream createInputStreamInstance(Object input,
boolean useCache,
File cacheDir) {
if (input instanceof File) {
try {
return new FileImageInputStream((File)input);
} catch (Exception e) {
return null;
}
} else {
throw new IllegalArgumentException();
}
}
Where is your use of close() methods within the exception handling? Streams have to be closed when there are exceptions, too, as well as normal termination of the block of the code.
The symptom sounds like you run out of heap space or sometime.
It is not the coding errors that others pointed out, since the problem is intermittent.

Categories

Resources