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.
Related
The scenario is like I wrote a MVC-based application:
Controller - Service - DAO layer. Now I got an exception in DAO layer and I want to handle that exception in presentation layer so that service layer needs no change.
Because by using regular try/catch or throws it has to pass through the service layer which I don't want.
Is there any better approach to achieve it?
class Controller{
method1(){}
}
class service(){
method1Serice(){}
}
class DAO(){
method1DAO(){
// exception occurs here
}
You can have the DAO class throw an unchecked exception. (any subclass of RuntimeException will do). You can create your own custom exception or use any of the predefined ones. just make sure the Service doesn't catch Throwable and you can have the Controller catch it.
You can extend your exception class from RuntimeException so that compiler does not complain about exception handling. You can then catch that exception in the presentation layer.
Perhaps you are looking for Controller Based Exception Handling, you can check these in Exception Handling in Spring MVC and also Error Handling for REST with Spring.
#ExceptionHandler(YourException.class)
public String handleException(){
logger.info(message);
return "database_error";
}
Actually I would suggest you handle the exceptions properly in Service-Layer and encapsulate that exception properly to return to the front-user via Controller-Layer.
Normally, checked exceptions are carrying some meaningful messages which can be used to do recovery or let the caller explicitly handle it properly. Try not to directly avoid it since it's there.
As I understand it, a data access object (DAO) is intended for transferring data between the server and the client. I'm assuming that the client is what you refer to as the presentation layer. In other words, the part that the end user interacts with. As such, the DAO should contain fields and accessor methods only, i.e. it should not contain logic. Hence it should not contain methods that may throw exceptions. So I would suggest perhaps re-designing your application. Otherwise, perhaps you can provide more detailed code?
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.
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.
I want to use an interceptor for my bean, which will check the validity of a given connection token.
If the connection is invalid, I want to throw a particular exception, if the connection expired, I want to send another (TokenExpiredException, something like this). These Exceptions are included in the interface given to the client.
#AroundInvoke
public Object checkParams(InvocationContext ctx) throws TokenExpiredException, Exception{
//code to check token
//...
throw new TokenExpiredException();
}
From what I tried, throwing such specific Exception in the Interceptor leads to an UndeclaredThrowableException on the client side. While this exception includes the reference to the cause, it is not really ideal, and can't be dealt with with regular catch clauses.
What is the correct way then to declare different Exception types with Interceptors?
I don't think there is a correct way to do that. Methods should throw only the exceptions they declared, and an interceptor shouldn't add a new one.
My personal case got fixed by adding an error code to our default exception which is thrown by all methods.
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/