I am writing a web application using Spring 3 framework. Consider a situation where I have N number of controllers. Each controller delegates the request to exposed services and gets the response and return to users.
I would like to know if there is a better to way catch unexpected runtime exceptions thrown out of the controller code. I do not want to write something like the following for each of my controller methods. Or is it the only way?
try {
//call the service
} catch(ServiceException serviceEx) {
//do process for know exception
} catch(Exception ex) {
//return generic error message.
}
I know that we can use Spring Exception resolver. But I do not want to show different error page when unexpected error happens. I want to show some generic error message on UI as part of my widget?
Edit:
I also don't want my users to see the exception stacktrace when trying to perform some operations.
Sundar
I think catching RuntimeExceptions is bad practice. Originally RuntimeExceptions where thought as inicators to programming errors (e.g. NullPointerException to indicate that a null check is missing). Whereas checked exceptions where meant to indicate errors that the program can recover from (e.g. FileNotFoundException).
The problem today is that many frameworks use RuntimeExceptions where checked exceptions should be used. Therefore it is difficult to differentiate between cases where a program can handle the exception and where a programming error (bug) is encountered.
This is my personal view of this things for enterprise development. I know that most people mandate for dropping checked exceptions and handle everything as unchecked exception (as in Scala).
In my opinion you should only catch exceptions in your code from which you can recover. All other exceptions (checked or unchecked) should be caught by one über exceptionhandler which will log the exception and show the user some generic error page (possibly with an id that you can use to find what the exception was).
For example, in struts2 you would that this like so:
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="unrecoverableException"/>
</global-exception-mappings>
I never use spring mvc but this article seems to give you the options for an über exceptionhandler:
http://doanduyhai.wordpress.com/2012/05/06/spring-mvc-part-v-exception-handling/
You can catch runtime unexpected exceptions using this approach.
try {
...
} catch ( Exception e ) {
throw new RuntimeException("msg",e);
}
I think RuntimeException is designed for situations like breach of contract or some unrecoverable fault. Most of the time, you should just let the container or some outer infrastructure to handle it for you. Or you have to write a lot of redundant code to deal with them and it's kind of against the design philosophy of Spring.
In your case, may be you can leverage some filter or interceptor to catch those unexpected RuntimeException if you really need to transfer them to some other generic messages.
Related
I am new to Axon framework and am trying to implement an application using CQRS with state-stored aggregates. The application relies on a database constraint (using H2 for now) to enforce uniqueness on a name attribute. I would like to catch this exception and rethrow it as a user-friendly domain exception.
Per the Axon documentation:
Exception Handling says "an #ExceptionHandler will only handle exceptions thrown from message handling functions in the same class"
Message Intercepting documentation says "A function annotated with #ExceptionHandler will be regarded as a handler interceptor which will only be invoked for exceptional results. Using annotated functions to this end for example allow you to throw a more domain specific exception as a result of a thrown database/service exception."
But I cannot get this to work. I have tried adding exception handlers as follows:
#ExceptionHandler
public void handle(ConstraintViolationException ex) throws Exception {
if (ex.getMessage().contains("UNQ_COMPANY_ID") || ex.getMessage().contains("UNQ_PLAN_NAME")) {
throw new DomainException("Plan name and company id must be unique");
}
throw ex;
}
but this method is not called. I have tried putting the exception handler method on the aggregate and on a separate command handler class, tried adding resultType=ConstraintViolationException.class, and tried catching other types of exceptions including Exception, RuntimeException, AxonServerRemoteCommandHandlingException, etc. but this method is never called.
I can see the error in the log output:
org.axonframework.axonserver.connector.command.AxonServerRemoteCommandHandlingException: An exception was thrown by the remote message handling component: org.hibernate.exception.ConstraintViolationException: could not execute statement
Is it possible to catch database exceptions in state-stored aggregates? If it is, can someone point me towards what I am doing wrong?
The statement "an #ExceptionHandler will only handle exceptions thrown from message handling functions in the same class" makes me wonder whether I need to create a custom repository class (rather than using the default GenericJpaRepository) but that seems like a lot more work than should be necessary.
Thank you!
Update: I was able to roughly accomplish what I want by adding a UnitOfWork parameter to the #CommandHandler method and using it to registering a rollback callback on it as follows:
uow.onRollback(unit -> {
DefaultUnitOfWork duow = (DefaultUnitOfWork) unit;
Throwable ex = duow.getExecutionResult().getExceptionResult();
while (ex != null) {
if (ex.getMessage().contains("UNQ_PLAN_NAME")) {
throw new RuntimeException("Plan name must be unique");
}
ex = ex.getCause();
}
});
But this seems kind of verbose, as well as limiting me to throwing unchecked exceptions only. This also doesn't feel like the right way to do this though because I assume the purpose of the #ExceptionHandler annotation is to eliminate need for code like the above.
This is doable of course.
Actually, the best pointer I could give you if the code-samples repo where you can see a sample about distributed exceptions.
In general, as you could see in your shared log, the 'original' exception is wrapped into an AxonServerRemoteCommandHandlingException meaning you will have to handle that. Doing that, you can pretty much add anything to the details field of this class, adding the indication you had a ConstraintViolationException for example (or an ERROR_CODE, like HTTP protocol does) and you are fine to unwrap it on the other side.
What might be the "gotcha" you require, is to know that an #ExceptionHandler annotated method should reside in the object handling the message. So if you want to react to a failing command handling operation (which would be the case in your sample), you will need to place the exception handler in the Aggregate, next to the Command Handler.
That fact you get an AxonServerRemoteCommandHandlingException to me suggests the exception is caught on the command dispatching end. So, prior to dispatching a command on the CommandGateway/CommandBus.
However, whether this is the problem at hand, isn't clear to me right now, since the sample only shows the exception handler and not where it resides. Please share whether my assumption on the placement of the exception handler is correct. If not, we'll dive into this deeper to get to the cause.
I am implementing a spring rest application as a maven multi module project. controllers in web, service and dao as layers.
I am having issues to find the exact cause and stack trace for any exception in service layer. I am not using any try catch block in the service methods. Instead, I am just throwing an exception. Now when a null pointer exception is raised, the global exception handler is finding the exception. It says null, but does not provide any stack trace.
Do I need to use try catch blocks? If yes, I will have these blocks all over the service methods.
Any suggestions are welcome.
Your exception handler isn't displaying the stacktrace because you're not telling it to. Your code is bad and broken.
logger.error("Error: " + e.getMessage());
logger.error("Error [cause]: " + e.getCause());
Using getMessage() to see what exception you're having is useless. A NullPointerException returns as its message the String "null", which doesn't help you solve problems one bit. Logging the cause like that will call the toString() method of cause which won't be helpful either.
The only way to deal with exceptions is:
logger.error("Error", e);
This will log the stacktrace properly, including any causes (your code didn't even consider that a cause can also have a cause). You can use a custom message instead of "Error", but it doesn't really matter.
You can use #ExceptionHandler.
Here you'll find some examples and see that dont need to modify your current code. Remember to use a Logger or put a System.out.printLn() to see the stacktrace of the exception.
Also maybe you have to consider debug your method to see waht parameter or method is givin a null value.
How can I set an error in Request Context rather than throw an Exception?
Like:
void valid(Object o){
if(o == null){
//add an error to Request context
//I want to avoid the throw new ....
return;
}
}
I believe exception is not a functionality to be avoided.
It was created for a purpose, and should be used in this way.
The problem is when devs use them to help on the application's flow, because exception is an expensive solution for that, and there are other ways for doing so.
There is nothing wrong in throwing a BadRequestException for example when there is some user input failure. Some frameworks are already expecting specific exceptions, and most of them is already prepared for treatment for customized exceptions.
I have a medium-size Java Web-application using Log4J as logging-framework.
Right now i am going through my Exception handling and Logging to make my application more robust.
It is running on Tomcat 6, with spring, hibernate and Struts2 as frameworks.
What I would like to do is to log EVERY UNHANDLED exception that happens in the application. So that i can log them, make log4j send me an email, and then see where i am missing try-catch blocks. And finally modify my code accordingly.
Cause right now all the unhandled exceptions is printed direct to the screen, and my users usally do not bother to copy me the exceptions.
I know i can read tomcat-logs, but i would like to have them handled by log4j so that i can get an email on every such exception.
Any suggestions?
With Struts2, you can define global exception mappings for specific Exception types. If you define one for java.lang.Exception it acts as a catch-all for any exception not mapped elsewhere:
<global-exception-mappings>
<exception-mapping exception="com.example.MyException result="myError" />
<exception-mapping exception="java.lang.Exception" result="error" />
</global-exception-mappings>
<global-results>
<result name="myError">/myError.jsp</result>
<result name="error">/error.jsp</result>
</global-results>
In your error JSPs (*), you can then log them with log4j and give your users a nice "Something went wrong" error page without confronting them with confusing stacktraces.
(*) better: An error action where you can log the exception and only then let Struts render a JSP where you tell the user that something went wrong. No need to clutter JSPs with logging code.
About modifying all your code:
Don't blindly add catch blocks all over your code -- if some piece of code can't handle an exception, just let it propagate (adding a throws clause on the method signature if necessaty). At certain levels in the stack, consider wrapping the thrown Exception and adding some information to help identifying the cause and rethrow it:
catch (IllegalArgumentException ex) {
// Always pass the original exception along, never just the message.
// It's much easier to find the root cause that way.
throw new UpdateException("Failed to parse foo object: " + foo, ex);
}
Also, resist the temptation of emtpy catch blocks. They swallow the exception and you may never find out that something or what might be going wrong in your application. Log all exceptions unless you're very sure you'll never be interested in them.
Create a custom error page, see here: How to show user-friendly error page in browser when runtime exception is thrown by servlet?
In the error page you can add some java code to log the exception with log4j.
Note: it is generally considered bad practice to put java code in a JSP, but logging in an error JSP is one place where I think it is acceptable.
First, I am throwing run time exceptions for all unrecoverable exceptions, this causes these exceptions to travel up to the container, where I currently use an error page (defined in web.xml). In this error page is a scriptlet that invokes the logger.
The issue I am having with this is that the exception is no longer on the stack at this invocation. I have access to it from a request scope variable ("javax.servlet.error.message"). This string is the stack trace. I need this stack trace for logging purposes obviously, and on different app servers "javax.error_message" can be turned off for security reasons.......
So my question is, how can best log runtime exceptions from within Java EE apps without wrapping everything in this:
try {} catch (Exception e) {logger.log(...)}
?
I want some way to invoke the logger from the container maybe... right before the container catches the exception for example.
I found a solution. By adding a response filter and wrapping chain.doFilter(req, resp) like so:
try {
chain.doFilter(req,resp);
} catch (Exception e) {
logger.error("", e);
throw new RuntimeException(e);
}
This works fine so far and isn't dependent on a particular framework or app server.
There is nothing I know of in Servlet API to accomplish this.
However, you can do this in Tomcat with an instance listener. You can install a listener in context.xml like this,
<InstanceListener>myapp.MyListener</InstanceListener>
Tomcat fires InstanceEvent.AFTER_SERVICE_EVENT event right after the container catches the exception and before it throws the exception again. You can invoke the logger right there.
Correct me if I'm wrong, but the 'exception' object is present as a variable.. called 'exception' in your 'error' jsp. You could always use this object to log retrieve the exception information and log in in the error jsp itself.
AOP (Aspect Oriented Programming) would be my first choice.
You define:
join point (a runtime exception is thrown).
advice (your code to log the exception).
point cuts (which parts of your applications are "listening" this aspect).
Take a look at http://www.aspectj.org/