Say we have a method changeUserName(Long id,String newName) which invokes the repository's findUser(Long id) to find the right user entity and then change its name. Is it appropriate to thow an IllegalArgmentException when findUser returns null ? Or should I instead throw a custom UserNotExistException (extends AppException extends RuntimeException) ?
UPDATE:
RuntimeException:
#nachokk #JunedAhsan Actually I deliberately make all the exceptions unchecked , because I think this way makes client code clean , easy for debuging and more safe. As to those "unhandled" ones, I'll catch them all on the top of layers thus avoiding showing them on the UI.
This is due to the fact that many clients catch checked exceptions and then just ignore it, and in some cases they don't know how to handle it. This is a hidden trouble.
Clarification:
Sorry for my bad English. What I meant is if the changeUserName should throw an IllegalArgumentException, not the findUser method. And another question: how to differentiate illegal argument from business rule violation?
You should use UserNotExistException. The name is very declarative of what is happening. In my opinion you should to avoid returning null but if you do you have to document it.
UPDATE
I was thinking and as #JunedAhsan suggest, UserNotExistException could be better a CheckedException (extends from Exception and not RuntimeException).
From this link: Unchecked Exceptions : Controversy
If a client can reasonably be expected to recover from an exception,
make it a checked exception. If a client cannot do anything to recover
from the exception, make it an unchecked exception.
/**
* #return User found or throw UserNotExistException if is not found
*/
public User findUser(Long id) throws UserNotExistException{
//some code
User user = giveMeUserForSomePlace();
if(user == null){
throw new UserNotExistException();
}
return user;
}
It depends on how you handle exceptions.
IllegalArgumentException is ok if you only display error report by using e.getMessage() and you don't care repetitive string appending code.
Here is some advantage I find by using custom exceptions:
1. Reduce reptetive code:
Let's say changeUserName is surely not the only case you'll load User, so this code snippet below will happen everytime you invoke repository.findUser(Long id)
if (user == null) {
throw new IllegalArgumentException("No such user found with given id["+ userId +"]");
}
On the other hand, an ad-hoc exception is much more handy:
if (user == null) {
throw new UserNotExistException(userId);
}
public class UserNotExistException extends RuntimeException {
public UserNotExistException(Long id) {
super("No such user found with given id["+ id +"]");
}
}
2. You need more support from your exceptions:
Maybe you need to return status code or something like that. An custom exception hierachy may do some help:
see this answer for detail.
I would too suggest to use UserNotExistException but with a difference that instead of it being unchecked exception (by virtue of extending RuntimeException), make it checked exception (extending Exception if AppException is not doing this already).
This will make sure that caller of changeUserName handles UserNotExistException exception and make the code a bit robust.
Related
My understanding of these exceptions is if an object in the database that you are looking for doesn't exist or exists these gets thrown? But is it ok for myself to use when I want to handle different cases in MyServiceClass.
Is it bad practice to throw these exceptions or should I create my own Exceptions for let's say if a user dont exist in the database?
How does it work in a real production?
Thanks in advance!
You should only implement a custom exception if it provides a benefit compared to Java's standard exceptions. The class name of your exception should end with Exception.
But it’s sometimes better to catch a standard exception and to wrap it into a custom one. A typical example for such an exception is an application or framework specific business exception. That allows you to add additional information and you can also implement a special handling for your exception class.
When you do that, make sure to set the original exception as the cause. The Exception class provides specific constructor methods that accept a Throwable as a parameter. Otherwise, you lose the stack trace and message of the original exception which will make it difficult to analyze the exceptional event that caused your exception.
public void wrapException(String input) throws MyBusinessException {
try {
// do something
} catch (NumberFormatException e) {
throw new MyBusinessException("A message that describes the error.", e);
}
}
Try not to create new custom exceptions if they do not have useful information for client code.
And if you make a custom exception be sure to:
Document the Exceptions You Specify
Throw Exceptions With Descriptive Messages
Catch the Most Specific Exception First
Don’t Log and Throw
Currently my signup looks like this:
public void signup(User newUser) throws Exception {
log.info("Sign up: " + newUser.getEmail());
if (restService.emailAlreadyExists(newUser.getEmail())) {
throw new Exception("Email already in use.");
}
List<Role> roles = new ArrayList<Role>();
roles = roleRepository.findAllOrderedByName();
roles.add(roleRepository.findByName("user"));
newUser.setRoles(roles);
newUser.setPassword(restService.getHashedValue(newUser.getPassword()));
try {
em.persist(newUser);
} catch (Exception e) {
throw new Exception("Just noobs use apps with less bugs. Try again. Now!");
}
log.info(newUser.toString());
userEvent.fire(newUser);
}
In first order I'm just interested in two messages (will become FacesMessage) for the user. To prevent other cryptic messages for the user, I even would need to extend the try-block up to roles.
Well, that would be bad practice, I guess. Also using a generic Exception smells, they say. But: I detect following documented Exceptions in this small piece of code:
IllegalStateException
IllegalArgumentException
EntityExistsException
TransactionRequiredException
ObserverException
Even not speaking about the eight(!) Exceptions of the method getSingleResult() of javax.persistence.TypedQuery.
Should I really handle all Exceptions in this example, or is it ok to skip a few (and/or maybe even use a generic Exception like above).
Best practice is: catch all exceptions separately and make as more custom log messages as possible. It's easier to understand faulty situations and to act accordingly.
Reality in a typical business application is: try to group your exceptions (ex. group all possible exceptions caused by your method input, all the ones throwed by the db etc. etc.) and learn that sometimes you will put the infamous catch (Exception e) or rethrow a generic exception with a generic message... or people will start calling you about logs growing like elephants.
I have service, a simple class that need to take input and run some business logic. Before executing this service, the user must set all the data. In general, it look like this:
public class TestService extends InnerServiceBase {
/**
* Mandatory input
*/
private Object inputObj;
#Override
protected ErrorCode executeImpl() {
//Some business logic on inputObj
return null;
}
public void setInputObj(Object inputObj) {
this.inputObj = inputObj;
}
}
What is the best runtime exception to throw in case the inputObj is null ?
IllegalStateException seems like the best fit. The object is not in the correct state to have executeImpl() called on it. Whatever exception you use, make sure the error message is helpful.
Whether you should be using an unchecked exception at all is a whole other question...
Depends on the scenario.
If this is part of an API that another developer is using, throwing NullPointerException is reasonable since you don't want that input to be null. Adding a descriptive exception message would be helpful.
If you're not interested in throwing an NPE, or this is part of code that's not going into an API, then you could throw an IllegalArgumentException, as null could be considered an illegal argument.
If setInputObj is called with a null argument, and that's not valid, then throw NullPointerException. There's some debate over the "correct" exception here (IllegalArgumentException or NullPointerException for a null parameter?), but Guava, Apache Commons Lang and even the JDK itself (Objects.requireNonNull) have settled on NPE.
If executeImpl is called before inputObj has been set, throw IllegalStateException.
I have some function works with database.
I have set a try/catch for error handling here, and display a message, It works fine.
Now the class calling this delete function need to know if there is a error or not. In my case : refresh the GUI if success, nothing to do if fail (as there already show up a message message dialog).
I come up a idea to return boolean in this function.
public static Boolean delete(int id){
String id2 = Integer.toString(id);
try {
String sql =
"DELETE FROM toDoItem " +
"WHERE id = ?;";
String[] values = {id2};
SQLiteConnection.start();
SQLiteConnection.updateWithPara(sql, values);
} catch (SQLException e) {
Main.getGui().alert("Fail when doing delete in DataBase.");
System.out.println("Exception : "+ e.getMessage());
return false;
}
return true;
}
Don't know if this is good or bad, please tell.
EDIT :
Here is more detail for How do I use :
Let's say the code above is inside Class A,
in Class B :
public boolean deleteItem(int id){
int i = index.get(id);
if(theList[i].delete()){ //<---- here is the function from Class A
theList[i] = null;
index.remove(id);
retutn true;
}
retutn false;
}
I need to pass the boolean in more than one class, I don't know if that can better through...
in Class C :
public void toDoList_deleteItem(){
MyButton btn = (MyButton)source;
int id = btn.getRefId();
List toDoList = Main.getToDoList();
if(toDoList.deleteItem(id)){ //<-------function in Class B
Main.getGui().refresh();
}
}
Edit 2 :
I have notice the question is somehow more likely asking "What should I handle a Exception at database Layer that affect to GUI Layer ?"... Something like that. Please correct me if the question title should be edit.
It looks like you are returning a boolean status to indicate that an exceptional condition had occurred. Generally, this is not a good practice, for two reasons:
It encourages an error-prone way of handling exceptions - it is very easy to miss a status check, leading to ignored errors
It limits your API's ability to report errors - a single pass/fail bit is not always sufficient, it may be desirable to pass more information about the error.
A better approach would be to define an application-specific exception, and use it in your API. This forces the users of your API to pay attention to exceptional situations that may happen, while letting you pass as much (or as little) additional information as you find necessary. At the same time, your code does not get polluted with if (!delete(id)) { /* handle error */ } code on each API call, shrinking your code base, and improving its readability.
Can you tell me more about "define an application-specific exception", or show some code example please?
Here is how I would do it:
public class DataAccessException extends Exception {
... // Define getters/setters for passing more info about the problem
}
...
public static void delete(int id) throws DataAccessException {
try {
... // Do something that may lead to SQLException
} catch (SQLException se) {
// Do additional logging etc., then
throw new DataAccessException("Error deleting "+id, se);
}
}
Note: It is common to give custom exceptions four constructors mirroring the constructors of the Exception class to allow exception chaining. The constructors are described here.
As long as you do not want the caller to know what happens, just that it fails (and that failing is part of its intended behavior) you should be fine.
That being said, I am noticing this: Main.getGui().alert("Fail when doing delete in DataBase.");.
It would seem that you are accessing the GUI layer from some other place. This might cause issues should you decide to multi-thread your application. Also, it is usually considered good practice to have your layers not intersect.
Don't return a Boolean, return a boolean. Since this is not an exception / error condition, it is fine.
Exceptions should be used when you don't expect a failure.
In your case, if it's fine for you that a SQLException is thrown and does not affect your program, it's ok to return a boolean.
If the SQLExcetion causing the delete to fail can cause problems in another part of your application it's better to throw an exception.
Edit:
Based on your edits, it seems that you are doing some maintenance and cleaning when an error happens. In such a case I would recommend to use Exceptions better than using booleans to control the execution.
This question is primarly opinion based. Personally I would prefer not to catch the exception at that point.
Depending on what the caller of delete() should do, you might need other resulutions. So you should better add a throw statement and let the calling method decide if the error is critical - or if it can proceed.
Just true and false is not necessary enough to let the caller decide correctly. He won't know if deletion fails due to database errors, due to foreignkey constraints, or something else.
letting the exception bubble up the call stack will provide the caller with the exact error going on, increasing the chance to handle the error in a proper way, or just displaying a custom error message helping the user to take proper actions.
Requirements:
Section is created by selecting one teacher, one subject and one
schedule.
System verifies that all business rules are followed.
System detects that a business rule is not being followed.
System informs user of conflict.
System doesn't create new section.
3.System creates new section.
My problem is, if I define a constructor for section, Section(Teacher t, Subject s, Schedule c), I don't know how to return the error message for the conflict.
Should I just let my constructor throw an exception? If yes, how to return a string from a caught exception? How to create that exception?
Or is there any better, yet simple, implementation?
Reporting constructor failure boils down to two options:
Throw an exception as you suggest. This is a reasonable approach if failure is not expected to happen often and is truly "exceptional".
If failure is a normal part of the business logic, I'd recommend using the Factory pattern and returning a wrapper object that contains the newly created object plus a status variable that can indicate the detailed causes of the failure when it occurs.
You can throw the exception for sure.
throw new Exception("Some required files are missing");
Or create a new Exception to be used in your app (it will work the same way)
If you want to read the message inside of a try / catch statement just do this:
try
{
// ...
}
catch(Exception ex)
{
System.out.println(ex.getMessage()); //this will get "Some required files are missing"
}
For more information checke these links out:
http://en.wikibooks.org/wiki/Java_Programming/Throwing_and_Catching_Exceptions
How to throw a general exception in Java?
http://docs.oracle.com/javase/6/docs/api/java/lang/Throwable.html#getMessage()
It isn't possible to return a value from a constructor. Your only way to do this is to throw an exception of some sort. You can either use an existing exception type (if there are any applicable) or create your own by extending Exception. For example:
public class MyException extends Exception {
public MyException(){
super();
}
public MyException(String message){
super(message);
}
}
Your constructor would simply throw a new instance of the exception and set an appropriate message. The code creating the class instance would catch the exception and handle it. You can obtain the message at that point by calling getMessage().