Is there a way to intercept Undertow RequestTooBigException in spring-ws - spring

I have spring boot application that provides some rest api and soap interface using spring-ws.
I'm restricting all post requests to less than 50MB using
server.undertow.max-http-post-size=50MB.
The restriction works but not the error handling.
Tried using a SoapFaultMappingExceptionResolver and mapping RequestTooBigException as an exception inside that. That didn't work because I think this is blocked by undertow and that's before the soapExceptionResolver is triggered.
Tried using a #ExceptionHandler but same result.
Since it's a soap request the accepted type is not json and the default spring exception handler tries to return json with the details of the exception, thus resulting in the following in the logs:
2019-09-17 09:24:11.715 WARN 12564 --- [XNIO-1 task-23] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation]
2019-09-17 09:24:11.950 ERROR 12564 --- [XNIO-1 task-75] io.undertow.servlet.request : UT015012: Failed to generate error page /error for original exception: io.undertow.server.RequestTooBigException: UT000020: Connection terminated as request was larger than 52428800. Generating error page resulted in a 406.
Is there a way to either intercept that exception for the WS services, or to make the spring default error handler to return the exception as XML (just for the ws)?

Tried using a #ExceptionHandler but same result.
I suppose that Spring considers that exception as a implementation detail of Undertow during the request processing that it performs and as a consequence it doesn't want to allow it leak above.
In Spring, you have exception handing and exception resolving.
Exception handlers are not always well designed to define a custom exceptions handling whether Spring implementation resolves them for you and apply a specific processing for. There you look like in this case.
But all is not lost. A clean and possible approach (not tested) is to implement your own exception resolver to prevent Spring to map that Undertow exception into a HttpMediaTypeNotAcceptableException.
Since you use spring-ws, you should implement org.springframework.ws.server.EndpointExceptionResolver or more simply AbstractEndpointExceptionResolver or SimpleSoapExceptionResolver.
Implement resolveExceptionInternal() to perform the logic in case of that exception is thrown :
public class MyEndpointExceptionResolver extends AbstractEndpointExceptionResolver {
public MyEndpointExceptionResolver(){
setOrder(0);
}
#Override
protected abstract boolean resolveExceptionInternal(MessageContext messageContext, Object endpoint, Exception ex){
if (ex instanceof RequestTooBigException){
// create the response message with the exception
WebServiceMessage message = ...
// set it in the MessageContext
messageContext.setResponse(message);
return true; // resolved
}
return false; // leave the default resolver doing its job
}
}
Note that you may have multiple active exception revolvers for a same layer/concern. So you have to set the precedence of this one over the default one.
setOrder(0) does that.

Related

Spring Microservices with Hystrix - fallback only Return/Throw Exception

I have been trying to implement hystrix fallback to only throw Exception rather than raking a response.
I have been searching up and down for ways to have the fallback method to only throw Exceptions. The whole point of implementing Hystrix here is main to preserve resources and close unnecessary call to another MS that is already down and I need to standardize the response (throw Exception) regardless of what is the originally intended response.
Here is the rough implementation that i'm trying
#HystrixCommand(fallBackMethod="fallback")
public String actualMethod(String input){
code to call another MS
}
private String fallback(String input){
throw RuntimeException("Some specific error message");
}
However, i kept getting fallback failed.
A pointer somewhere would be great. Thanks people
There is a typo in your code #HystrixCommand(fallBackMethod="fallback") should be #HystrixCommand(fallbackMethod="fallback")

Should I provide layer-specific exceptions in a SpringBoot backed REST Api?

I have a SpringBoot based REST Api structured as follows :
Rest Controller -> Service -> Repository
and I'm wondering how exactly to handle exceptions "properly".
For instance, let's say someone calls a /myresources/{id} endpoint with a non-existant {id}. The call gets delegated to the service which in turns tries to get the MyResource from the Repository. It fails and returns null. The Service then throws a MyResourceNotFoundException.
Now I want a specific format for my REST errors so I have a #ControllerAdvice ResponseEntityExceptionHandler which handles the custom serialization of these exceptions (#ExceptionHandler(MyResourceNotFoundException.class)).
Fine.
But this is going to result in a lot of handling/translation for each different custom exception. So I thought I could generify this by adding HttpStatus codes and messages to a base abstract exception class which MyResourceNotFound and others would extend and override. Thus the ResponseEntityExceptionHandler would simply handle building my custom error DTO in a standard way.
But then I realised that I'm adding REST concepts to an exception thrown at the service level. These shouldn't be aware of such notions...
Maybe I should catch the MyResourceNotFoundException in the Controller and throw another layer-specific exception which contains the appropriate messages and HttpStatus etc. in order to handle this generically in the ResponseEntityExceptionHandler...
What are your thoughts on this ?
You can generalize the exception as XYZMicroserviceException.
class XYZGenericException extends Exception{
String message;
custom error details....
XYZgenericException(errorMessage, custom error Details..){
this.message=errorMessage;
.......
}
}
and you can surround the suspected call which would lead to exception with try block and raise the generic exception in catch block that can be handled in global exception handler.
try{
xyz.abcMethod() // may give some exception
}
catch(Exception e){
throw new XYZGenericException(.........)
}
In the exception handler class with #restcontrolleradvice you can annotate the methods with the type of specific exception class to be handled.

Good idea using ControllerAdvice to perform REST authentication of a request?

In my current Spring Boot application i seem to hit a wall when trying to implement a REST request filter. My goal with the request filter was to read the header and body part and validate the incoming data and check if it meets the HMAC construction we are using.
So the request filter seemed not to work an alternative solutions is to use #ControllerAdvice.
Then the request validation can be implemented very easy. But i am not sure if it normally seen as an incorrect usage of the #ControllerAdvice annotation.
#ControllerAdvice
public class GenericWebControllerAdvice {
#ModelAttribute
public void authenticationFilter(#RequestHeader(value = "Authorization") String authHeader, #RequestBody String payload) {
// process authentication based on header info and body content
// calculate the hash and check if meets the security settings
// if the hash fails throw an exception that returns a http status code
}
}
Any comments on the solution or alternatives that are better?
No you should do the validation in the controller (ie method with #RequestMapping).
Spring supports JSR 303/349 bean validation. Thus if your request body is a POJO and you have the correct annotation Spring will automatically do the validation for you. There is a tutorial of that here:
http://www.leveluplunch.com/java/tutorials/017-validate-spring-rest-webservice-request/
As for request parameter validation (ie not bean validation) I have had to make my own transfer objects and exception handling. How you do global exception handling is covered in the Spring Reference guide but generally you extend and/or register a org.springframework.web.servlet.handler.SimpleMappingExceptionResolver. Ironically #ControllerAdvice can be used for exception handling but I find it better to extend and register an Exception Resolver. More info can be found here:
https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers
Edit based on OP comments and edits:
If your doing authentication or some other request based validation/authorization its probably best to use an Interceptor. Reference doc. #ControllerAdvice will probably not work as the request handling is too far a long. That is you want something before databinding happens.

Exception handling in spring

I am developing web application with spring + hibernate. As per my knowledge, it is best practice to put #transactional in service layer. Spring throws DataAccessException in case of any exception while updating data into database.
Below is my high level class structure.
#Transactional
class OrderService {
public void createOrder() {
try {
orderDAO.createOrder();
} catch (DataAccessException e) {
// convert into business exception and sends back to presentation logic.
}
}
}
What happens here is data access exception is thrown only after completion of method. so if any exception occurs, I am not able to convert it into business exception in catch block.
Work around is to flush the hibernate session in dao method but I do not like this approach. Is there any better approach to this?
I presume you are using Spring MVC, although you do not specify. If you are using Spring MVC, then there are a few different options.
You can create a Filter that looks for the DAE exception and recodes it to be a different status or exception that your front end would better understand. You can look at Spring Security's ExceptionTranslationFilter as an example of how this is already done for different exceptions
You can use a SimpleMappingExceptionResolver to map a specific exception to a particular view. This would allow your presentation layer to be agnostic and not need to know anything about the exception thrown.
You can use an #ExceptionHandler within a specific controller to handle the DAE exception in a general manner and appropriately prepare something for the presentation layer.
As an extension to #3, you can use a #ControllerAdvice to manage all DAE exceptions for any controllers in the webapp.
You can read about Exception Handling in Spring MVC for more details as well.
Generally speaking, I find that the best solution is to catch transaction exceptions at a much higher level and manipulate the information to present it to the front end in a way that is back-end agnostic. This allows you to set up your own error codes/etc. The only time I try/catch exceptions in my service itself is if I actually want to attempt a retry or modify the logic flow based on some specific exception and don't want the front end to know about it.

Purpose of throwing exception by Spring controller function

I have come across few Spring contoller's function, which are throwing IOException.
#RequestMapping(method = ***)
#ResponseBody
public List<Offering> getOfferingDetailsList(HttpServletResponse response, #PathVariable("productIds") String productIdString, HttpServletRequest request) throws IOException
I doubt about use of such exception throwing, when no one above is catching and handling it. Is it fine to set response status like "response.setStatus(HttpStatus.SC_NOT_FOUND)" in place of throwing such exception ? What is the standard way of handling exception in controller ?
it is always good to have common exception handling functionality , so that we can make our controller code free from exception handling , by externalize to common exception handling functionality, i have come across this interesting topic for this purpose
http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
and also use a global exception handler that will do that for all the exceptions of all the controller methods. That will centralize the exception handling, prevent massive code duplication, and avoid cluttering your controller methods.
Look at the #ControllerAdvice and #ExceptionHandler annotations.
A fairly standard way of handling exceptions in Spring Controllers is to use #ExceptionHandler.
Check out this post for more details

Resources