Spring rest docs for Rest service with JSONObject as #RequestParam - spring-boot

I am trying to do write Spring rest docs for the rest service which accepts JSONObject as #RequestParam.
ex:
URL - http://localhost:9090/report?request={cdomain:automation,date:20190920}
Also I need to publish description for cdomain and date for understanding.
I am able to generate the rest docs for #PathVariable with below code:
URL - http://localhost:9090/report/11
this.mockMvc.perform(RestDocumentationRequestBuilders.get("/report/{id}",1))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json;charset=UTF-8"))
.andDo(document("fin-report/balance-sheet",
pathParameters(parameterWithName("id")
.description("Identifier of the person to be obtained.")),
responseFields()...
Please let me know how to do documentation for JSONObject as #RequestParam, like below code and URL:
Code - #RequestMapping(method = RequestMethod.GET, produces = "application/json", path = "report)
public String getReport(#RequestParam(value="request") JSONObject jobjparam) {...}
URL - http://localhost:9090/report?request={cdomain:automation,date:20190920}

Related

x-www-form-urlencoded Array inconsistently populated in Spring REST call

I am attempting to send a PUT request to a Rest API using x-www-form-urlencoded content. My aim is to send a list of strings in the request similar to this article. I have the following REST controller defined in a Spring Boot application to allow for this:
#RestController
#RequestMapping(value = "/rest/api", produces = MediaType.APPLICATION_JSON_VALUE)
public class RestApiController {
#PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE)
private ReturnType putRestApiTypeJson(
#PathVariable("id") String id,
#ModelAttribute PutDataRequest request) {
System.out.println();
return null;
}
#PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
private ReturnType putRestApiTypeUrlEncoded(
#PathVariable("id") String id,
#ModelAttribute PutDataRequest request) {
System.out.println();
return null;
}
}
which leverages PutDataRequest defined by:
#Data
#AllArgsConstructor
#NoArgsConstructor
public class PutDataRequest {
Set<String> characters = new HashMap<>();
Set<String> movies = new HashMap<>();
}
I try hitting the rest api controller via curl to perform testing. The Application JSON PUT request receives characters and movies no problem, however the form-urlencoded endpoint does so inconsistently:
// No data populated in PutDataRequest at debug time:
curl -X PUT 'http://localhost:some-port/rest/api' -d 'characters=Some%20Name%26movies=Some%20Title' -H 'Content-Type: application/x-www-form-urlencoded'
// Data populated in PutDataRequest at debug time:
curl -X PUT 'http://localhost:some-port/rest/api?characters=Some%20Name%26movies=Some%20Title' -H 'Content-Type: application/x-www-form-urlencoded'
Can anyone give an insight on why providing the key-value pairs via -d prevents the data from being forwarded to the form-urlencoded PUT endpoint? For context, I run this coded using spring version 5.2.3.RELEASE and spring boot version 2.2.4.RELEASE.
I decided to sidestep Spring in this situation. Instead of relying on Spring to figure out how to marshal the data I wanted, I added a HttpServletRequest to the form-urlencoded method signature and pulled the data out of the request:
#PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
private ReturnType putRestApiTypeUrlEncoded(
#PathVariable("id") String id,
#ModelAttribute PutDataRequest data,
HttpServletRequest request) {
String body = request.getRequest().lines()
.map(line -> URLDecoder.decode(line, Charset.defaultCharset()))
.collect(Collectors.joining(System.lineSeparator()));
// manipulate body content to extract desired data
}
I was inspired to do the above by this answer.
Also found another way to get around this error. Turns out PUT and DELETE requests aren't enabled by default, and you need to add an implementation for the formContentFilter method in your Application.java (or wherever you call SpringApplication.run(...) )
Once I added the following to Application.java, I ran again and it worked like magic:
#Bean
#ConditionalOnMissingBean(org.springframework.web.filter.FormContentFilter.class)
#ConditionalOnProperty(prefix="spring.mvc.formcontent.filter", name="enabled", matchIfMissing=true)
public OrderedFormContentFilter formContentFilter() {
return new OrderedFormContentFilter();
}

REST API call from spring boot not working

I am trying to fetch live data from NSE options trading. Below code is not working and the request made is stuck without any response.
Any workaround on this?
public void getLiveBankNiftyData() {
String RESOURCE_PATH = "https://www.nseindia.com/api/option-chain-indices?symbol=BANKNIFTY";
ResponseEntity<Object[]> responseEntity = restTemplate.getForEntity(RESOURCE_PATH, Object[].class);
Object[] objects = responseEntity.getBody();
}
i tried this
// request url
String url = "https://www.nseindia.com/api/option-chain-indices?symbol=BANKNIFTY";
// create an instance of RestTemplate
RestTemplate restTemplate = new RestTemplate();
// make an HTTP GET request
String json = restTemplate.getForObject(url, String.class);
// print json
System.out.println(json);
I found a way out. Instead of using RestTemplate I used WebClient and this solved the issue.

Using Feign #HeaderMap with Springboot 1.5.4.RELEASE does not send headers

I am trying to use feign.HeaderMap annotation to pass a map of HTTP headers in the rest request but these are appearing in the body.
Code below:
#FeignClient(name = "accounts", url = "localhost:8080")
public interface AccountClient {
#RequestMapping(method = RequestMethod.GET, value = "/rest/accounts/get", produces = MediaType.APPLICATION_JSON_VALUE)
Account findOne(#RequestParam("id") String id, #HeaderMap Map headers);
}
You are mixing annotations. When using spring-cloud-netflix you will need to use the Spring annotation #RequestHeader instead.
#RequestMapping(method = RequestMethod.GET,
value = "/rest/accounts/get",
produces = MediaType.APPLICATION_JSON_VALUE)
Account findOne(#RequestParam("id") String id, #RequestHeader Map headers);
In Feign by default, all parameters not annotated will be serialized in the Body.

Make Rest Client using Spring Rest Template

Here is my spring controller code..
#RequestMapping(value= "/save_item",
method = RequestMethod.POST,produces="application/json")
public #ResponseBody ModelMap saveItem(ModelMap model,
#RequestParam("id") String itemId,
#RequestParam("name") String itemName) {
model.addAttribute("itemId",itemId);
return model;
}
How can i make a rest client using spring rest tempalte?.
I need to send two parameters from my rest client(id,name).
Anyone Please help me.
Thanks.
You can create a RestTemplate object and execute as this
ResponseEntity<List<City>> result = restTemplate.exchange(
new StringBuilder(URL).append(city).toString(),
HttpMethod.GET, null, responseType);
In this project you can find a maven project with spring-boot and sptring-web that uses this restTemplate snippet and jackson for the json response
https://github.com/voliveirajr/dev-test

Need help on RestTemplate Post Request with Body Parameters?

I have a rest api url and submitted the same as POST request with body (user name, password, other parameters) via Rest Client (restclient-ui-2.4-jar-with-dependencies) and it got worked fine without any issues.
Ex:
URL: https://test.com/cgi-bin/testing/api
Body: username=testuser&password=pass123&id=13002&name=raju
The same is not working fine when i used Spring RestTemplate postForObject(url, varmap, Employee.class) method.
Can someone help me with a simple example where the request is a URL, with body parameters and the response is XML which is mapped with a class?
Sample Code:
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("username", "test");
map.add("password", "test123");
map.add("id", "1234");
MarshallingHttpMessageConverter mc = new MarshallingHttpMessageConverter();
mc.setMarshaller(new Jaxb2Marshaller());
mc.setUnmarshaller(new Jaxb2Marshaller());
list.add(marshallingHttpMessageConverter);
emediateRestTemplate.setMessageConverters(list);
Employee employee = (Employee) restTemplate.postForObject(url, map, Employee.class);
Thanks in advance,
Kathir
The above converters Ex: "MarshallingHttpMessageConverter" are not required.
MultiValueMap<String, String> parametersMap = new LinkedMultiValueMap<String, String>();
parametersMap.add("username", "test");
parametersMap.add("password", "test123");
parametersMap.add("id", "1234");
For Post:
restTemplate.postForObject(url, parametersMap, Employee.class);
url is String - rest api URL
parametersMap - MultiValueMap
Employee - object which needs to be converted from the JSON response
For Get:
restTemplate.getForObject(url, class object, variablesMap);
url is : String - rest api URL
variablesMap - Map
class object - object which needs to be converted from the JSON response

Resources