I am writing Integration Tests for controllers using RestTemplate, so far I have been able to call most , however haven't been able to tackle this particular parameter combination.
I know how to deal with headers, GET or PUT parameters, but multiple String is sole one that have yet to figure. Dunno if #Annotations make difference.
#RequestMapping(value="/getBook", method = GET)
#ResponseStatus(OK)
public #ResponseBody
GetBookResponse getBook(#RequestParam("isbnID") String isbnID, #RequestParam(required=false) Double price, #RequestHeader(required=false) String publisher)
{
.....
}
and how this would work in the case for POST
Normally I use ResponseEntity to get response but been stuck pn how to prep it.
Typically we create a new HttpRequest and add the request parameters to it and submit your HttpRequest with all its corresponding parameters in your post. I don't know how to implement it with the framework you are using though. I've written tests for controllers and this is how I did it. GET request usually has just one parameter in the url so you don't really have to add request parameters but POST should have request parameters set to the httpRequest.
Related
I'v been asked to implement a request for a REST Web Service, with dynamic parameters. I'll explain with an example:
now our request object's fields are three strings, which are taken from the controller and used to realize the business logic. Tomorrow, we may have the need to introduce another parameter, so I'v been suggested to implement the request object with a Map, so that we can manage more than 3 properties in the request, without opening the code and having to re-deploy the service.
Now, my question is, is this possible? I think it is, but anyways the controller will not know what to do with the newly inserted properties, or maybe it will never use it! So, IMHO, this is a useless rework, because we will need to open the code and redeploy the .war anyhow.
Thanks in advance for your help.
P.S. The web service is a wrapper for GraphDB calls, if it helps
If you are using GET method, you can get parameter names to values as shown in below snippet:
#GET
public String get(#Context UriInfo ui) {
MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
MultivaluedMap<String, String> pathParams = ui.getPathParameters();
}
For Form parameters it is possible to do the following:
#POST
#Consumes("application/x-www-form-urlencoded")
public void post(MultivaluedMap<String, String> formParams) {
// Store the message
}
By using MultivaluedMap, you can pass any parameters to the Rest service and you can process your business logic.
Reference: Extracting request params
In a controller class,
I have one method
#RequestMapping(value="test", method={RequestMethod.POST,RequestMethod.PUT})
#ResponseBody
public String testApp(#RequestParam String priceA, #RequestBody String valueOfProduct) throws Exception {
}
My client is sending prices to my App as POST requests for processing.
Now client (which is not under my control) is planning to send the price value as a request parameter and another client is planning to send price in requestheader.
The trick is:
If it is present in requestheader it wont be present in requestparameter.
So I have to design it such that my server code works fine in both cases.
Kindly let me know which design would be the best.
Will it be
#RequestMapping(value="test", method={RequestMethod.POST,RequestMethod.PUT})
#ResponseBody
public String testApp(#RequestParam String priceA, #RequestHeader("PRICE") String priceAFromAnother, #RequestBody String valueOfProduct) throws Exception {
}
But above logic wont work as #RequestParam wont be available all the time.
Have you tried searching by your own first?
Take a look that this answer.
If you know the header to search for, you could add a request filter (HttpServletRequestWrapper) that pre-process the request. Here is simple example Modify request parameter with servlet filter
NOTE: I would caution you that this methodology is not maintainable if your parameter set/api is going to grow over time.
If I have a #Controller method whose parameter is a #RequestBody param, I usually have to write some jQuery script or something similar to perform an AJAX request with JSON object in order to call that method. If I tried calling that method via a web browser directly, it returns with a Error 415 Unsupported Media Type.
Is there any alternative to just quickly call such method using browser without having to write some jQuery code? Like perhaps a way to write the JSON object in the URL/address bar?
code:
#RequestMapping("testCall")
#ResponseBody
public List<TestObject> getTestCall (#RequestBody TestParams testParams) {
return stuff;
}
public class TestParams {
private Integer testNumber;
//getter/setter for testNumber
}
I thought maybe I could just do:
http://localhost/testCall?testNumber=1
maybe Spring would auto populate a new TestParams instance with that property set to 1 but that didnt work...
maybe I need to do something extra for that?
The whole point of a #RequestBody annotated parameters is for the Spring MVC stack to use the HTTP request body to produce an argument that will be bound to the parameter. As such, you need to provide a request body. Sending a request body is very atypical for a GET request. As such, browsers don't typically support it, at least not when simply entering an address in the address bar and submitting the request.
You'll need to use a different HTTP client, like jQuery. I typically have a small Java project in Eclipse that's setup with an Apache HTTP components client which can send HTTP requests to whatever server. It takes a few seconds/minutes to setup the correct request body and run.
I have spent the last year building a REST API, and by far the best way to exercise that API manually is using the Chrome Extension, Postman. I cannot recommend this tool enough.
https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en
To test your simple example you'll need to invoke a POST (I assume that as you have a request body, but your controller method doesn't define a HTTP Verb) using POSTMAN to your Url (like the following example):
POST /contextRoot/testCall
{
"testNumber": 1
}
If you want to test your API automatically (which I recommend), you can use the excellent Spring Mvc Test project. This allows your to call your API via a rest-like DSL and assert that the response is in the shape you want. More details can be found here:
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/testing.html#spring-mvc-test-framework
you can add request params to the getTestCall method:
#RequestParam(value = "testNumber", required = false, defaultValue = "") String testNumber
There is a chrome app called Advanced REST client. You can pass the data in form of json to your controller using this chrome app. For eg. json data is
id:1,
name:"xyz"
whereas the controller can have #RequestBody Person form.
The Person class would be a POJO having id and name as instance variables. The Spring would automatically map the json data to the form.
I think this is the easiest and simplest way of checking your spring controller.
Check the extension Advanced REST client here
From what I know You can send JSON object to the webbrowser and it will be displayed without further need of AJAX.
useful tutorial:
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/
I have a scenario to pass values from one request to another subsequent rquest. (i.e) I will call 'Controller1' on the first request and take the request parameters or query string and should send them to 'Controller2' as 'new request'.
Strictly I should not use any of the following approaches.
should not use sessions.
should not use cookies.
should not use requestdispatcher.forward(--).
without FlashAttributes (which internally uses session, which won't work in 'Clustered environmnets').
should not expose the ModelAttribues in request parameters in case of redirection (i.e) I should not even expose them as request parameters using spring RedirectView.
please let me know, if we have any alternative approch.
Thanks in advance.
You could call the underlying method directly
So if you have as controller2 :
#RequestMapping(value = "/MyURL", method = RequestMethod.POST)
public String myMethod(final BaseDTO baseDTO, Model model) {}
Inject controller2 into controller1 and call "normally":
controller2.myMethod(baseDTO, model);
I'm trying to send parameters with PUT from JavaScript to a Spring application. Here is the #RequestMapping in a Spring Controller:
#RequestMapping(value = "toggle-paid-action", method = RequestMethod.PUT)
#ResponseBody
public final String togglePaid(#RequestParam final int year,
#RequestParam final String docType, #RequestParam final int number) {
And here the JavaScript snippet that is supposed to send those parameters.
Ext.Ajax.request({
params: {year: year, docType: docType, number: number},
url: 'toggle-paid-action',
method: 'PUT',
However, I get a "400 Bad Request" every time with description "The request sent by the client was syntactically incorrect ()".
If I check with Firebug, there is a PUT tab with all my parameters, and the parameters are correctly spelled since if I switch from PUT to POST on both sides everything works.
I was wondering what could be the problem, is PUT limited to #PathVariable parameters, or it can send also POST-like parameters?
I suppose you can't pass parameters to spring using request method PUT as there is a restriction in the servlet API. You can only work with PUT methods implementing a restful service, passing data as the request body, in other cases (like Spring MVC Databinding) PUT won't work.
see SpringMVC is not recognizing request body parameters if using PUT
JIRA:
https://jira.springsource.org/browse/SPR-7414
This, as suggest above, seems to be a bug in spring/servlet API. In reality PUT requests are supposed to work on Request Body (or payload) and not on Request Parameters. In that sense, servlet API & spring's handling is correct.
Having said that, a better and much easier workaround is to pass no data element from your javascript/jQuery call and pass your parameters as part of the url itself. meaning, set parameters in the url field the way you would do in a GET call.
$.ajax({
url: "yoururl" + "?param1=param2Val&..",
type: "PUT",
data: "",
success: function(response) {
// ....
}
});
now this works for simple parameters, i guess, will not work for complex JSON types. Hope this helps.