REST RequestParam optional parameter - java

I have an Interface method which can be called as below -
{{url}}/packageName/{{var}}/list
It can take in a param of type Collection<String> , so i can fetch specific results.
{{url}}/packageName/{{var}}/list?paramIds=param1&paramIds=param2
Now if i leave paramIds empty as below, Spring MVC creates LinkedHashMap , size 0 and i get no results back.
{{url}}/packageName/{{var}}/list?paramIds=
This is my annotation #RequestParam(value = "paramIds", required = "false") Collection<String> paramIds
I tried to get rid of required and use defaultValue but unable to set defaultValue to null.
For now i changed the annotation to #RequestParam(value = "paramIds", defaultValue = "none") and added code in the dao to handle "none" as null - wondering if there is a better way to solve this problem.
Thanks in advance.

It sounds to me like Spring is giving you the best option, an empty list is usually better than a null.
My first choice would be to modify your DAO code to handle an empty list instead of expecting null, but assuming that's not possible, why not have a check in your controller to pass null to your DAO if the collection is empty, like:
if (paramsIds.isEmpty()) {
dao.doSomething(null);
}

Related

Accessing optional parameters in Spring Boot GraphQL

I have this QueryMapping method where I have some parameters marked as required in my GrapthQL schema, but not all. Using #Argument allows me to grab all required parameters, but when I send a Query without an optional parameter it crashes. Using the RequestParam annotation with a default value doesn't work since its type is an integer and the annotation requires a string. (I guess it's supposed to be called within a REST-API)
#QueryMapping
public List<Record> getRecord(Argument String email, #Argument int dateFrom, #RequestParam(required = false, defaultValue = 0) int dateTo) {
return repository.findSpecific(email, dateFrom);
}
Edit: Method overloading does not work.
What can I do?
I found a solution by using Kotlin: Adding a Question mark behind the Parameter Type allows me to set the value to null.

spring expression with ResponseEntity Type

Actually, I am caching an Http Response using Spring Cache and now I want to put a condition that is to update the cache only when the Response is valid.
#Cacheable(value = CACHE, condition = "#result.body.responseData.toLowerCase().contains("A")")
public ResponseEntity<ProcessMqReqPostResponseBody> sendMqRequest(Integer pageNumber, Integer pageSize, String sortOrder, String merchantId) {
//Method Implementation
}
Without the condition, I can test my cache fine but when I added this condition, I get the error
org.springframework.expression.spel.SpelEvaluationException: EL1007E:
Property or field 'body' cannot be found on null
I don't understand that because I can output the responseEntity in my test and it is not null. Is that behavior correct?
Thanks,
Ashley
Spring's behavior is correct because you are writing a condition that will work according to the result.
The #result value is always null before the method is executed, the result value is only filled after the method is executed.
If you want to test this, you can change your condition as follows, method will not be cached at all and will not give an error.
#Cacheable(value = CACHE, condition = "#result != null and #result.body.responseData.toLowerCase().contains(\"A\")")
If you want to act on the result, you can only do so using the unless element.
Unlike condition(), this expression is evaluated after the method has been called and can therefore refer to the result.
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/cache/annotation/Cacheable.html#unless--

Spring #RequestHeader defaultValue for header parameter that is not required

I am trying to add a default value to an optional header parameter for when it is not present. However, when the parameter is not included, I noticed that it is not being populated with the default value:
public Mono<User> getUser(
#RequestHeader(value = "accept", defaultValue = "abc") String acceptHeader,
...
)
When I am debugging the code, acceptHeader is "/" when no the param is not specified. I looked online and could not find any reason as to why this is happening. Not sure if it makes a difference, but I am making the call with Postman. Does anyone have any idea why this is happening? I could implement code to handle this logic inside getUser but I would like to ideally use annotations.
/ is a default value so is not empty and defaultValue = "abc" doesn't work. If you want to do something when nothing was put into accept value use this instead it defaultValue = "abc":
if (acceptHeader.eqals("/") {
... do something
}

How to keep nulls in a Spring GET servlet?

#RestController
public class MyController {
#GetMapping("/get)
public void get(Map<String, String> params) {
println(params.get("optional")); //"null"
}
#PostMapping("/post)
public void post(Map<String, String> params) {
println(params.get("optional")); //null
}
}
localhost:8080/get?key=value&optional=null
Result: the value of the key optional will be "null" written as String, not as null type.
Whereas a POST request would work as follows:
{
"key": "value",
"optional": null
}
Question: how can I make the GET request behave the same as POST? Means, how can I tell spring to interpret the null string in a GET as a real null?
You can't pass null via HTTP query parameter like you do it in JSON. Because null within an HTTP query has no special meaning and is treated like any other string.
Instead just don't pass optional parameter at all
localhost:8080/get?key=value
You could do something like this as well.
#RequestParam(name = "optional", required = false) String optional
Spring Docs
Like #Nikolai says, null has no special meaning in the query. The query is often called the Query String such as in AWS API Gateway, which is more descriptive that it tells you that it is a String, it isn't a Map, Strings only have chars encoded, there is no concept of a null in this context.
IMO it isn't good practice to use a Map<String,String> params if you can avoid it, rather prefer strong types and list all the possible query params with optional parameters for non-required inputs. If you want the users to specify a Map it should be in the BODY, but a GET with a body feels wrong to me so you might need to then change the HTTP method.
If you have many parameters, and that's why you are using a Map, remember some browsers limit the chars in a URL to 2048, so it can be dangerous and you may have a case whereby the user cannot specify all the parameters they need to because of this limit.
TL;DR: Map<String,String> should be in request body.

Spring MVC default value not working

#RequestMapping(value = "/Fin_AddBankAccount", method = RequestMethod.POST)
public #ResponseBody JsonResponse addCoaCategory(
#RequestParam(value="code", required=true) long code,
#RequestParam(value="startFrom", required=true) long startFrom,
#RequestParam(value="name", required=true, defaultValue="N/A") String name)
{
}
defaultValue="N/A" not working , As I did not provide any text in name field , it store null in database instead of "N/A"?
What is the point of setting a default value if you really want that parameter.
if you mark it as required true(not needed as it is default) then no need of a default value.
If that parameter is not mandatory then mark it as false and give a default value.
Documentation of Spring RequestParam.required
Default is true, leading to an exception thrown in case of the parameter missing in the request. Switch this to false if you prefer a null in case of the parameter missing.
From your question I figured out that you are sending parameter name with empty value using POST request. According to the Spring documentation you should not send name parameter in the request in order to use default value. Simply remove name field from HTML form if it is empty.
It seems that default values makes more sense for GET requests.
make sure you don't pass empty string value
Valid Methods:
1. Fin_AddBankAccount?name=
O/P: name="N/A"
Fin_AddBankAccount?
O/P: name="N/A"
Invalid Methods:
Fin_AddBankAccount?name=""
this will set empty string to variable i.e. name="";
In my project
#RequestParam(value="name", required=true, defaultValue="N/A") String name
This code correctly sets name variable as defaultvalue N/A when requestparam "name" was not provided. My guess is you are not inserting this name variable into the table properly so database is storing null instead of "N/A". Please show us or double check the data access object code. Good luck
Thanks #TiarĂª Balbi, in fact you do not need "required=true" because defaultValue="N/A" implicitly sets this variable as required=false anyways.

Categories

Resources