Does Springboot #RequestParam support List<Object> params in get request - spring-boot

Springboot #RequestParam annotation can pass basic list parameters, just like:
#GetMapping("param")
public String requestParamDemo(#RequestParam("list")List<Long> list) {
System.out.println(list.toString());
return list.toString();
}
and in postman, GET request localhost:8998/param?list=1,3,100 is works, "1,3,100" can be converted to List, but how or if Springboot #RequestParam support custom Generics such as below:
#GetMapping("objlist")
public String paramWithObjList(#RequestParam("objList")List<AaParam> objList) {
System.out.println("objList = " + objList);
return objList.toString();
}
import lombok.Data;
#Data
public class AaParam {
private int id;
private String name;
}
postman request: GET url: localhost:8998/objlist?objlist=[{id: 1, name: "aa"},{id: 2, name: "bb"}]
I tested in local and it didn't work.
Want to know if #RequestParam can do that or any alternative way to implement it.
Thanks!

Hope this suggestion holds good for your requirement.
I would suggest going with #RequestBody code will look like this
#PostMapping(path = "/objlist", consumes = "application/json", produces = "application/json")
public String paramWithObjList(#RequestBody List<AaParam> objList) {
System.out.println("objList = " + objList);
return objList.toString();
}
Note: please add some ObjectPaser in your actual logic (for example Jackson )
Postman request would be like this

Related

Controller Parameter giving a strange error

I have a wrote a project using spring boot my controller were just working fine until I have added
'params' to getmapping annotation
my PlaneTypeVersionedApi Interface down below;
#Validated
#RequestMapping("/version")
public interface PlaneTypeVersionedApi {
#GetMapping(value = "/plane", params = "v1")
ResponseEntity<String> getOnePlaneByProduce1(#RequestParam("plane-type")String planeType);
}
my PlaneTypeVersionedApiImpl Class down below;
#RestController
public class PlaneTypeVersionedApiImpl implements PlaneTypeVersionedApi {
private final PlaneCallerService planeCallerService;
public PlaneTypeVersionedApiImpl (PlaneCallerService planeCallerService) {
this.planeCallerService = planeCallerService;
}
#Override
public ResponseEntity<String> getOnePlaneByProduce1(String planeType) {
return ResponseEntity.ok(planeCallerService.getPlaneType(planeType));
}
}
when I try on Postman for my controller;
localhost:9080/version/plane?plane-type=light-weight?v1
I have 400 bad request and saying
Resolved [org.springframework.web.bind.UnsatisfiedServletRequestParameterException: Parameter conditions "v1" not met for actual request parameters: plane-type={light-weight?v1}]
The syntax of the query parameters on the url is not valid.
Here is the correct syntax : localhost:9080/version/plane?plane-type=light-weight&v1.
https://launchschool.com/books/http/read/what_is_a_url#querystringsparameters
your url is bad not sure what your intent use of params
example 1 valid url = localhost:9080/version/plane?plane-type=light-weight&v1=
using #RequestParam("plane-type") String plane-type
#RequestParam("v1") String v1 is enough to get the value no need use of attribute params
example 2 if you want to use params
#GetMapping(value = "/plane", params = {"v1"}) this mean you want v1 value
ResponseEntity<String> getOnePlaneByProduce1(#RequestParam("v1")String v1);
example 3 you want both
#GetMapping(value = "/plane", params = {"v1","plane-type"}) this mean you want v1 value and plane-type
ResponseEntity<String> getOnePlaneByProduce1(#RequestParam("v1")String v1, #RequestParam("plane-type") String plane-type);
params option just mean that endpoint require to have those params if one you specific is not there it gonna complain

#FormParam convert to Spring MVC

I am using the latest version of Spring. I have to integrate with a third party server of company A. Now, company A has given me this code:
Path("/user")
public class CallBacks {
String hostDB="jdbc:mysql://localhost:3306/matchmove";
String username="root";
String password="password";
#POST
#Path("/add")
// #Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response receive(
#FormParam("id") String id,
#FormParam("amount") String amount,
#FormParam("asset_code") String assetCode,
#FormParam("asset_issuer") String assetIssuer,
#FormParam("memo") String memo) throws NumberFormatException, SQLException {
return Response.ok().build();
}
I want to use Spring as the rest of my project is in Spring! Can some one please advice on the following:
Which annotation can I use in place of #FormParam?
What can I use in place of Response.ok().build()?
Thank you
#FormParam -> #RequestParam
Response.ok -> ResponseEntity.ok
#PostMapping(value = "/add")
public ResponseEntity receive(#RequestParam("id") String id) {
return ResponseEntity.ok().build();
}

DTO has only null with GET request params, but not POST #RequestBody

I'm trying to get my query params in a DTO like in this question but my DTO has always null value.
Is there anything wrong in my code ? I made it as simple as possible.
Queries:
GET http://localhost:8080/api/test?a=azaz => null
POST http://localhost:8080/api/test with {"a":"azaz"} => "azaz"
Controller with a GET and a POST:
#RestController
#RequestMapping(path = {"/api"}, produces = APPLICATION_JSON_VALUE)
public class MyController {
// GET: dto NOT populated from query params "?a=azaz"
#RequestMapping(method = GET, path = "test")
public #ResponseBody String test(TestDto testDto){
return testDto.toString(); // null
}
// POST: dto WELL populated from body json {"a"="azaz"}
#RequestMapping(method = POST, path = "test")
public #ResponseBody String postTest(#RequestBody TestDto testDto){
return testDto.toString(); // "azaz"
}
}
DTO:
public class TestDto {
public String a;
#Override
public String toString() {
return a;
}
}
Thanks !
Full Spring boot sample to illustrate it
The problem is that you are missing setter for the field.
public void setA(String a) {
this.a = a;
}
should fix it.
I'm assuming that you have done required configuration like having Jackson mapper in the class path, consume json attribute, getter and setter in DTO classes etc.
One thing missed here is, in RequestMapping use value attribute instead of path attribute as shown below
#RequestMapping(method = POST, value= "/test", consumes="application/json")
public #ResponseBody String postTest(#RequestBody TestDto testDto){
return testDto.toString();
}
And, make sure that you set content-type="application/json" while sending the request
I think what you are trying to do is not possible. To access the query Parameter you have to use #RequestParam("a"). Then you just get the String. To get your object this way you have to pass json as Parameter. a={"a":"azaz"}
Kind regards

How to specify multiple parameters in POST method

I have Model called Loan:
public class Loan {
private int loan_id;
private String clientName;
private String clientSurname;
private Double amount;
private int days;
//getters and setters
}
And Controller
#RestController
public class MyController {
#Autowired
MyService myService;
#RequestMapping(value = "/makeAction",method = RequestMethod.POST)
public String makeLoan(){
return myService.makeAction(...);
}
}
The question is: how to bypass multiple variables via adressbar like:
localhost:8080/makeAction?loanId=1#clientName=Stive#clientSurname=Wassabi
and so on.
UPD: Another attempt failed:
#RequestMapping(value="/makeLoan",method = RequestMethod.GET)
public String makeLoan(#PathVariable("loan_id")int loan_id,
#PathVariable("name") String clientName,
#PathVariable("surname") String clientSurname,
#PathVariable("amount") double amount,
#PathVariable("days") int days ) throws Exception {
return myService.makeLoan(loan_id,clientName,clientSurname,amount,days);
P.S tried #PathVariables - failed to use
Thanks you all for helping me with this
The final code looks like that:
#RequestMapping(value = "/makeAction")
public String makeLoan(#RequestParam("loan_id")int loan_id,
#RequestParam("clientName")String clientName,
#RequestParam("clientSurname")String clientSurname,
#RequestParam("amount")double amount,
#RequestParam("days")int days ) throws Exception {
return loanService.makeAction(loan_id,clientName,clientSurname,amount,days);
}
I had to remove GET/POST method and switch #PathVariable to #RequestParam
Well, first of all, you shouldn't put parameters for POST in the URL.
URL parameters are used for GET, and they are separated with & so in your case:
localhost:8080/makeAction?loanId=1&clientName=Stive&clientSurname=Wassabi
For POST you should submit parameters as request body parameters. Parameters are bound with #RequestParam annotation like #SMA suggested.
In your method define them with RequestParam annotation like:
public String makeLoan(#RequestParam(value="clientName", required=false) String clientName) {//and others, and hope you meant & to seperate request parameters.
}
Well, assuming you're using spring MVC, this could be helpful:
How to explictely obtain post data in Spring MVC?
Be aware that if you're using a POST method, your parameters should be read in the request body...

Spring MVC #RequestParam a list of objects

I want to create a page where a person sees a list of users and there are check boxes next to each of them that the person can click to have them deleted.
In my MVC that consumes a REST API, I want to send a List of User objects to the REST API.
Can the #RequestParam annotation support that?
For example:
#RequestMapping(method = RequestMethod.DELETE, value = "/delete")
public #ResponseBody Integer delete(
#RequestParam("users") List<Users> list) {
Integer deleteCount = 0;
for (User u : list) {
if (u != null) {
repo.delete(u);
++deleteCount;
}
}
return deleteCount;
}
In the MVC client, the url would be:
List list = new ArrayList<User>();
....
String url = "http://restapi/delete?users=" + list;
Request parameters are a Multimap of String to String. You cannot pass a complex object as request param.
But if you just pass the username that should work - see how to capture multiple parameters using #RequestParam using spring mvc?
#RequestParam("users") List<String> list
But I think it would be better to just use the request body to pass information.
Spring mvc can support List<Object>, Set<Object> and Map<Object> param, but without #RequestParam.
Take List<Object> as example, if your object is User.java, and it like this:
public class User {
private String name;
private int age;
// getter and setter
}
And you want pass a param of List<User>, you can use url like this
http://127.0.0.1:8080/list?users[0].name=Alice&users[0].age=26&users[1].name=Bob&users[1].age=16
Remember to encode the url, the url after encoded is like this:
http://127.0.0.1:8080/list?users%5B0%5D.name=Alice&users%5B0%5D.age=26&users%5B1%5D.name=Bob&users%5B1%5D.age=16
Example of List<Object>, Set<Object> and Map<Object> is displayed in my github.
Just a reminder, any List of custom objects might require custom converters to be registered, like:
#Bean
public Converter<String, CustomObject> stringToCustomObjectConverter() {
return new Converter<>() {
#Override
public CustomObject convert(String str) {
return new ObjectMapper().readValue(str, CustomObject.class);
}
};
}
#Bean
public Converter<String, List<CustomObject>> stringToListCustomObjectConverter() {
return new Converter<>() {
#Override
public List<CustomObject> convert(String str) {
return new ObjectMapper().readValue(str, new TypeReference<>() {
});
}
};
}
So you can cover custom cases like:
/api/some-api?custom={"name":"Bla 1","age":20}
/api/some-api?custom={"name":"Bla 1","age":20}&custom={"name":"Bla 2","age":30}
/api/some-api?custom=[{"name":"Bla 1","age":20},{"name":"Bla 2","age":30}]
where: #RequestParam("custom") List customObjects

Resources