I want to write an #ExceptionHandler so JSON requests will get an error response in JSON as well. For non-JSON requests, I want the servlet container to send its default HTML response.
To do this, I'll need to do some content negotiation. Spring MVC handles it for normal requests via annotations, but no such annotation is available for #ExceptionHandlers.
I am wondering how can I programmatically call the content negotiation code?
So apparently, content negotiation happens after the error handler is called, so I have to do most of the heavy lifting myself.
The method to use is ContentNegotiationManager.resolveMediaTypes(), which gives a list of types that one will have to go through and make a decision.
An example of how to do this can be found the source of ContentNegotiatingViewResolver.getMediaTypes()
Related
I am creating an controller where there is certain attributes in json which is an doing in postman a POST request like this if all attributes are posted then its fine
if one then is missing then it would look like this
i want this response when some attribute is missing how to implement this
This is normally implemented in two steps:
Implement a validation mechanism for the method that handles the incoming request. Normally you would throw an exception here if the input is incorrect, in your example a missing JSON key.
Implement a global error handler that will process the exception from point 1 and format the response as JSON.
For point 1 the usual choice is the Java Bean Validation framework because it's integrated with Spring Boot and allows to define validation constraints with annotations like #NotEmpty. You can take a look at this example.
For point 2 the usual choice is #RestControllerAdvice or #ControllerAdvice. You would have to understand your service web server setup to implement it properly e.g. it might behave differently if you use Spring WebFlux.
My application uses spring-webflux, it still uses classic #Controllers with #RequestMapping-annotated handler methods.
Some methods produce application/json, while others produce text/event-stream.
When a request hits a controller, there is no problem: each mapping has produces with the corresponding media type defined.
The application also uses spring-security (the reactive flavor). If an unauthenticated request arrives, we must build a error response using correct format: JSON for application/json endpoints and a Server-Sent-Event for text/event-stream endpoints.
The problem is that security checks are made before the request handler is resolved, so Spring has no clue about the correct response media type at this point.
If a client sends Accept header, this solves the problem: we just parse it and decide what content type to use, with something like the following:
request.getHeaders().getAccept().contains(MediaType.TEXT_EVENT_STREAM)
(the algorithm is oversimplified, but you get the idea).
But some clients do not send Accept header at all. Strictly speaking, we have all the information we need: we have request, and, somewhere in spring-webflux beans information about all the mappings is stored.
So the question is: how (only having ServerWebExchange instance and access to Spring context) do you make use of this mapping information to find out what media types are supported by a handler corresponding to the current request?
P.S. What I tried/thought of so far:
Manually maintain list of all streaming endpoints... yuck!
Use a bean post-processor to collect information about all mappings and then try to emulate spring-webflux behavior... cumbersome and probably fragile.
I want to have the following flow:
Request -> 1) Validate JSON Body -> 2) Validate JSON for Security Concerns -> ...etc
And Throw exceptions / give appropriate JSON Responses in 1) or 2).
I have tried to use Interceptors and Filters.
Filters: I can modify the body by having a Request Wrapper and then passing it along the chain to the JSON Validation, however when I throw exceptions they are not intercepted by the #ControllerAdvice Exception Handler, which works for everything else. From what I have read this is by design...? Also I have tried to set a response manually, example below, but it seems spring boot changes the status code to 405.
response.getWriter().write("{\"test\" : \"test\"");
response.sendError(400);
Interceptors: I get an error because I am reading the body more than once, I can not see how to set the Custom HttpServletRequestWrapper I have made before the interceptors run.
I am after a way of implementing this scenario.
Any help would be greatly appreciated. Thanks!
I realised that because Filters are run first I can modify the request by using a Request Wrapper. Then I use an interceptor to run the security and json checks.
I would still like to know how to modify responses in a Filter though, I do not like how spring boot will change it even though you already have a response code.
What I want to do is process AMQP messages in a very similar way the Http Requests are processed using spring-webmvc annotations such as #RequestMapping, #RequestParam etc. But, instead of the Http Request my source object will be an AMQP message. The AMQP message request will have two headers, for example -
method="POST"
url="/api/myobjects/{someParam}"
and the payload will contain data in json format.
If you have noticed, this is nothing but HTTP REST api mapped to AMQP message.
I want to be able to write a controller like handler, for example -
#Controller
public class MyObjectHandler {
#RequestMapping(value="/api/myobjects/{someParam}", method="POST")
public MyObject createMyObject(#Payload MyObject myObj, #PathParam String someParam) {
//... some processing
return myObj;
}
// ...more handlers
}
I have looked at spring-amqp/rabbitmq annotations and also spring integration annotations. They are close to what I want, but would not allow routing to handler methods based on header parameters, especially the REST url.
I don't expect that a readymade solution would be available for this. Just want to make sure I choose the best possible option. Some of the options I think are (in order of precedence)
If the spring-webmvc annotation processing mechanism is extensible, just extend it to use AMQP message as source instead of Http Request
Modify the spring-webmvc annotation processing mechanism to take the AMQP message as input instead of Http Request
Write your own solution with custom annotaions and their processors, which I think is a very involving task
Or any other possible approach than above?
Any guidance/direction is appreciated.
I think the starting point is likely AbstractMethodMessageHandler in spring-messaging.
There's currently a SimpAnnotationMethodMessageHandler implementation for websockets which invokes #Controllers.
You could use a #RabbisListener method that has a Message<?> parameter (Spring AMQP will convert the underlying Rabbit message to a spring-messaging message, including the headers). Then, invoke the message handler to route to the appropriate controller method.
If you come up with a robust implementation, please consider contributing it.
Sorry friends if this question is very easy but i am confuse i unable to find out solution.
As we all know in spring MVC framework we create controller which will handle multiple request from same page using #requestmapping annotation.
but same thing i want to do in servlet how can i do ?
Suppose i have a jsp which which will contain a jqgrid,and two forms i want to use only one servlet to load the data into jqgrid and that servlet only will handle request from both the form . Since we have only doGet and doPost in servlet how one servlet fulfill all three request. Hope you understand my question if you have and link where i get sample or and tutorial link plz reply me
Well, the only easy way to do this would be to use a request parameter to control how the processing happens.
In a very basic example, you may have something like a requestType value that gets passed as either part of the query string or the request body. You would assign values of 1-3 (or 0-2) with each value indicating a different type of request. Your servlet would then parse the request accordingly.
This actually is how the DispatcherServlet in SpringMVC works. There's only one servlet class instance and when a request comes in, it examines the query string along with other parts of the request to determine which controller should handle the request.