Is the use of NullPointerException recommended in this case:
/**
* Drop the database referenced by the singleton.
*
* #throws NullPointerException
*/
public static void dropDatabase() throws NullPointerException {
if (store != null) {
store.dropDatabase(DATABASE);
} else {
throw new NullPointerException("No valid database connection.");
}
}
Well it's pretty pointless code in that you'd still get a NullPointerException if it unconditionally called store.dropDatabase. You wouldn't get the same message, but the stack trace would make it pretty clear.
In this case I would say it should be an IllegalStateException though:
Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.
Sounds exactly like the situation to me. I'd also do the check first, like this:
if (store == null)
{
throw new IllegalStateException("No valid database connection.");
}
store.dropDatabase(DATABASE);
That way you can get all the preconditions out of the way at the start of the method, and then focus on the main body.
With Guava, I'd just change this to:
Preconditions.checkState(store != null, "No valid database connection.");
store.dropDatabase(DATABASE);
It's OK. Ideally, you should not be needing to write if ... else, the dropDatabase method, if using store in any useful way, will throw NPE automatically.
Related
I'm creating a "File Manager" to practice my IO skills. If I'm creating a file, how would I handle an error if file#createNewFile() returns false?
#Override
public void run() {
File file = new File(src + "\\" + srcName);
try {
if (file.createNewFile()) {
MessageHandler.createSuccess(comp);
} else {
throw new IOException();
}
} catch (IOException e) {
MessageHandler.error500(comp);
}
}
Right now I'm simply throwing an IOException to be caught in the next block, but I'm not sure if that is the best idea. It should be fine on the client end but when debugging I would have no idea what went wrong internally.
It depends. I guess there is no single clear answer to this, so other members of the community might view this differently than I do.
According to the Javadoc, createNewFile returns false only if the file already exists.
Therefore, in cases where the file should not be present whatsoever, I also just throw an IOException.
If I have a reason to assume the file could be present, the user interacting with the program should be notified of this problem in some way. How exactly you do this depends on the UI of your program.
The code snippet you showed us does not make much sense. Throwing an exception, just to catch it immediately, isn't very performant (unless the clever Java optimizers eliminate the costly operations).
Your current run() method does:
MessageHandler.createSuccess() if the file didn't exist and could be created (file.createNewFile() returned true).
MessageHandler.error500() if the file didn't exist, but could not be created, e.g. because of not having the necessary permissions (file.createNewFile() threw an IOException).
MessageHandler.error500() if the file already existed (file.createNewFile() returned true). [Are you sure that already having the file is an error?]
For the case number 3, creating, throwing and catching an IOException does not serve any useful purpose (other than guiding the code into the catch clause).
I'd simply rewrite the code to something like
#Override
public void run() {
File file = new File(src + "\\" + srcName);
try {
if (file.createNewFile()) {
MessageHandler.createSuccess(comp);
} else {
MessageHandler.error500(comp);
}
} catch (IOException e) {
MessageHandler.error500(comp);
}
}
You might even find a result code different from 500, better representing the cause of the failure.
Exceptions are a very good way for one method to communicate to the other methods up its caller hierarchy that it wasn't able to do its job. Throwing and catching an exception within one method rarely is a good idea.
void appendFile() throws IOException{
FileWriter print = new FileWriter(f, true);
String info = GetData.getWord("Write desired info to File");
print.append(" "); //Write Data
print.append(info);
System.out.println("this executes");
print.flush();
print.close();
}
boolean fileExist(){
return f.exists();
}
try{
if (f.fileExist())
f.appendFile();
else {
throw new IOException();
}
}
catch(IOException e) {
e.printStackTrace();
}
I'm not sure if the ecxeption is well handeled? The FileWriter is not going to be created if there is a fileNotFoundException, therefore don't need to be closed. However, is it possible that this code throws another kind of IOException after the file was opened?, and in that case do I need a finally block to close the file.
No.
It doesn't safely close the resource
The general rule is, if you call a constructor of an object that represents a closable resource, or a method that returns one which documents that this counts as 'opening the resource', which often but not always includes new being part of the method name (examples: socket.getInputStream(), Files.newInputStream), then you are responsible for closing it.
The problem is, what if an exception occurs? So, you have to use try/finally, except that's a mouthful, so there's a convenient syntax for this.
The appendFile method should use it; it isn't, that makes it bad code. This is correct:
try (FileWriter print = new FileWriter(f, true)) {
String info = GetData.getWord("Write desired info to File");
print.append(" "); //Write Data
print.append(info);
System.out.println("this executes");
}
Not how it is not neccessary to flush before close (close implies flush), and in this case, not neccessary to close() - the try construct does it for you. It also does it for you if you get out of the {} of the try via a return statement, via control flow (break), or via an exception, or just by running to the } and exiting normally. No matter how - the resource is closed. As it should be.
It throws description-less exceptions
else throw new IOException(); is no good; add a description that explains why the exception happened. throw new IOException("File not found") is better, but throw new FileNotFoundException(f.toString()) is even better: The message should convey useful information and nothing more than that (in other words, throw new IOException("Something went wrong") is horrible, don't do that, that message adds no useful information), should not end in punctuation (throw new IOException("File not found!") is bad), and should throw a type that is most appropriate (if the file isn't there, FileNotFoundException, which is a subtype of IOException, is more appropriate, obviously).
It commits the capital offense
You should not ever write a catch block whose contents are just e.printStackTrace();. This is always wrong.
Here's what you do with a checked exception:
First, think of what the exception means and whether the nature of your method inherently implies that this exception can occur (vs. that it is an implementation detail). In this case, you didn't show us what the method containing that try/catch stuff even does. But let's say it is called appendFile, obviously a method that includes the text 'file' does I/O, and therefore, that method should be declared with throws IOException. It's not an implementation detail that a method named appendFile interacts with files. It is its nature.
This is somewhat in the eye of the beholder. Imagine a method named saveGame. That's less clear; perhaps the mechanism to save may involve a database instead, in which case SQLException would be normal. That's an example of a method where 'it interacts with the file system' is an implementation detail.
The problem that the exception signals is logical, but needs to be more abstract.
See the above: A save file system can obviously fail to save, but the exact nature of the error is abstract: If the save file system is DB-based, errors would show up in the form of an SQLException; if a file system, IOException, etcetera. However, the idea that saving may fail, and that the code that tried to save has a reasonable chance that it can somewhat recover from this, is obvious. If it's a game, there's a user interface; you should most absolutely TELL the player that saving failed, instead of shunting some stack trace into sysout which they probably never even look at! Telling the user that something failed is one way of handling things, not always the best, but here it applies).
In such cases, make your own exception type and throw that, using the wrapper constructor:
public class SaveException extends Exception {
public SaveException(Throwable cause) {
super(cause);
}
}
// and to use:
public void save() throws SaveException {
try {
try (OutputStream out = Files.newOutputStream(savePath)) {
game.saveTo(out);
}
} catch (IOException e) {
throw new SaveException(e);
}
}
If neither applies, then perhaps the exception is either essentially not handleable or not expectable or nearly always a bug. For example, writing to an outputstream that you know is a ByteArrayOutputStream (which can't throw), trying to load the UTF-8 charset (which is guaranteed by the JVM spec and therefore cannot possibly throw NoSuchCharsetException) - those are not expectable. Something like Pattern.compile("Some-regexp-here") can fail (not all strings are valid regexps), but as the vast majority of regexes in java are literals written by a programmer, any error in them is therefore neccessarily a bug. Those, too, are properly done as RuntimeExceptions (which are exceptions you don't have to catch or list in your throws line). Not handleables are mostly an application logic level thing. All fair game for runtimeexceptions. Make your own or use something that applies:
public void save(int saveSlot) {
if (saveSlot < 1 || saveSlot > 9) throw new IllegalArgumentException("Choose a saveslot from 1 to 9");
// ... rest of code.
}
This really feels like door number one: Whatever method this is in probably needs to be declared as throws IOException and do no catching or trying at all.
Minor nit: Uses old API
There's new API for file stuff in the java.nio.file package. It's 'better', in that the old API does a bunch of bad things, such as returning failure by way of a boolean flag instead of doing it right (by throwing an exception), and the new API has far more support for various bits and bobs of what file systems do, such as support for file links and creation timestamps.
I'd like to know what is the best way or best-practice to handle this kind of situation. Guess a straightforward function like this:
public Object f1() {
Object result = null;
try {
String payload = methodThrowsAnException();
result = payload;
} catch (IOException e) {
throw new IllegalStateException(e); <<<<<<<<<<<<<<<
}
return result;
}
I'd like to know if it's a good practice:
to re-throw the exception or
return a null when something has been wrong inside.
I don't know if I've explained so well.
Re-throwing caught exception is a bad idea. most often, the stacktrace will contain more or less detailed information about your architecture. This would be to useful for an attacker.
I wouldn't allow my app to get into illegal state because of the user's action. In your case, I would say:
try {
String payload = methodThrowsAnException();
result = payload;
} catch (IOException e) {
throw new IllegalArgumentException(<user's input which caused the exception>); <<<<<<<<<<<<<<<
}
There is nothing wrong with returning a null from your method if there is a particular scenario where you expect that exception.
Alternatively you can just allow the Exception to bubble up, and be handled by the caller.
When would I catch and re-throw an exception? When I can convey better meaning by throwing a new exception.
Would I include the original exception when I throw a new one? I would do it if it is a unknown/unexpected scenario which requires further debugging.
Let me share some examples:
Something unrecoverable like Out of DB Connection. I would just let the exception bubble up. It should get handled just before it reaches the user, and probably end up in a generic error message like 'Service not available. Please try again later'.
Something application related... such as backup file not found. In that case I will swallow up the FileNotFoundException and instead I will throw a BackupFileMissingException which is specific to my application. Here I don't need to include the FileNotFoundException because it is an expected scenario and there is nothing further to investigate.
I call some other API and they throw an exception, which is not documented. In this case, I will translate it into my application exception such as InterfaceApiException and include the original exception, so that it can be logged at the REST/Action layer along with the root cause.
I am trying to send a message from the server to the client using the following method:
final public void sendToClient(Object msg) throws IOException
{
if (clientSocket == null || output == null)
throw new SocketException("socket does not exist");
output.writeObject(msg);
this.output.flush();
}
and before the
output.writeObject;
everything seems fine, but right after, the socket along with the input/output streams all become null..
Any idea why?
Edit:
Here is a link to all server-client parts of the code-
https://drive.google.com/open?id=0B02W0JiTbQUXS1RCVk9ORER3YUU
And when I wrote that the variables become null, what I mean is that there is no exception thrown (tried surrounding it with try-catch) and when I debug, it just changes after said specific line..
Some ideas:
somewhere else in your program the fields are being set to null;
the fields are not becoming null, another set of fields, that were not initialized, is being checked/causing the problem (e.g. from wrong instance); or
the java virtual machine is broken or something else very strange is going on.
the msg object, which we don't known what it is, is messing up the socket in its writeObject method
Anyway the posted code doesn't seem to be the cause for the fields becoming null, hard to make better guesses without a Minimal, Complete, and Verifiable example.
So, I know this is going to sound a little extreme but I'm trying to make a point:
OK. so my code doesn't care what kind of exception is being thrown, 99.9% of the time if an exception is being thrown it handles it the same no matter what.
Now, Why should i even bother throwing \ creating new exception in my code?
apparently all the libraries i use throw them already and the are very informative as well.
a null object passed for my method? who cares, a null pointer exception will be thrown automatically for me.
Can you make a good argument why should i create new exceptions and throw them?
EDIT what i mean:
why bother with this:
public myMethod() {
try {
doStuff1();
}
catch(Exception e) {
throw new Exception("Error in doStuff1");
}
try {
doStuff2();
}
catch(Exception e) {
throw new Exception("Error in doStuff2");
}
when i can use this:
public myMethod() {
doStuff1();
doStuff2();
}
Your client wants detailed error reporting. What went wrong, and where did it go wrong.
They don't have a clue what a null pointer exception is. And even then, that in itself is not particularly helpful without the stack trace. So a null pointer gets passed into your RetrieveReportX method? Check if it's null and throw a ReportXNoIdentifierException rather than letting it auto-throw a null pointer exception. Then you'll have a error handler somewhere that, based on these custom exceptions, can report exactly what went wrong in what (human) process, and your client is happy because rather than NullPointerException at [stacktrace], they can see "An identifier was not supplied when attempting to retrieve report X."
why should i create new exceptions and throw them?
In some cases it is common and good practice to throw Exception deliberately.
Take
IllegalArgumentException
If your method only accepts arguments within a particular range, e.g. only positive numbers, then you should check for invalid parameters and throw an IllegalArgumentException.
For example:
public int calculateFactorial(int n) {
if (n < 0)
throw new IllegalArgumentException("n must be positive");
if (n >= 60)
throw new IllegalArgumentException("n must be < 60");
...
}
public void findFactorial(int n)
{
try{
calculateFactorial(n)
}catch(IllegalArgumentException ie){
System.out.println(ie.getMessage());
}
}
From Java tutorials - Advantages of Exceptions
Advantage 1: Separating Error-Handling Code from "Regular" Code
Advantage 2: Propagating Errors Up the Call Stack
Advantage 3: Grouping and Differentiating Error Types
Answer
Exception handlers that are too general can make code more error-prone by catching and handling exceptions that weren't anticipated by the programmer and for which the handler was not intended.
As noted, you can create groups of exceptions and handle exceptions in a general fashion, or you can use the specific exception type to differentiate exceptions and handle exceptions in an exact fashion.