I am using a FeignClient and a GetMapping to interact with an external system.
My GetMapping is defined as:
#GetMapping(value = "/path/to/endpoint?fields=[\"nm\",\"label\"]")
public String hitEndpoint() {}
Debug shows that the endpoint is being called with:
https://url/path/to/endpoint?fields=[%22nm%22&fields=%22label%22]
Which is failing because the endpoint expects valid json for the fields parameter:
https://url/path/to/endpoint?fields=[%22nm%22,%22label%22]
How do I convince GetMapping to make the request correctly?
Thanks for any help.
Although I think its better to pass JSON as body of a POST method to your controller. But if you insist on doing this I can propose to you 2 solutions:
First Solution
Encode your JSON array into Percent-encoding so you can send it via URL.
For example, your array will be like this:
["nm","label"] -> %5B%22nm%22%2C%22label%22%5D
I used this online tool to encode it.
Second Solution
Encode your array into Base64 and GET it via URL to your controller.
Decode the given Base64 string in the controller and parse it as a JSON array.
There is no need to define your Array parameter in the URL, using spring you can define your API as below and with the power of #RequestParam annotation you can define that you expect to receive an array as a parameter in the URL
#RequestMapping(value = "/path-to-endpoint", method = RequestMethod.GET)
public ResponseEntity<YourResponseDTO> yourMethodName(
#RequestParam("ids") List<Long> arrayParam) {
// Return successful response
return new ResponseEntity<>(service.yourServiceMethod(requestDTO), HttpStatus.OK);
}
Then you can call your GET endpoint using below URL:
/path-to-endpoint?ids=1,2,3,4
Related
I'm new to Spring...I have a Spring Boot API application and all of my methods (POST, GET, etc) work great with Postman when the Content-Type is set to application/json, I can send and receive JSON.
However, I'd really like for my methods to also accept a GET or POST in the browser. When I use the browser to do a GET, the API returns an INTERNAL_SERVER_ERROR. I created a small form and try to POST to my API, but then I get the UNSUPPORTED_MEDIA_TYPE: Content type 'multipart/form-data;boundary=--------------------------802438220043016845671644;charset=UTF-8' not supported
These are 2 of the methods in my #RestController:
#RequestMapping(method = RequestMethod.POST, value = {"","/"})
public ResponseEntity<MyModel> createModel(#Valid #RequestBody MyModelDto modelDto) {
MyModel model = modelService.createModel(modelDto);
URI createdModelUrl = ServletUriComponentsBuilder.fromCurrentRequest().path("/{identifier}")
.buildAndExpand(model.getIdentifier()).normalize().toUri();
return ResponseEntity.created(createdModelUrl).build();
#RequestMapping(method = RequestMethod.GET, value = "/{identifier}")
public Resource<MyModel> getByIdentifier(#PathVariable("identifier") String identifier) {
MyModel model = modelService.getByIdentifier(identifier);
Resource<MyModel> resource = new Resource<>(model);
return resource;
}
If there's any other code that would be helpful to show, let me know and I'll update the thread.
In createModel method, instead of #RequestBody, please use #ModelAttribute for MyModelDto parameter.
You can use can try following ways,
Set consume block in "#RequestMapping".
like , #RequestMapping(value="/abc", consume = "multipart/form-data", method=HTTPMethod.POST")
Use #Multipart annotation and file object as #Part annotation
Instead of use #RequestBody use #RequestPart.
I have a Spring REST application that accepts JSON messages, written like
#RequestMapping(value = "/myhook", method = RequestMethod.POST,
produces = JSON, consumes = JSON)
public #ResponseBody MyResponse doIt
(#Valid #RequestBody(required = true) MyContractRequest request) {
MyResponse response;
...
return response;
}
This works really well with almost no code to support, but now I have a requirement to sign both response and request.
I started from simply computing the shared signature of all message fields at Java level and assigning it to the dedicated signature field. However this requires to have and maintain code for computing the signatures:
public void update(java.security.Signature sign) throws Exception {
sign.update(name);
sign.update(value);
sign.update(etc);
}
Some people around me expressed opinion that the need to write and maintain this signing code may not be the best design, and it may be better to sign the whole message as a single JSON string. I could fetch the request as a string manually, and then process JSON manually, but I really would like to preserve the Spring controller concepts.
Also, I cannot longer have the signature field in the message itself because the value of this field obviously also changes the signature of the JSON string.
Is there any way to compute the signature of the whole JSON message body on the message departure and arrival, and where to place the signature so it could be passed together with the message? One of the idea is to use the custom HTTP header for the signature. Anyway, how to compute it first?
You can use a servlet filter with Spring MVC and modified your content whatever you want in request and response as well
Example :
http://www.mkyong.com/spring-mvc/how-to-register-a-servlet-filter-in-spring-mvc/
or you can use Spring 3 MVC Interceptor
http://viralpatel.net/blogs/spring-mvc-interceptor-example/
How to make the RequestMapping to handle GET parameters in the url? For example i have this url
localhost:8080/MyApplication/spm/gcNkyLXkwv
how to get the spm value from the above url
This can be done using PathVariable. I will just give example how it can be done. You can incorporate in your example
Suppose you want to write a url to fetch some order, you can say
www.mydomain.com/order/123
where 123 is orderId.
So now the url you will use in spring mvc controller would look like
/order/{orderId}
Now order id can be declared a path variable
#RequestMapping(value = " /order/{orderId}", method=RequestMethod.GET)
public String getOrder(#PathVariable String orderId){
//fetch order
}
if you use url www.mydomain.com/order/123, then orderId variable will be populated by value 123 by spring
Also note that PathVariable differ from requestParam as pathVariable are part of URL. The same url using request param would look like www.mydomain.com/order?orderId=123
I'm trying to build an API that takes a POST with one parameter in the body that should be x-www-form-urlencoded. I've currently mapped it as:
#RequestMapping(method = POST, consumes = APPLICATION_FORM_URLENCODED_VALUE, produces = APPLICATION_JSON_VALUE)
public ResponseEntity<LinkEntity> createShortLink(#RequestBody String url) {
LinkEntity savedLink = linkService.create(url);
}
When I do a POST with Postman (REST Chrome extension) with one form parameter url=http://www.drissamri.be it comes into this method as url=http%3A%2F%2Fwww.drissamri.be as expected.
When I try to change the #Requestbody into #RequestParam(value = "url") I still get the URL with the url= prefix (as expected) but it is not urlencoded anymore. Why doesn't the encoding take place any more? Is this a bug or is there another way to take in the parameter as urlencoded value
As correctly mentioned by Pavel Horal the parameter is retrieved by ServletRequest#getParameter and is already decoded. If you need to access the origin parameter you can access the parameter by other means.
One way would be to inject a HttpServletRequest and use HttpServletRequest#getQueryString() which does not decode the values.
I'm trying to receive a JSON String with subdomain to a Java Map at Spring MVC Controller.
Let's say I have this JSON at the JavaScript part:
var contract = {dateFrom:someDate,
dateTo:someDate,
season: {seasonCode:someString}}
The JSON is sent as GET Ajax call.
The Controller looks like this:
#RequestMapping(value = "/", method = RequestMethod.GET, headers = "Accept=application/json")
public ResponseEntity<String> getVertagFromSearch(#RequestParam Map<String, Object> allRequestParams, ModelMap model){
The output of the Map looks like this:
{dateFrom=02-07-2014, dateTo=02-07-2014, season[seasonCode]=SO03}
The GET Request looks like this:
http://localhost:8080/contracts/?dateFrom=02-07-2014&dateTo=02-07-2014&season%5BseasonCode%5D=SO03
I want to parse this Map into my contract domain object. But with this structure it doesnt work. Without a subdomain(season) it worked.
Thanks in advance!
Update 1
Sending as an object it looks like this: (output Browser)
Object { dateFrom: "09-07-2014", dateTo: "08-07-2014", season: Object }
Sending after JSON.stringify it looks like this:
"{"fromDate":"09-07-2014","dateTo":"08-07-2014","season":{"saiCode":"SO03"}}"
In this case I think the probem are the double quotes at the beginning and at the end.
I think the best two options are:
1) Modify your JS object to have only simple objects. If you look at your request URL before your update, you had:
{your IP:port}/contracts/?dateFrom=02-07-2014&dateTo=02-07-2014&season%5BseasonCode%5D=SO03
That is not JSON at all, is a simple request with three parameters:
dateFrom = 02-07-2014
dateTo = 02-07-2014
season%5BseasonCode%5D= SO03 // %5B and %5D are '[' and ']' escaped
So your javascript is transforming a JS object (not JSON) in plain parameters.
2) Send a parameter, a string, with your JSON structure and then use some JSON library to parse it:
http://localhost:8080/contracts/?myJson=<JSON_String>
and then modify your controller as:
#RequestMapping(value="/", method=RequestMethod.GET, headers="Accept=text/plain")
public ResponseEntity<String> getVertagFromSearch(#RequestParam String myJson, ModelMap model){
JSONObject myJSON= new JSONObject (myJson);
...
}
Usually sending a JSON is easier with a POST (just adding it to the body), but as your request seems to ask for data, a POST request is not a good idea. Most of the rest APIs use the first approach, JSON tends to be part of a response more than part of a GET request.