How would an IOException be thrown in below code ? Is it if the response object times out ?
public void doGet(HttpServletRequest request, HttpServletResponse response) {
try {
response.getWriter().print("Test");
} catch (IOException e) {
e.printStackTrace();
}
}
You are trying to write to a socket, so there could be all sorts of IO errors. The socket could have been closed / reset for example.
getWriter() javadoc
"IOException - if an input or output exception occurred"
In short, getWriter is an input/output operation which tries to open a PrintWriter (I believe). The opening of that writer can simply fail, resulting in the IOException thrown.
Plus, the print() operation is also input/output, so that goes by the same conditions.
Related
AFAIK, the standard try-with-resources form
try(InputStream is= new ...){
... some reading from is
} catch (..){
... catching real problems
}
catch (IOException e) {
... if closing failed, do nothing - this clause is demanded by syntax
}
is equivalent to:
try{
InputStream is= new ...
... some reading from is
} catch (..){
... catching real problems
} finally {
try{
is.close();
} catch (IOException e) {
... if closing failed, do nothing
}
}
The first variant is more simple, of course. But I see the case when the second variant is absolutely OK, whereas the first becomes ununderstandable.
Imagine the situation, when you have got code, where the try(){} appears in the function with throws IOExceptions clause.
String readFromFile(...) throws IOException{
...
try(...){
...
}
}
The IOException in the second catch eats all IOExceptions, either connected to the attempt of closing or not. And does nothing. I suppose, that somewhere out of the method there is a piece of code that works with that IOException and does something noticeable. For example, logs the stack. So, local catches will be never reached. We are not interested in the second catch clause, but usually, we need some special reaction for the first one.
On the other hand, if we delete the closing catch(IOException e){} clause, counting on the throws in the method header, that absolutely uninteresting for us closing exception will be reacted to.
While we are catching the closing problems by IOException, I see no way out of the problem. And Eclipse java editor demands me to use this very exception for that clause!
How can I divide IOException appearing from closing from other IOExceptions, appearing in the try{} body?
I think Java is to blame for this one. The close() method should have thrown a different exception than IOException there is rarely anything the caller can do about it. Your only solution is to rewrap the IOExceptions you're interested in before rethrowing.
Usually what I do is I extract the entire content of the try-block to its own method where I can catch any IOExceptions and re-throw them as custom exceptions. I can then catch the remaining IOException by itself in the catch block.
public void foo() throws CustomException {
try (InputStream is= new ...) {
bar(is); //This catches internal IOExceptions and throws a CustomException
}
catch (IOException e) { //The close() exception
}
}
I have the following code where I need to catch AccessDeniedException exception
import java.io.PrintWriter;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
class MyFileClass {
public void write()
throws IOException
{
PrintWriter out = new PrintWriter("sample.txt");
out.printf("%8.2f\n", 3.4);
out.close();
}
}
public class MyClass {
public static void main(String[] args)
throws Exception
{
try {
MyFileClass mf = new MyFileClass();
mf.write();
} catch (AccessDeniedException e) {
print("Access denided");
}
catch (FileNotFoundException e) {
print("File not found");
}
}
}
In case sample.txt is read only, I get output as "file not found" rather "Access denided". I would like to understand what is the reason for this? Also, is the above structure for catching AccessDeniedException correct?
AccessDeniedException is only thrown by the new file API; the old file API (which you use with this PrintWriter constructor) only knows how to throw FileNotFoundException even if the real filesystem-level problem is not "the file does not exist".
You have to use the new API to open an output stream to the destination file; then you can have meaningful exceptions:
// _will_ throw AccessDeniedException on access problems
final OutputStream out = Files.newOutputStream(Paths.get(filename));
final PrintWriter writer = new PrintWriter(out);
More generally, the new file API defines FileSystemException (inheriting IOException), which all new, meaningful exceptions defined by the new API inherit.
This means among other things that you can clearly separate, in catch clauses, what is caused by filesystem-level errors and "real" I/O errors, which you can't do with the old API:
try {
// some new file API operation
} catch (FileSystemException e) {
// deal with fs error
} catch (IOException e) {
// deal with I/O error
}
There is NO such AccessDeniedException in PrintWriter.
SecurityException is the exception thrown by PrintWriter
If a security manager is present and checkWrite(file.getPath()) denies
write access to the file
I've got a few test methods that aren't behaving as I expect them to be. In these scenarios, I'm writing logging messages to a text file.
Both methods are about closing the output link to the file and attempting to write to it. Obviously this means I expect an IOException which is also reflected in my code.
These are the two test methods I'm talking about
#Test(expected = IOException.class)
public void writeToClosedConnection() throws IOException {
LogHandler.getInstance().createNewChatlog("Jack");
LogHandler.getInstance().stopLogging(); // Closes the bufferedWriter
LogHandler.getInstance().writeToChatLog(new Message("Jim", "CAN'T WORK"));
}
#Test(expected = IOException.class)
public void closeStream() throws IOException {
log = new ChatLog(new GregorianCalendar(), "STANDARDTESTLOG", directory);
log.closeLogFile(); // Closes the bufferedWriter
log.addMessage(new Message("Jim", "CAN'T WORK"));
}
Both methods to write messages belong in the same route. writeToChatLog invokes addMessage, which will in turn call on the writeToLogFile method.
This last method is defined as
protected void writeToLogFile(String message) {
try {
if (logging) {
bWriter.write(message);
bWriter.newLine();
bWriter.flush();
} else {
throw new ForbiddenActionException("Logging is disabled");
}
} catch (IOException e) {
OutputUtil.showErrorMessage("Couldn't write to logfile", "IO error");
e.printStackTrace();
}
}
The issue at hand is that even though IO errors are thrown (twice this:)
java.io.IOException: Stream closed
at java.io.BufferedWriter.ensureOpen(Unknown Source)
at java.io.BufferedWriter.write(Unknown Source)
at java.io.Writer.write(Unknown Source)
at io.Log.writeToLogFile(Log.java:41)
at io.ChatLog.addMessage(ChatLog.java:16)
at tests.ChatLogTest.closeStream(ChatLogTest.java:76)
and the popup message (Couldn't write to logfile) is shown, I still get an assertionError (java.lang.AssertionError: Expected exception: java.io.IOException).
JUnit is version 4.
Why is this happening?
You never really throw IOException. Inside writeToLogFile you catch it, log it and do nothing else. From you outside world perspective nothing wrong happened:
protected void writeToLogFile(String message) {
try {
//...
} catch (IOException e) {
//...
e.printStackTrace();
}
}
You see, even if IOException was thrown, it's suppressed. Thus it never escapes out of writeToClosedConnection() method so JUnit can't see it. And it fails the test. A quick solution would be to propagate the exception, which unfortunately requires modifying your signature:
protected void writeToLogFile(String message) throws IOException {
try {
//...
} catch (IOException e) {
//...
throw e;
}
}
writeToLogFile() doesn't throw an IOException. If it did, it would have to be declared as
protected void writeToLogFile(String message) throws IOException {
You're explicitely catching any IOException that could be thrown from the instructions in writeToLogFile(). Catching an exception is precisely used to avoid the exception to be thrown.
Don't catch IOException, and declare the IOException in the method declaration, and the test will pass:
protected void writeToLogFile(String message) throws IOException {
if (logging) {
bWriter.write(message);
bWriter.newLine();
bWriter.flush();
} else {
throw new ForbiddenActionException("Logging is disabled");
}
}
I have a simple servlet where I write to a file if it has a queryparameter 'hello', and since this is a test I want to display the error the the webpage also.
IntelliJ is complaining that I am not catching the IOException, not sure what's wrong:
private static void WriteToFile(String filePath, String fileName, String fileData) {
FileWriter writer = null;
try {
writer = new FileWriter(fileName);
writer.write(fileData);
} catch(IOException ex) {
} finally {
if(writer != null) {
writer.close();
}
}
}
Also, in my exception, I noticed on the web most people write:
How can I output the error to the web page?
You're not catching IOException when you call writer.close(); in the finally block.
You're also completely swallowing any IOException thrown in the main code, which is a really bad idea. If something's goes wrong, you'll have no idea what's happening.
I would personally suggest that you let that method throw the exception to the caller:
private static void writeToFile(String filePath, String fileName,
String fileData) throws IOException {
FileWriter writer = new FileWriter(fileName);
try {
writer.write(fileData);
} finally {
writer.close();
}
}
Note that if the try block throws an exception and the finally block does, you'll effectively "lose" the original exception. You may want to suppress exceptions throw when closing.
Or just use Guava which makes all of this simpler anyway with its Files class.
Or if you're using Java 7, you could use a try-with-resources statement.
(I note that you're ignoring filePath by the way - why?)
You can write in catch block too : writer.write(errorMessage);
or you may redirect to Error page if error occured
I write to socket with:
OutputStream socketStream = socket.getOutputStream();
socketStream.write(buf);
But this can throw IOException, so I do:
try {
OutputStream socketStream = socket.getOutputStream();
socketStream.write(buf);
} catch (IOException e) {
// logging
} finally {
socket.close();
}
But socket.close also force me to catch IOException! So do I need try ... catch it again in finally?
When catch IOException from close, it mean socket not closed? So try close again? Or what to do?
Thanks
close() throws IOException because closing something usually implies calling flush(), and flushing might fail. For example, if you lose network connectivity and issue socket.close(), you cannot flush whatever you have buffered, so flush() will throw an exception. Because data might be lost, the exception is checked, so you are forced to deal with that possibility.
I think the best way to deal with this is:
try {
OutputStream socketStream = socket.getOutputStream();
socketStream.write(buf);
socket.close();
} catch (IOException e) {
// try to deal with your I/O error; do logging
} finally {
closeSilently(socket);
}
...
// Somewhere else, usually part of an utility JAR like Apache Commons IO
public static void closeSilently(Socket s) {
if (socket != null) {
try {
socket.close();
} catch (IOException e2) {
// do more logging if appropiate
}
}
}
This code will work normally in the common case. If something goes wrong (even inside close()), it will allow you to catch the exception and do something before unconditionally closing your socket and swallowing everything it might throw.
The Exception thrown by close can usually just be ignored (well you can log it). That's pretty much the same as throwing an exception in a destructor in C++ - there's not much (usually nothing) you can do about it and trying to close it again is nonsensical. Cleanup throwing exceptions is usually bad design - you can implement cleanup code for the cleanup but that's a recursive problem, in the end you'll just have to except that you can't handle it.