How do i use spring mvc void controller method? - java

I am reading spring framework reference. When i read here. I found that spring mvc supports returning void types.And then i read some examples of using void.But these examples do not make me to understand when time to use void.Is there a better example of how to use it?

From the referenced document:
"... if the method handles the response itself (by writing the response content directly, declaring an argument of type ServletResponse / HttpServletResponse for that purpose) or if the view name is supposed to be implicitly determined through a RequestToViewNameTranslator (not declaring a response argument in the handler method signature)"
There are two conditions listed.
If the method writes to the servletResponse directly. In this case, there is nothing for spring to do; a return value of void tells spring "I got this" and it does nothing with the response.
If the view name can be determined vai a RequestToViewNameTranslator. In this situation, spring knows the view to return based on the request, so no return value is required.

Related

Passing HttpServletResponse in Spring Boot controller method

Came across spring boot code snippet which has HttpServletResponse passed has an argument in the controller method
public void someApiMethod(#RequestBody MyRequest req, HttpServletResponse response) {
//some code
response.setStatus(HttpStatus.NO_CONTENT.value());
}
The same could have been achieved using ResponseEntity and I feel there is no need of passing HttpServletResponse here.Kindly advise on which is the best approach and why, considering this code is written for rest API ?
Better solution is to use #ResponseStatus for there is no real reason to add non-API arguments, such as HttpServletResponse or ResponseEntity in controller methods. Only path variables, request params, request body & headers should be the set of controller parameters for majority of cases. Plus it is more readable, maintainable, and still is usable by Swagger etc.
#ResponseStatus(code = HttpStatus.NO_CONTENT)
public void someApiMethod(#RequestBody MyRequest req) {
//some code
}
Spring boot (and in particular Spring MVC which is a part of spring boot in this case) provides an abstraction over low-level HttpResponse which is a part of the servlet specification.
In a nutshell, this abstraction saves you from thinking in terms of Http Protocol and allows concentrating on a business logic which is a good thing.
So if you can avoid HttpServletResponse - do it by all means (and this is what you'll usually do in your applications).
You can create objects (and spring will convert them for you if its REST), you can return ResponseEntity which is "status" + "body" - spring will do all the conversions.
So consider these techniques first.
Now, sometimes you have to manipulate the response at the low level, well in this case you have to work with HttpServletResponse object.
Example of this if you want to return a binary data that cannot be easily converted. For instance, if you want to prepare a zip file and send it back as a result of HTTP request, you'll have to get a more fine-grain low-level control, in this case, it's better to start off with HttpServletResponse param passed into controller method.
It depends on your particular use case.
If you can implement your use case without directly accessing the HttpServletResponse object, do so by any means. It is the cleaner approach.
You might have a scenario in which you need to access the HttpServletResponse. Such an example would be when you need to stream content back to the client, so you need direct access to the response output stream. In recent versions of Spring this can also be achieved via StreamingResponseBody, which avoids the need to directly access the response outout stream.
I believe it is a better approach to return a ResponseEntity and use that as per your suspicious.
ResponseEntity is easier to handle and a more "elegant" solution, more consistent with Spring design.

Get method name in Java Filter

Got a Java Filter which is responsible to intercept some endpoints.
In doFilter method, as follows:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
How do I get the accessed method name?
For instance:
Given 2 Servlets followed by operation name:
LifeCycle
create
delete
SearchService
findByName
findById
When LifeCycle.create operation is called by a front end perspective, the filter intercepts it, however I couldn't know if the operation called was create or delete?
Are there some way to get the "create" operation name in Java Filter?
Thanks in advance.
Filters are invoked by the web container when a request is made to the server (servlet or jsp). They are not called by Servlets or jsps.
You can see Filter's life-cycle in the image below:
For more see DOCUMENTATION
If you want to know which action is called from the front-end, then you can use a request parameter and then capture it from ServletRequest
I could get the operation name using:
((HttpServletRequest) request).getHeader("SOAPAction");
If you are searching for method names then you can try this piece of code:
StackTraceElement[] st = Thread.currentThread().getStackTrace();
String methodName = st[2].getMethodName();
You can further modify the index of st to get the chained caller methods. It is just a simple array of stack trace objects containing class and method names. Good Luck!

Why do I need to add #ResponseBody to my controller action?

According to Spring documentation, this annotation indicates that a method return value should be bound to the web response body. I understand that, and I've been using this for my ajax calls. However, I recently came across code that doesn't use the annotation.
So I guess my question really is why it works without the annotation?
Without the annotation, a different process takes place. Depending on the return type (you can find the defaults in this document) the response will be generated differently.
For example, if your return type is String, then, by default, the return value will be resolved as a View name, a ViewResolver will try to resolve and create a View object, and a RequestDispatcher will forward/include/redirect to it (ex. a jsp) so that the Servlet container can handle generating the response.
The actual interface that handles the return type is HandlerMethodReturnValueHandler and there are many implementations for each type. See here for more information.

How to define RequestMapping prioritization

I have a situation where I need the following RequestMapping:
#RequestMapping(value={"/{section}"})
...method implementation here...
#RequestMapping(value={"/support"})
...method implementation here...
There is an obvious conflict. My hope was that Spring would resolve this automatically and map /support to the second method, and everything else to the first, but it instead maps /support to the first method.
How can I tell Spring to allow an explicit RequestMapping to override a RequestMapping with a PathVariable in the same place?
Edit 2: It seems that it would work if the /support mapping came before the /{section} mapping. Unfortunately we have dozens of controllers containing numerous methods with RequestMapping. How can I make sure that the controller with the /{section} mapping is initialized last? Or would a pre-interceptor be the way to go?
Edit 1: This is simplified, I know that having those two RequestMapping alone wouldn't make much sense)
Using Spring you can extend the org.springframework.web.HttpRequestHandler to support your scenario.
Implement the method:
#Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
Use it to analyze the incoming request, determine if the request url is part of your special subset of request url's and forward to the appropriate location.
Ex:
#Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/** You will want to check your array of values and have this data cached **/
if (urlPath.contains("/sectionName")) {
RequestDispatcher requestDispatcher = request.getRequestDispatcher("sections" + "/" + urlPath);
requestDispatcher.forward(request, response);
}
}
And setup your sections such as:
#RequestMapping(value={"/sections/{sectionName}"})
This will not interfere with any of your pre-existing controller mappings.
If 2 these methods are defined in 2 different controllers your problem is that you have 2 controllers mapped to same URL. You do not control the order of controllers initialization right now, so the order is random.
I think you need /support mapping to be initialized before /{section}.
To achieve this try to define that controller "section" depends on controller "support". If this will not help try to put both methods together to one controller and put method mapped to "support" before "section"
I this does not work here is other suggestion. What "section" is? If it can accept limited number of values it should be defined as enum. I believe that in this case everything will work as required if support and section methods are in one controller or in separate controllers.
Good luck.
This not seems to be a problem, this is a valid mapping. If you have a look to http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-uri-templates
In the section 16.3.2 Mapping Requests With #RequestMapping exists two methods doing exactly the same that you are trying.
To be sure that your classes are being compiled try to add a #RequestMapping("/someprefix") at class level to see if the URL is being exposed as you want.
I verify your example locally using the version 3.1.0.RELEASE and no issue were present.
As a workaround (and also to provide a well-understand REST URI add some context to your second mapping:
#RequestMapping(value={"client/support"}) // i.e: if you are working with clients
public ModelAndView getsupport(#PathVariable Long supportId){
// do your code here something here
}
Of course that this is valid if this is the unique controller present in the system, otherwise you must use RequestMapping at class level as I suggested above.
I hope this helps.
I am not seeing this behavior with Spring 3.1.2, it could potentially have been a bug with an older Spring version. Here is a gist which runs through without any issues for me - https://gist.github.com/3802254

how to over ride request object in ServletRequestWrapper?

I want to over ride the default getParameter() method of ServletRequestWrapper with getParameter() method of SecurityRequestWrapper.
For example, if I am using a simple jsp form to take the name of a person,
String name = request.getParameter("firstName");
I want the above getParameter() method to be from the SecurityRequestWrapper class. I am not able to understand how the request object is over riden since the getParameter method is mostly called on it by default in any jsp form.
I understand that the SecurityRequestWrapper you're talking about already implements HttpServletRequestWrapper? If so, then just create a Filter which is mapped on an url-pattern of *.jsp (or whatever you'd like to invoke this Filter for) and does basically the following in the doFilter() method.
chain.doFilter(new SecurityRequestWrapper((HttpServletRequest) request, response));
I might be wrong, but I do not think this is possible. Because request and response objects are created by the container and passed onto the servlet's process method. The very reason these objects are created by the container, because they want to flush the output and would like to control that. I will be interested to know however if it is possible to pass our own request / response objects.

Categories

Resources