Setting HttpServletRequest as a testing method argument using MvcMock - spring-mvc

I am in process of writing a junit for one of the controller methods with method signature as below:
#RequestMapping(value="/getTokenizedURL.json",method=RequestMethod.POST)
#ResponseBody
public ResponseData getTokenizedURL(#RequestBody final RequestData requestData, final HttpServletRequest request) throws CustomException
I need to call this method using MockMvc and I am able to call using below:
mockMvc.perform(post("/user/getTokenizedURL.json")
.contentType(MediaType.APPLICATION_JSON)
.content(json))
.andDo(print())
.andExpect(status().isOk());
But the problem is I am unable to setup HttpServletRequest Parameter while calling the original method using mock mvc. Without setting HttpServletRequest argument, my test is giving issues since it is something required and used with in original method.
Please let me know how should I setup the same. Thanks!

The idea is that you shouldn't need to.
MockMvcRequestBuilders#post(..) returns a MockHttpServletRequestBuilder which lets you construct the request with any values you want. These will be mirrored in the HttpServletRequest that gets passed to your handler method.
For example, you used
.contentType(MediaType.APPLICATION_JSON)
this will set the content-type header of the request. In your handler method, if you did
request.getHeader("content-type");
you'd get back a corresponding String for the MediaType.APPLICATION_JSON.
The MockHttpServletRequestBuilder has "setters" for every part of the request.

Related

Why cant we get a file data from a RequestBody in java?

I am trying to upload a file to a server so i am trying to use #RequestBody to get the data of the file, but i am getting 415 error code while trying to upload a file.
So i have googled(got solution to upload a file) and got to know that i cant get file data from a request body. So i want to know why cant we access file data from request body as data will be sent in request body in HTTP requests, so i want to know how is the request happening in the case of uploading a file.
My server code before:
#RequestMapping(value = "/upload",headers = "Content-Type=multipart/form-data", method = RequestMethod.POST)
#ResponseBody
public String upload(#RequestBody MultipartFile file)
{
}
Solution:
#RequestMapping(value = "/upload",headers = "Content-Type=multipart/form-data", method = RequestMethod.POST)
#ResponseBody
public String upload(MultipartHttpServletRequest request)
{
}
Technically you could write your own HttpMessageConverter which would parse the full multipart request body, but you'd have to have a very specific target type that could handle all the parts.
You'll notice from the javadoc of #RequestBody
Annotation indicating a method parameter should be bound to the body
of the web request.
that the intention is to bind the entirety of the request body to the method parameter. How do you bind every part of a multipart request to a single parameter? Something like a MultiValueMap<String, Object> (which is what FormHttpMessageConverter uses when writing a multipart request). But that wouldn't be very useful because you'd have to check the type of each value.
It makes much more sense as a developer to specify exactly what you need. That's why #RequestParam and #RequestPart are available.
Because the files are not the request body, they are part of it and there is no built-in HttpMessageConverter that can convert the request to an array of MultiPartFile.
Thats why it works #RequestParam("file") MultipartFile[] files
instead of
#RequestBody MultipartFile file
Hope it helps.

Write ModelandView to a file

A spring controller method returns ModelAndView and I want to write the response to a file, how can this be done ?
ModelAndView mv = new ModelAndView(viewName);
mv.addObject("foo",foo);
return mv;
can the to be rendered content accessed in the same controller method ?
The rendered view is not available at the controller level. If you need to access the rendered version in the controller, you could render the content yourself and return the rendered String from the controller method.
You could also get in further up in the stack and use a ServletFilter and wrap the output stream, e.g. with a TeeOutputStream from Apache commons. At the point you do however not really know which controller method was called. What you could do to signal this is to set a RequestAttribute in the controller method that the filter checks to decide whether to write to the file.

#RequestParam How to handle incorrectly framed URLs

I am having a method test like below and making a RESTful webservice call to fetch the data,
#RequestMapping(value ="/select", method = RequestMethod.GET)
#ResponseBody
public String test(
#RequestParam(value="begin", defaultValue="0",required=false) final String begin
)
{
//Some java code
}
**RESTful Webservice Call:**
http://localhost:8081/a/b/c/select?begin=1
Returning the data properly
http://localhost:8081/a/b/c/select?begin:1
Here in the url = has been replaced with : for negative testing.
Here Spring ignores the given value 1 and picks the default value 0 and returns the data accordingly without errors
Question:
But I want to capture the actual URL field with value which is begin:1, do some validation and display error message that the url is incorrect.
I understood that begin:1 is not considered as part of url by spring and hence picks the default value. Wondering is there a way in Spring to capture the wrongly framed url's.
Any pointers would be helpful. Many Thanks!

HttpServletRequest object in Spring webflow?

How to get HttpServletRequest object in FlowController?
I am trying to retrieve request object from getNativeRequest() method,But it is not giving HttpServletRequest object.
(HttpServletRequest)RequestContextHolder.getRequestContext().getExternalContext().getNativeRequest()
I followed above approach, It's returning SRTServletRequest object.
Correct me if I'm wrong, but SRTServletRequest implements HttpServletRequest, so you should just be able to cast it.

How to configure an endpoint in Spring to accept both form data and XML request body?

I have a small question regarding Spring's MVC data binding capabilities.
I do have the following controller class:
#Controller
#RequestMapping("/foo")
public class FooController() {
// … some init stuff //
#RequestMapping(value = "/{id}/edit.{format}", method = RequestMethod.POST)
public ModelAndView editFoo(#RequestBody FooItem foo, #PathVariable("format") String format) {
// some code here to edit the FooItem //
}
}
I want to be able to post form data as well as XML against this method. For that to work I added two message converters to my applicationContext.xml: The default formHttpMessageConverter and an XStream marshaller.
This works fine, but I have a problem, that if I use #RequestBody and post form data against the URL, the server responds with a 415 Error. If I remove this annotation, form data works well and Spring creates the object for me, but if I post XML against it, I get an empty object.
Is there any way around this or do I need to have 2 methods to be able to handle both of the incoming formats?
Thanks in advance!
I think you need two methods.
FormHttpMessageConverter doesn't have the same databinding capabilities as #ModelAttribute provides, it can't bind request to the specified target class, only to MultiValueMap (see javadoc).

Resources