I just started learning Java, and I am stuck. I was told to handle a call to a method, in the main method that can throw different types of exceptions.
What is thrown: IOException
How to handle: Wrap in an IllegalArgumentException with a message "Resource error" and throw it
What is thrown: FileNotFoundException
How to handle: Wrap in an IllegalArgumentException with a message "Resource is missing" and throw it:
This is a starting point, that is given:
static Exception exception = new FileNotFoundException();
public static void main(String[] args) throws Exception {
riskyMethod();
}
public static void riskyMethod() throws Exception {
throw exception;
}
To handle the exceptions riskyMethod() can throw, put it into a try-catch block. You can put several catch blocks after try to handle different exceptions. To wrap any exception into an IllegalArgumentException pass the exception as the second argument to the constructor. The first argument is the error string.
The whole code:
static Exception exception = new FileNotFoundException();
public static void main(String[] args) throws Exception {
try{
riskyMethod();
}catch(FileNotFoundException e){
throw new IllegalArgumentException("Resource is missing", e);
}catch(IOException e){
throw new IllegalArgumentException("Resource error", e);
}
}
public static void riskyMethod() throws Exception {
throw exception;
}
I did not test this code, but after adding the necessary imports it should work.
First, remove throws Exception from your main.
Handling an exception means not re-throwing it, or throwing a different one.
Catch the exception and do something with it:
public static void main(String[] args) {
try {
riskyMethod();
} catch (IOException e) {
System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage());
}
}
You can print what you like - this is just a suggestion.
Note that you don't need to specifically catch FileNotFoundException, because it is an IOException.
Related
In Java 7 Rethrow Exception feature added.I know it's concept but I want to see the real application of it and why this feature needed?
I will take examples from here
This is the example:
static class FirstException extends Exception { }
static class SecondException extends Exception { }
public void rethrowException(String exceptionName) throws FirstException, SecondException {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
} else {
throw new SecondException();
}
} catch (FirstException e) {
throw e;
}catch (SecondException e) {
throw e;
}
}
This compiles with both java 6 an 7.
If you want to keep checked exceptions from method signature, you have to keep cumbersome catch clauses in java 6.
In Java 7 you can do it in following way:
public void rethrowException(String exceptionName) throws FirstException, SecondException {
try {
if (exceptionName.equals("First")) {
throw new FirstException();
} else {
throw new SecondException();
}
} catch (Exception e) {
throw e;
}
So your benefit is that you have less cumbersome catch clause.
Use Rethrowing Exceptions with More Inclusive Type Checking feature
in Java SE 7, you can specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration
When you want to declare specific exceptions that can be thrown (mainly when you are catching a generic error)
For example see Precise Rethrow example:
public static void precise() throws ParseException, IOException{
try {
new SimpleDateFormat("yyyyMMdd").parse("foo");
new FileReader("file.txt").read();
} catch (Exception e) {
System.out.println("Caught exception: " + e.getMessage());
throw e;
}
}
This also make your code compliant to Sonar's Raw Exception rule.
Note you can similarly catch Throwable
Couple of use-cases:
Using rethrow, you can edit the stacktrace information to make
it more accurate. Also when needed you can hide or rid off the
unnecessary internal details in stack trace.
try { //... }
catch (Exception e) { throw (Exception) e.fillInStackTrace(); }
Real application of fillInStackTrace is very well explained here:
Why is Throwable.fillInStackTrace() method public? Why would someone use it?
Quote from the book "Thinking in Java" written by Bruce Eckel:
If you want to install new stack trace information, you can do so by
calling fillInStackTrace( ), which returns a Throwable object that it
creates by stuffing the current stack information into the old
exception object
Add custom message to the thrown exception. Add custom message to thrown exception while maintaining stack trace in Java
A simple example I can think of:
void fileOperator(String operationType) throws Exception(){ ... }
void fileReader() throws Exception {
try{
fileOperator('r');
}
catch(Exception e){
throw Exception("Failed to read the file", e);
}
}
void fileWriter() throws Exception{
try{
fileOperator('w');
}
catch(Exception e){
throw Exception("Failed to write the file", e);
}
}
Also, we can throw a more specific exception type (say FileReadException, FileWriteException) from the catch block.
Ive two method that throw the same exception throws IOException
the problem is that each method throw it from different reason, I wrap the methods
in the main with try catch, what is the recommended way to solve it ?
I need different message for each exception with the same type..
public static void main(String[] args) {
try{
….
readFile(path);
convert(file)
} catch (IOException e) {
…..
}
private static String readFile(String path) throws IOException {
//Here files requires IOException - Reason here cannot Read file
String lineSeparator = System.getProperty("line.separator");
List<String> lines = Files.readAllLines(Paths.get(path));
}
private static String convert(String file) throws IOException {
//Here reader requires also ioException- Reason here cannot parse file
ObjectMapper reader = new ObjectMapper(new YAMLFactory());
Object obj = reader.readValue(file, Object.class);
}
There are several ways you could approach this. One way, perhaps the heaviest in terms of new code you would need to write, would be throw a custom exception from each of your helper methods. Then you could catch each specific exception in a separate block.
But what I might recommend here is that you simply wrap each of the two calls to your helper methods in separate try-catch blocks:
try {
readFile(path);
} catch (IOException e) {
// handle first exception here
}
// more code
try {
convert(file)
} catch (IOException e) {
// handle second exception here
}
This is fairly clean and doesn't require a lot of refactoring. If you keep encountering this problem, then maybe consider creating custom exceptions for your application. If you have a look at many Java libraries, you will see that they often use their own custom exceptions.
If you wanted to go the route of using a custom exception, you could define one, e.g.
public class FileReadIOException extends Exception {
public FileReadIOException(String message) {
super(message);
}
}
and then use it:
private static String readFile(String path) throws FileReadIOException {
try {
String lineSeparator = System.getProperty("line.separator");
List<String> lines = Files.readAllLines(Paths.get(path));
}
catch (Exception e) {
throw new FileReadIOException(e.getMessage());
}
}
try {
readFile(path);
// more code
convert(file)
} catch (FileReadIOException e) {
// handle first exception here
} catch (SomeOtherException e) {
// handle second exception here
}
The above code showing custom exception is a bit contrived, because the reality is that all of your code is throwing IOException. Creating custom exceptions in your case does not add much value, because they are already (rightfully) throwing an IOException. I'm not sure that it doesn't make sense to handle just one type of exception. More typically, if you were working on a large enterprise application, you would use custom exceptions to handle situations which go wrong in your own custom code.
My way is usually to create your own exception and throw it like that
public class Snippet {
public static void main(String[] args) {
try {
String path = "";
readFile(path);
String file = "";
convert(file);
} catch (MyException e) {
// do whatever
}
}
private static String readFile(String path) throws MyException {
try {
String lineSeparator = System.getProperty("line.separator");
List<String> lines = Files.readAllLines(Paths.get(path));
} catch (Exception e) {
throw new MyException("Custom 'readFile' message", e);
}
}
private static String convert(String file) throws MyException {
try {
ObjectMapper reader = new ObjectMapper(new YAMLFactory());
Object obj = reader.readValue(file, Object.class);
} catch (Exception e) {
throw new MyException("Custom 'convert' message", e);
}
}
}
class MyException extends Exception {
private static final long serialVersionUID = -3166824380774329449L;
public MyException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
}
Tim's way is valid too.
#OP The best person to solve this would be you yourself.
There are quite easily multiple ways to solve that. Check which one suits you more properly.
One of the solution as per me is below. This is based on the reason IOException is superclass to many other exceptions. IOException documentation
try {
readFile(path);
} catch ( FileNotFoundException e) {
// handle first exception here
} catch ( EOFException e) {
// handle 2nd exception here
}
For the above to work you would need to know which type of IOException is being thrown.
Another solution is check individual exception messages when you know what are expected messages you may receive.
try {
readFile(path);
} catch ( IOException e) {
if(e. getMessage().contains("TXT 1...") {
//Case handle #1
} else if(e. getMessage().contains("TXT 2...") {
//Case handle #2
}
}
The best way to handle exception is not to have them. When exception is thrown, it indicates that natural lifecycle of your application has been interrupted for one reason or another. Most exceptions are self-explanatory and provide you with precise explanation of what happend, therefore creating new exceptions and re-mapping those thrown is almost always counterproductive and may result in more confusion than usefulness(especial if you work in a team).
Furthermore exceptions doesn't need to be terminal, in most cases, a scenario can be devised to retry/prompt different input etc. to ensure that lifecycle is not interrupted. Killing an application on exception can create more problems in some cases (e.g: not closing files properly, hence losing processed data).
Now to your actual problem. If you have two or more components, that throws unrelated exceptions(name is not a relation in this case), it is best not to have them in the same try/catch structure as less workaround will be necesary to scrap that one part, instead of the whole thing which can still exit on its own, or doesn't even need to be initiated.
Here is my 5 cents
public static void main(String[] args) throws Exception {
String path = "path";
String path2 = "path2";
try{
readFile(path);
} catch (IOException e) {
throw new Exception("read file exception", e);
}
try{
convert(path2);
} catch (IOException e) {
throw new Exception("convert exception", e);
}
}
private static String readFile(String path) throws IOException {
//Here files requires IOException - Reason here cannot Read file
String lineSeparator = System.getProperty("line.separator");
List<String> lines = Files.readAllLines(Paths.get(path));
}
private static String convert(String file) throws IOException {
//Here reader requires also ioException- Reason here cannot parse file
ObjectMapper reader = new ObjectMapper(new YAMLFactory());
Object obj = reader.readValue(file, Object.class);
}
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");
}
}
In Java, if a general exception is caught and rethrown, will outer methods still be able to catch specific exceptions?
In other words, can I do this:
try {
try {
//...
} catch (Exception e) {
//...
throw e;
}
} catch (SpecificException e) {
//...
}
re-throwing an exception does not change anything about it (it's still the same object originally thrown).
While jtahlborn answer is correct, there is one more appreciation: the compiler will see that you are throwing an exception of the generic type (even if at runtime it can be only of the specific class) and will force you to declare the generic exception in the method header.
private void test() throws FileNotFoundException {
try {
throw new FileNotFoundException("Es una exception");
} catch (IOException e) {
throw e; <-- Error because the method only throws
FileNotFoundException, not IOException
}
}
e is indeed FileNotFoundException, but as it is declared as IOException the compiler works with the broader class. What you can do is "cast" the exception.
throw (FileNotFoundException) e;
Eclipse marks the "throw e" in the inner catch as an unhandled exception, BUT it does catch the exception because when I run this it prints "It worked!". Thanks #jtahlborn. Unfortunately this means that there will still need to be an unnecessary try/catch block somewhere.
public class Tester {
public static void main(String[] args) {
try {
try {
throw new SpecificException("Test!");
} catch (Exception e) {
throw e;
}
} catch (SpecificException e) {
System.out.println("It worked!");
}
}
}
When trying to write read an int from standard in I'm getting a compile error.
System.out.println("Hello Calculator : \n");
int a=System.in.read();
The program throws an exception:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Unhandled exception type IOException at SamplePackege.MainClass.main(MainClass.java:15)
How do I fix this error?
My Code :
try {
Scanner sc = new Scanner(System.in);
int a=sc.nextInt();
} catch (Exception e) {
// TODO: handle exception
}
in.read() can throw a checked exception of type IOException.
You can read about Exception Handling in Java Here.
You can either change your program to throw an IOException, or you can put the read in a try catch block.
try{
int a=System.in.read();
catch(IOException ioe){
ioe.printStackTrace();
}
or
public static void main(String[] args) throws IOException {
System.out.println("Hello Calculator : \n");
int a=System.in.read();
}
The program doesn't have a bug.
The method read() requires you to catch an Exception in case something goes wrong.
Enclose the method inside a try/catchstatement:
try {
int a = System.in.read();
...
}
catch (Exception e) {
e.printStackTrace();
}
In any case I strongly suggest you to use documentation and/or Java tutorials, in which these things are clearly stated. Programming with out using them is just pointless. You will save yourself a lot of headaches, and probably also our time.