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.
Related
So im reading the below and i understand why you would do it..
https://jenkov.com/tutorials/java-exception-handling/exception-wrapping.html
example :
try{
dao.readPerson();
} catch (SQLException sqlException) {
throw new MyException("error text", sqlException);
}
So what if i want to isolate all external exceptions inside the dao layer only, and only use my exceptions. so in the above example i dont want to send SQLEXception inside the constructor, would doing the below be enough. Would it contain enough information :
throw new MyException("error text", sqlException);
or maybe my constructor should be the following instead
public MyException(String text,Exception ex)
You can inherit your exception from Exception like
MyException extends Exception {
}
and then use try catch like :
try {
dao.readPerson();
} catch (MyException ex) {
// handle Exception
}
by doing this you can do whatever you want in your class and i think its cleaner than other ways.
It will trigger automatically so you dont need to raise an exception.
If you want to catch SQL Exceptions only you can inherit MyException from SqlException so it will only trigger when SqlException happens
I understand that you worry about the catching part of your code knowing about the wrapped exception. In "not knowing" there are different layers.
Level 1: Nothing obligates the catching class to get the cause and therefor explicitly knowing about the SQLException. They just catch the MyException and don't care what's wrapped in it. Usually that's enough.
Level 2. Another level of not knowing is restricting the catching class to even have access to the wrapped exception. In that case why wrap it at all? Just catch the SQLException in your DAO layer and throw MyException without wrapping the original exception in it.
About wrapping the causing Exception instead of the original one. You could do that but you might lose valuable information so 99% of the time it's not recommended. There are some corner cases where I've done it though. Let's say you throwing code runs asynchronously through ExecutorService. Then if an exception is thrown it's wrapped to ExecutionException, but as a caller I might not be interested that the code ran asynchronously so I catch the ExecutionException, get it's cause (the actual exception that happened) and wrap that to my custom exception.
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
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.
I have a Java 1.4 web app that uses Hessian to make web service calls. I'm trying to write it as robust and transparent as possible. I don't want any hessian exceptions to make it out of my delegate class when calling the proxy. I want to be able to catch any Hessian runtime exceptions, unwrap them and either rethrow some of the major exceptions (e.g., ConnectException) or rewrap them in another exception. But finding these exceptions are a bit of a challenge.
Every method I have in my delegating class has this sort of structure.
public MyResult myMethod(MyArgsType myArgs)
throws ConnectException
{
try
{
return proxy.myMethod(myArgs);
}
catch (HessianRuntimeException ex)
{
Throwable cause = ex.getCause();
if (cause instanceof ConnectException)
throw (ConnectException)cause;
throw new MyRuntimeException(cause);
}
}
This has been working fine in my own tests but some other runtime exceptions are making it out and I'm missing them. For instance, we recently found that it may throw a HessianConnectionException caused by a SocketException (the remote server was down). I was fully expecting that what I currently have would have caught that. The HessianConnectionException doesn't derive from the HessianRuntimeException so now I have to add that exception to be caught.
public MyResult myMethod(MyArgsType myArgs)
throws SocketException, ConnectException
{
try
{
return proxy.myMethod(myArgs);
}
catch (HessianException ex) // HessianConnectionException derives from HessianException
{
Throwable cause = ex.getCause();
if (cause instanceof SocketException)
throw (SocketException)cause;
throw new MyRuntimeException(cause);
}
catch (HessianRuntimeException ex)
{
Throwable cause = ex.getCause();
if (cause instanceof ConnectException)
throw (ConnectException)cause;
throw new MyRuntimeException(cause);
}
}
Ok that's fine with me, it had to be done... but where does it end? I can't find any documentation on what other runtime exceptions that I need to be aware of or any of their underlying causes.
I'm hoping just catching HessianException and HessianRuntimeException would be enough since those are the only runtime exceptions that I can find listed here. But with these newly found issues, I'm not sure what exceptions I would want to unwrap since it seems like it's a mixed bag (as far as I knew, SocketException and ConnectException were different representations of the same problem).
Is there any documentation in what runtime exceptions are thrown when calling methods through the proxy and all their underlying causes?
I assume you have done web searches etc., so here is a fallback position in case you don't find the documentation you are looking for.
After your existing catches, catch RuntimeException. Test whether the Exception's class name begins with "Hessian" and/or check its package name. If it is not Hessian-originated, rethrow.
After you know it is a Hessian exception you can do something similar to your current strategy, looking through the cause chain for something that makes sense in your context or at least is from a non-Hessian package.
Have this method call:
->
simpleJdbcTemplate.queryForInt(SQL,null);
->
queryForInt() method in the springs SimpleJdbcTemplate throws a DataAccessException which is a runtime exception. I want to propegate exceptions to the view tier of the application since Spring frame work Wraps Checked Exceptions inside RuntimeExceptions I stuck here.
How do I do this?
Explanation 1:
The value-add provided by the Spring Framework's JDBC abstraction framework- they say The Spring Framework takes care of all except 3 and 6. 3 and 6 need to be coded by an application developer
Define connection parameters
Open the connection
Specify the statement
Prepare and execute the statement
Set up the loop to iterate through the results (if any)
Do the work for each iteration
Process any exception
Handle transactions
Close the connection
But if I encounter a situation where the connection to the database losses after certain time the program started. Then a runtime exception will be thrown when a call to the above method made.since I don't handle the exception I cannot inform the user interface (view).
Just because Spring throws a runtime exception doesn't mean you cannot catch it. If you want to do something special for DataAccessExceptions, you can certainly do that:
try {
// query logic
} catch (DataAccessException ex) {
// handle the exception
}
If you're using Spring's MVC framework, it may be worth looking into the ExceptionResolver interface. It's a mechanism for deciding how to handle all those uncaught exceptions thrown by the lower layers of the application. It gives you one last chance to display a different view based on exceptions that are thrown.
It depends if your view tier catches checked exceptions (any subclass of throwable that does not subclass RuntimeException or Error, or are not instances of RuntimeException or Error directly) or unchecked exceptions (RuntimeException or Errors or subclasses of these Throwable subclasses).
Generally, you'll either have something like this:
try {
//... processing
} catch(Exception/RuntimeException e) {
// propagate the exception to the view in a meaningful manner
}
If this is the case, for a runtime exception, you don't have to do anything - the block will catch the runtime exception.
If you want to convert it to checked, assuming you're using a version of Java that supports wrapped exceptions, all you have to do is:
try {
//...spring code
} catch(DataAccessException e) {
throw new Exception(e);
}
Then, your layer above this processing will catch it as a checked exception.
Do you just want to be able to access the original exception information in your View? If so, you should be able to invoke getCause() on the RuntimeException to get the underlying checked Exception that caused it. Otherwise you would need to add a "throws" declaration to your methods that are utilizing SimpleJdbcTemplate, catch DataAccessException and rethrow the checked Exceptions that are wrapped.