Throwing exceptions in Controller methods Play framework? - java

I am using Play framework (2.5) for Java development. In that, we configure routes and for those routes the relative controller methods to be triggered.
I have a question whether is it OK to include exception throws in these controller method signatures or we must catch them inside the method body?
EX:
public Result getPurchasedStatisticsOutOfAllPriceChecked(String from, String to) throws InvalidParameterException, SalesServiceException {
RequestParams requestParams = new RequestParams(messageProvider);
requestParams.setDateRangeStart(from);
requestParams.setDateRangeEnd(to);
return ok(processInfluenceOnSales(influenceOnOverallSales));
}

I think the better way is to handle those Exceptions inside your Action method, instead of throwing. By this you can respond to the client with relevant error message, otherwise you end up with
500 Internal server error
and your stacktrace looks like following play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception followed by respective exception trace.

Related

Axon framework: Handling database exceptions in state-stored aggregates

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.

Catching all exceptions and returning an exception with list of messages

I'm wondering if there is any elegant way to catch all exceptions (specifically custom runtime exceptions) and return an exception containing a list of the messages.
Instead of having a String message, the big exception would then contain String[] message for example.
Scenario:
A REST request is made to the back-end with a JSON object containing a bunch of fields. I want to validate these fields on the backend and return a list of errors if any exceptions occur.
If both the name and lastname field are not acceptable input, I don't want to throw an exception on the invalid name and have the user change the name and submit again only to get an error message that the lastname is invalid too.
Hence why I want to collect all invalid input and return a list of these in the form of an exception.
Spring collects JSR-303/JSR-349 bean validation failures into a BindException:
Thrown when binding errors are considered fatal. Implements the BindingResult interface (and its super-interface Errors) to allow for the direct analysis of binding errors.
Instead of developing your own mechanism for bean validation you might want to read 3. Validation, Data Binding, and Type Conversion and follow the standards.
With Spring Boot, you can use the following annotation to handle any kind of Exception for a class or a method :
#ExceptionHandler(YourExceptionHandler.class)
And you can create a class that let you regroup all your custom exception management like this (if you want to gather it) :
#ControllerAdvice
class GlobalControllerExceptionHandler {
#ResponseStatus(HttpStatus.CONFLICT) // 409
#ExceptionHandler(DataIntegrityViolationException.class)
public void handleConflict() {
// Nothing to do
}
}
You can also implement the interface HandlerExceptionResolver to manage all Exceptions that ARE NOT handled by the Controllers (all the others runtime Exceptions)
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex);
}
Everything is explained in details here : https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
EDIT: I just read that you added up scenario. Actually, for your special case, you should just parse the object, and return one exception (like bad object format, along with a 400 HTTP status code error, with a custom message containing all the fields that are invalid. I guess.

Java6 RuntimeException that returns Http status code

I found another post showing how we can create our own checked exceptions that also return a HTTP status code different from 500. However, I need it to be a RuntimeException.
Then, I found WebApplicationException which is an unchecked exception, returns a HTTP status code but does not allow me to set message as in a regular exception.
Is there any unchecked exception out there in Java EE 6 that allows me to set an error message like in a regular exception and also returns a HTTP status code that I can set?
Edit: Including an explanation of why I want this as requested by John.
I created a filter to catch HTML and XSS attacks from my requests parameters. Instead of checking for that everytime in Filter.doFilter which would be too slow, I extended HttpServletRequestWrapper and used it like this.
HttpFilterRequest implements Filter
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(new SafeHttpRequest((HttpServletRequest) request), response);
} catch (SecurityViolationException e) {
log.warn(format("A security violation was detected. Please enable debug for further details: %s]", e.getMessage()));
HttpServletResponse resp = (HttpServletResponse) response;
resp.sendError(e.getStatusCode());
}response);
}
SafeHttpRequest extends HttpServletRequestWrapper (supressing parts to shorten code)
#Override
public String getParameter(String parameter) {
return xssAndHtmlValidation(super.getParameter(parameter));
}
#Override
public String getHeader(String name) {
return xssAndHtmlValidation(super.getHeader(name));
}
xssAndHtmlValidation() throws SecurityViolationException which is a RuntimeException but the catch block at doFilter doesn't work because my exception is thrown as a ServletException containing SecurityViolationException.
Ok, so the issue is that you want SafeHttpRequest.xssAndHtmlValidation() to throw an exception that can pass out of HttpServletRequest.getParameter() and HttpServletRequest.getHeader(), neither of which declares any checked exceptions. You want this exception ultimately to be caught by HttpFilterRequest.doFilter(). You want it to have a customizable message and you want it to carry an HTTP response code.
You clearly do need an unchecked exception to approach the problem this way. It seems most appropriate to create a new one from scratch, by extending java.lang.RuntimeException. You can give that class whatever fields, constructors, and methods you want, by which to transport any information at all from xssAndHtmlValidation() to the filter. Doing so for an exception class is no different from doing so for any other class, though your constructors should be sure to invoke an appropriate superclass constructor.
The filter must then have a catch block for the new custom exception type. Since it is your own custom exception, it is unlikely to be caught by anything between the request and the filter, and since you will catch that specific exception, you can easily invoke whatever nice methods you provided for yourself, such as maybe a getResponseCode(). Presumably the catch block would then invoke one of the sendError() methods on the response object, and then return normally rather than throwing an exception up the stack.
Do note, by the way, that if the problem is detected too late, after the underlying resource has already committed to a different response, then attempting to sendError() will cause an IllegalStateException instead of changing the response code. The client won't see that (because, again, the response has already been committed), but the response might be truncated.
Note also that it is unclear whether you actually need your custom exception to carry an HTTP response code. Would it ever vary from one instance to another? If not, then the appropriate response code is inherent in the fact that the exception was thrown at all, and the filter can set a response code appropriately based solely on the fact that it has caught that particular exception type.
Update:
Of course, if your JSP engine is going to wrap your exception and throw it as a ServletException then you can catch that exception and decide what to do based on exception.getCause().getClass() (but do watch out for the cause being null). That could work if the engine has not already committed the response in such cases.
If your JSP engine is after all going to intercept all exceptions and convert them into HTTP code 500 responses, then any approach based on throwing an exception is simply a dead end. Your best option then is to handle it on the front end, in your filter, before passing the request down the chain. That's a natural fit for a filter.
You expressed concern that doing the test in the filter would be too slow, but that could be slower than your proposed alternative only if the request contains parameters or headers that are never examined by downstream components. On the other hand, your approach based on a request wrapper could in fact be the slower one if request headers or parameters are accessed more than once each downstream, as you will perform the validation on each access, even though you only need to perform it once per parameter / header.

Throwing exception for missing id in REST-API

I am creating a web service API following RESTful principles. In the service layer I have a method named:
/**
* #param answerId Id of the answer that will be deleted.
*/
void deleteAnswer(int answerId);
As you would expect this will delete the answer if the id of the answer is found in the system. Now, my question is:
Having this endpoint in the webservice:
HTTP DELETE /my-context/answers/{answerId}
the users of the API is able to add whatever id they want. They shouldn't, but they are able to. Because of that I want to throw an IllegalArgumentException from the service layer that I resolve HTTP message (Spring Web takes care of this). My other option would be to change the return type of the deleteAnswer method in the service layer so it returns true/false. What do you think?
If you return true false that means you are returning HTTP 200. While you should return 404. Spring has exception handler controller. You can throw your custom exception and define a exception handler which will send 404 with proper error message.
Returning an exception means that's an error to call your mehod like that. Returning true/false means that it's legal to call your service api like that.
Because you said "they shouldn't" I would go for exception.
I would rather use my own exception class that could be handled more cleanly than IllegalArgumentException.
Your web service should signal an error by specifying an appropriate status code, such as 400 or 404.
Your web service signature will then be:
ResponseEntity<Void> deleteAnswer(#PathVariable("answerId") int answerId);
You can throw an exception from the service layer, it's absolutely fine.
Then you could catch it in your 'deleteAnswer' method and return an appropriate status code.
Alternatively (and better), you can handle all the exceptions from all controllers in one place using
#ControllerAdvice class YourExceptionResolver {
#ExceptionHandler
public ResponseEntity<String> defaultErrorHandler(HttpServletRequest req, Exception e) {
//return status code 400, 404, or 500 based on the exception
//with String containing the error message
}
}
If you use #ControllerAdvice and exceptions from the service layer, you can keep your original signature 'void deleteAnswer(int answerId)'.

What's the simplest way to change from exception logging to exception handling in a Spring MVC app?

My Spring MVC app is full of methods that look like this:
#RequestMapping(value = "/foo", method = RequestMethod.GET)
public final void foo(HttpServletRequest request, ModelMap modelMap){
try{
this.fooService.foo();
}
catch (Exception e){
log.warn(e.getMessage(), e);
}
}
Exceptions are caught and logged but not handled otherwise.
The fooService called above does the same thing, never throwing exceptions up to the controller but catching and logging them. So, actually this controller exception code will never get invoked.
What's the best and simplest approach to implement proper exception handling in my app?
Get rid of all catch statements if all they do is logging carelessly. catch is meant to handle the error, not hide it.
Once all these catches are removed, install one global exception resolver in Spring MVC (1, 2, 3, ...) Simply implement this trivial interface:
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
}
In your exception resolver you might simply log the exception once and let it go as unprocessed (return null), so that error mappings in web.xml will forward request to proper error page. Or you can handle exception yourself and render some error page. AFAIK in simplest case there is no need for register exception resolver, just define it as a Spring bean/annotate with #Service.
Remember, catch the exception only when you know what to do with. Logging is only for troubleshooting, it doesn't handle anything.
BTW this:
log.warn(e.getMessage(), e);
is not only a very poor exception handling, but it is also slightly incorrect. If your exception does not have a message, you will see mysterious null just before the stack trace. If it does, the message will appear twice (tested with Logback):
22:51:23.985 WARN [main][Foo] OMG! - this is the exception message
java.lang.IllegalStateException: OMG! - this is the exception message
at Foo.bar(Foo.java:20) ~[test-classes/:na]
...sometimes undesirable, especially when exception message is very long.
UPDATE: When writing your own exception logger consider implementing both org.springframework.web.servlet.HandlerExceptionResolver and org.springframework.core.Ordered. The getOrder() should return something small (like 0) so that your handler takes precedence over built-in handlers.
It just happened to me that org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver running prior to my handler returned HTTP 500 without logging the exception.

Categories

Resources