Ignore MethodArgumentNotValidException or get the sent object - java

is there a way to ignore the validation done through annotation? In the project that I am working at the moment there is the need to work with predefined generated entities that have some annotated validation, such a email, length, etc.
I want to be able to ignore this validation that is performed through the entity. If this is not possible, I am already able to catch the exception in my exception handler through ControllerAdvice, but I am unable to find a way to get the object that was sent through there. Is this even possible?
This is my handler for it:
#ExceptionHandler(value = {MethodArgumentNotValidException.class, ConstraintViolationException.class})
public final ResponseEntity handleValidationExceptions(HttpServletRequest request, HttpServletResponse response,
Object handler) throws IOException {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Not ok");
}
I though about intercepting the request with preHandle as well, but then I come to the same issue of how to get the sent object in there. Through the HandlerMethod I know I can see the args that the method will receive but I can't find the request anywhere.
This would also be a suitable solution since I can just perform what I have to do over there and then "resume" the execution to the main method.

Related

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.

How to inject Grizzly Request into Jersey ContainerRequestFilter

I have Jersey being provided by Grizzly.
I have a ContainerRequestFilter implementation class. However this class is created once for all incoming requests. Therefore doing this:
public class EndpointRequestFilter implements ContainerRequestFilter {
#Context
private org.glassfish.grizzly.http.server.Request requestContext;
public void filter( ContainerRequestContext req ) throws IOException {
// remove for sake of example
}
}
The requestContext is null. I can inject the context into the actual endpoint being called, but that is rather crude and ugly and really no use to me; as i wish to log various requests. Ideally would like to get at this Request object at the ResponseFilter side of the request.
There has to be an easy way of doing this. All the questions/answers I have seen thus far doesn't work for Grizzly or injects at the method being called by the REST endpoint. I don't wish to go around all my hundreds of methods adding this in call just because I want to get the IP address!
So what is the key here? What am I missing?
I'm surprised you even got the app running, to get to the point where you could find out that request is null. Whenever I tried to run it, I would get an exception on start up, saying that there is no request scope, so the request can't be injected, which is what I expected. Though I couldn't reproduce the NPE, I'm thinking this solution will still solve your problem.
So the Request is a request scoped object, as it changes on every request. But the filter is by its nature, a singleton. So what you need to do, is lazily retrieve it. For that, we can use javax.inject.Provider, as a lazy retrieval mechanism.
Going back to the point in my first paragraph, this was the exception I got on start up
java.lang.IllegalStateException: Not inside a request scope.
This makes sense, as the Request need to be associated with a request scope, and on start up, there is none. A request scope is only present during a request.
So what using the Provider does, is allow us to try and grab the Request when there is a request scope present.
public static class Filter implements ContainerRequestFilter {
#Context
private javax.inject.Provider<Request> requestProvider;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
final Request request = requestProvider.get();
System.out.println(request.getRemoteAddr());
}
}
I've tested this and it works as expected.
See Also:
Injecting Request Scoped Objects into Singleton Scoped Object with HK2 and Jersey

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.

Is there a way to access HttpRequest type inside a #Controller method

I have tried to find the answer to this, but I cannot seem to find what I am looking for. So I apologize if this question already exists.
PROBLEM:
I want to be able to access the request type of a request inside of a generic method within my Controller.
DESCRIPTION:
Using Spring ROO and Spring MVC, I have developed a small web service that will respond with certain tidbits from a database when queried. In one of my controller classes, I have some methods that handle some variety of GET, PUT, POST, etc., for the URIs that are mapped within the #RequestMapping parameter.
For example:
#RequestMapping(method = RequestMethod.Get, value = "/foo/bar")
#ResponseBody
public ResponseEntity<String> getFooBar() {
// stuff
}
If a request is made to the web service that it is not currently mapped, a 405 error is returned (which is correct), but I want to return more information along with a 405 response. Maybe respond with something like:
"I know you tried to execute a [some method], but this path only handles [list of proper methods]."
So I wrote a short method that only has the RequestMapping:
#RequestMapping(value = "/foo/bar")
I have found that the method with this mapping will catch all unhandled request types. But I am having trouble accessing the information of the request, specifically the type, from within the method.
QUESTION:
A. How can I access the request type from within the method? OR
B. Is this the right approach? What would be the right approach?
EDIT
ANSWER:
I added a HttpServletRequestobject to the method parameters. I was able to access the method type from that.
I tried using HttpRequest, but it didn't seem to like that much.
Thanks all!
You can add a method parameter of HttpServletRequest, but I think you'd be better off continuing to reply with 405. A client should then make an HTTP OPTIONS call (see How to handle HTTP OPTIONS with Spring MVC?) and you can return the list of allowed methods there.
A. you can access request if you mentioned it as parameter in controller method
public ... getFooBar(HttpRequest request) {
...
}
B. you do not need to add any other description as the 405 status is descriptive.
In answer to "A", just add "HttpRequest req" as an additional argument to your controller methods. Spring will automatically inject a reference to the request, and you can play with headers to your heart's content.
In answer to "B" - "What would be the right approach", how about this?
In order to return that 405, Spring has raised a MethodArgumentNotValidException. You can provide custom handling for this like so:
#ExceptionHandler(MethodArgumentNotValidException.class)
#ResponseStatus(HttpStatus.BAD_REQUEST)
#ResponseBody
public MyMethodArgumentMessage handleMathodArgumentNotValidException(
MethodArgumentNotValidException ex) {
BindingResult result = ex.getBindingResult();
MyMethodArgumentMessage myMessage =
new MyMethodArgumentMessage(result.getFieldErrors());
return myMessage;
}
You should take a look at the #ExceptionHandler annotation. This lets you add methods such as the following to your controller. You can define your own exceptions and appropriate custom handlers for them. I use it to return well-structured XML and JSON from REST services. Although for it to work, you need to throw specific exceptions from your controller methods.
A good walk-through of using this was provided by Petri Kainulkainen in his blog:
http://www.petrikainulainen.net/programming/spring-framework/spring-from-the-trenches-adding-validation-to-a-rest-api/

Resteasy ExceptionMapper returning no result

I am developing a REST-facade for an EJB service, which means it calls the EJB, translates the result to representations a REST-caller will understand and then returns it (as json or xml). All of that works splendid. But the EJB service throws a variety of exceptions, e. g. when no result is found or a few different other cases. Since I don't want those propagating to the REST-caller, I implemented an ExceptionMapper:
public class EjbExceptionMapper implements ExceptionMapper<EJBException> {
private static final Logger logger = LoggerFactory.getLogger(EjbExceptionMapper.class);
#Override
public Response toResponse(final EJBException exception) {
ResponseBuilder result = Response.status(Status.BAD_REQUEST);
logger.debug("Bad request:", exception);
if (exception.getCause() != null) {
final Throwable cause = exception.getCause();
if (cause instanceof NoDeliveryFoundException) {
logger.debug("Found NoDeliveryFoundException:", cause);
result = Response.status(Status.NO_CONTENT).entity(cause.getMessage());
}
}
return result.build();
}
}
All the exceptions from my EJB-service arrive as javax.ejb.EJBException, which this Mapper manages to catch just fine, with different custom Exceptions of the application as causes. The plan is to return different Responses depending on the type of cause of the EJBException. The logger-calls used for debugging are both executed in case I get a NoDeliveryFoundException as the cause, so I know it's executed (the Mapper registered correctly and is used for mapping), but the client never sees a response.
Every call leading to an EJBException in the underlying service (and thus the use of this ExceptionMapper) leads to no Response at all, as if the toResponse()-method were returning null and not a custom built Response.
I even went so far as to log the Response right before returning it, it exists and contains what I expect, so I am positive that it is returned by the toResponse-method. But still, my client receives no Response.
So now I'm stumped and since no search managed to even find someone describing a similar problem, I turn to you, dear SO. ;)
Your toResponse-method contains some conflicting logic.
Response.status(Status.NO_CONTENT).entity(cause.getMessage());
Here you are assigning the the HTTP status code 204 No Content, but you are also adding a response. You can't set the status to 204 No Content and return a response body at the same time.
Also, if Exception#getCause() is null or if it's not an instance of NoDeliveryFoundException, the response body is empty.
Could this be the cause of your problems?

Categories

Resources