Best way to define error codes/strings in Java?
I am writing a web service in Java, and I am trying to figure out the best way to define error codes and their associated error strings. I need to have a numerical error code and an error string grouped together. Both the error code and error string will be sent to the client accessing the web service. For example, when a SQLException occurs, I might want to do the following:
// Example: errorCode = 1,
// errorString = "There was a problem accessing the database."
throw new SomeWebServiceException(errorCode, errorString);
The client program might be shown the message:
"Error #1 has occured: There was a problem accessing the database."
My first thought was to used an Enum
of the error codes and override the toString
methods to return the error strings. Here is what I came up with:
public enum Errors {
DATABASE {
@Override
public String toString() {
return "A database error has occured.";
}
},
DUPLICATE_USER {
@Override
public String toString() {
return "This user already exists.";
}
},
// more errors follow
}
My question is: Is there a better way to do this? I would prefer an solution in code, rather than reading from an external file. I am using Javadoc for this project, and being able to document the error codes in-line and have them automatically update in the documentation would be helpful.
Well there's certainly a better implementation of the enum solution (which is generally quite nice):
public enum Error {
DATABASE(0, "A database error has occurred."),
DUPLICATE_USER(1, "This user already exists.");
private final int code;
private final String description;
private Error(int code, String description) {
this.code = code;
this.description = description;
}
public String getDescription() {
return description;
}
public int getCode() {
return code;
}
@Override
public String toString() {
return code + ": " + description;
}
}
You may want to override toString() to just return the description instead - not sure. Anyway, the main point is that you don't need to override separately for each error code. Also note that I've explicitly specified the code instead of using the ordinal value - this makes it easier to change the order and add/remove errors later.
Don't forget that this isn't internationalised at all - but unless your web service client sends you a locale description, you can't easily internationalise it yourself anyway. At least they'll have the error code to use for i18n at the client side...
As far as I am concerned, I prefer to externalize the error messages in a properties files. This will be really helpful in case of internationalization of your application (one properties file per language). It is also easier to modify an error message, and it won't need any re-compilation of the Java sources.
On my projects, generally I have an interface that contains errors codes (String or integer, it doesn't care much), which contains the key in the properties files for this error:
public interface ErrorCodes {
String DATABASE_ERROR = "DATABASE_ERROR";
String DUPLICATE_USER = "DUPLICATE_USER";
...
}
in the properties file:
DATABASE_ERROR=An error occurred in the database.
DUPLICATE_USER=The user already exists.
...
Another problem with your solution is the maintenability: you have only 2 errors, and already 12 lines of code. So imagine your Enumeration file when you will have hundreds of errors to manage!
Overloading toString() seems a bit icky -- that seems a bit of a stretch of toString()'s normal use.
What about:
public enum Errors {
DATABASE(1, "A database error has occured."),
DUPLICATE_USER(5007, "This user already exists.");
//... add more cases here ...
private final int id;
private final String message;
Errors(int id, String message) {
this.id = id;
this.message = message;
}
public int getId() { return id; }
public String getMessage() { return message; }
}
seems a lot cleaner to me... and less verbose.