#RequestParam value converted to lower case - spring

I've a simple controller containing a request param like:
#RequestParam(required = false) String name
Now I also have mockmvc test containing:
mockMvc.perform(get("/rest/hello/greet")
.param("name", "Marcel"))
In the logging I see it seems the request param is passed through correctly:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /rest/hello/greet
Parameters = {name=[Marcel]}
However in my controller the request param comes in in lowercase..
#Get(path = "/greet", produces = APPLICATION_JSON_VALUE)
public ResponseEntity<JSONObject> greet(#RequestParam(required = false) String name) {
logger.info("greet called with name: {}", name);
It prints greet called with name: marcel.
Also - obviously - when passing this argument to other service it is passed as lowercase.
It's a very simple Spring Boot application so I wonder why this request param is coming in in lowercase.

Found the issue some Converter<String, String> was in application context which was causing this issue.

Related

Required request parameter for method parameter type String[] is not present spring boot

I am trying to read an array value from query param which is passes as
ot-replace[0]=kin43
On the controller I have
#GetMapping(value = "/{userId}/**")
public ResponseEntity<String> viewObject(#PathVariable(value = "userId") String uid,
#RequestParam(name="ot-replace")String[] regexReplace){}
I get the following error
"trace": "org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'ot-replace' for method parameter type String[] is not present\r\n\tat org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValueInternal(RequestParamMethodArgumentResolver.java:218)\r\n\tat org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:193)\r\n\tat org.springframework.web.
instead of ot-replace[0]=kin43 replace with ot-replace=kin43&ot-replace=kin44
You will get two item in your array.

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

How to write appropriate endpoint in Spring Boot for GET request?

I have an assignment to write simple GET request.
The format that is going to be typed in URL is like this:
http://localhost:8080/api/tasks/20-08-2020
Server should return TODOs for that date. I did managed to write a finder method. But not sure how to write an endpoint. This is what I have so far:
#GetMapping(value = "/{date}", consumes="application/json")
public ResponseEntity<List<Task>> getTasksByDateUsingURL(#PathVariable("date") #DateTimeFormat(pattern="dd-MM-yyyy") #Valid LocalDate dueDate){
List<Task> tasks = taskService.getAllTasksByDate(dueDate);
return new ResponseEntity<List<Task>>(tasks,HttpStatus.OK);
}
This is inside RestController class:
#RestController
#RequestMapping(value="/api/tasks")
public class TaskController {...}
I cannot hit this GET endpoint...
Workaround for your problem is to get the string as parameter and parse it manually
#GetMapping(value = "/{date}", consumes="application/json")
public ResponseEntity<List<Task>> getTasksByDateUsingURL(
#PathVariable("date")
String date
){
LocalDate dueDate = parse(date);
List<Task> tasks = taskService.getAllTasksByDate(dueDate);
return new ResponseEntity<List<Task>>(tasks,HttpStatus.OK);
}
private LocalDate parse(String stringDate) {
// TODO
}
As author said in comments:
When try to call the endpoint from browser, the mapping is not executed.
Seems like that the browser is sending request with wrong Content-Type header. Your mapping is explicitly requires only application/json value.
When try to call the endpoint from Postman, the application returns 400 status.
I could not see the body of response, but I guess the problem is #Valid annotation on the parameter. How should Spring validate the LocalDate?
So the solution is to remove consumes="application/json" from mapping or send corresponding Content-Type value
and remove #Valid annotation from parameter.

Issue with Spring Rest #RequestMapping when negating params

I have two spring controller methods :
#RequestMapping(value="/requestotp",method = RequestMethod.POST,params = "!applicationId") //new customer
public OTPResponseDTO requestOTP( #RequestBody CustomerDTO customerDTO){
return customerService.requestOTP(customerDTO);
}
#RequestMapping(value="/requestotp",method = RequestMethod.POST,params = {"idNumber","applicationId"}) //existing customer
public String requestOTP( #RequestParam(value="idNumber") String idNumber , #RequestParam(value="applicationId") String applicationId) {
return customerService.requestOTP(idNumber, applicationId);
}
using "!applicationId" , I am expecting that when I call the url with applicationId parameter there that the second method will be called , but actually when I pass a request like this :
{"idNumber":"345","applicationId":"64536"}
The first method gets called
This is the part of the params paremeters documentation that I rely on :
Finally, "!myParam" style expressions indicate that the specified
parameter is not supposed to be present in the request.
Can't you just simply delete first request params?
#RequestMapping(value="/requestotp",method = RequestMethod.POST) //new customer
public OTPResponseDTO requestOTP( #RequestBody CustomerDTO customerDTO){
return customerService.requestOTP(customerDTO);
}
The issue actually wasn't with negating the parameter, the issue was that I was sending {"idNumber":"345","applicationId":"64536"} in the POST body and I was expecting the variables to be mapped to the method parameters annotated with #RequestParam ... this is not correct ... #RequestParam only map URL parameters .... so the controller was trying to find the best match so it was using the first method as it contained #RequestBody

How to pass String array in #RequestParam in REST GET API call through POSTMAN or DHC REST application?

I have following REST controller in Java Spring Application:
#RequestMapping(
value = "/api/getApplication/{me_userId}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public Object getApplication(
#PathVariable String userId,
#RequestParam(value="fieldNames[]", required = false) String[] fieldNames) {
if (fieldNames != null) {
for (String fieldName : fieldNames)
System.out.println(fieldName);
}
...
return null;
}
So I can not succeed in simulating API call from DHC REST of POSTMAN what will pass that fieldNames[].
Does anyone know how to do it?
First of all, your current method does not work because your #PathVariable is wrong. In your #RequestMapping you have the following placeholder in your path: {me_userId}, which means that it will be mapped to a path variable with that name.
However, the only #PathVariable you have is nameless, which means it will use the name of the parameter (userId) in stead.
So before you try to execute your request, you have to change your #RequestMapping into:
#RequestMapping(
value = "/api/getApplication/{userId}", // <-- it's now {userId}
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
Then, if you run the application, you can kinda choose how you want to pass your parameters. Both the following will work:
?fieldNames[]=test,test2
Or:
?fieldNames[]=test&fieldNames[]=test2
Both these results should print the desired results.

Resources