Spring #RequestHeader defaultValue for header parameter that is not required - java

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
}

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.

REST RequestParam optional parameter

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);
}

Spring MVC: Dynamic Param Name or Param Name using Regex?

I'm trying out this grid component called jQuery Bootgrid. In AJAX mode, it POSTs parameters to the server and the one related to sorting is sent like this:
sort[colname]=desc
The colname part changes depending on how you sort the grid.
Is there any way in Spring MVC using #RequestParam to capture that sort param?
For example, something like:
#RequestParam("sort[{\\*}]") Map<String, String> sort
That's just a wild guess and I doubt there is any clean way to do it. Any suggestions on how to handle it would be great.
Update: Also tried this simpler version which I actually thought might work
#RequestParam("sort") Map<String, String> sort
See on bootgrid forum: https://github.com/rstaib/jquery-bootgrid/issues/111
It is really silly but because cannot parse dynamic parameter on server side, you need to create new request parameters from the sort parameter by defining requestHandler in your bootgrid configuration in the following way:
requestHandler: function (request) {
if (request.sort) {
request.sortBy = Object.keys(request.sort)[0]; //this only gets first sort param
request.sortDir = request.sort[request.sortBy];
delete request.sort
}
return request;
}
And in Spring Controller:
#RequestParam(value = "sortBy", required = false) final String sortBy,
#RequestParam(value = "sortDir", required = false) final String sortDir
Do not forget to mark these parameters as not required because sort is not always posted to server side.

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.

Different response entity body based on accept header with Spring WebMVC REST controller

I have a controller with a method signature like this
#RequestMapping(value = "/{project:[A-Z0-9_+\\.\\(\\)=\\-]+}", method = RequestMethod.GET)
public ResponseEntity<Object> lookupProject(#PathVariable String project,
#RequestParam(value = "fields", required = false) String fields,
#RequestParam(value = "asList", required = false, defaultValue = "false") boolean asList);
I am returning for JSON a Collection<Object> or Map<String, Object>. This isn't suitable for XML. I'd rather return a Project object.
Is there a clean way to determine which content type will be produced? The work-around would be another method which produces XML only and returns the Project object. I'd rather like to avoid duplicate code.
I am on Spring 3.1.3-RELEASE.
According to Spring documentation, your produces param will return content based on the Accept, i.e.
#RequestMapping(value="/someUrl/", produces="application/*")
public Project someControllerMethod(...)
If the method takes in application/xml, the method will produce XML, if application/json, it will produce json, etc.
You just need marshallers set up for the appropriate object types.
Documentation here:
http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html#produces()
Content type to be produced will depend on type acceptable by the client.One solution for this is already mentioned, using produces attribute.Another solution is using ContentNegotiatingViewResolver, which can resolve views based on accept header or other mechanism.
Refer the documentation http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.html
Example:http://www.mkyong.com/spring-mvc/spring-3-mvc-contentnegotiatingviewresolver-example/
Albeit, I think Dardo's solution is best, you could inspect the object type with your XMLHttpMessageConverter, and cast differently if it's a Project object.
In Spring Framework 4.1 you can use a ResponseBodyAdvice to modify the value returned from an #ResponseBody or ResponseEntity method just before it is written out.
See http://docs.spring.io/spring-framework/docs/4.1.0.RC2/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyAdvice.html.
I ended up in splitting in two methods.
Public methods have been renamed to lookupAsType. Both delegate/return
String[] fieldsArray = StringUtils.split(fields, ',');
return lookup(project, fieldsArray, asList, mediaType);
The new method lookup has the same code s before but contains not an if clause for the media types.
if (mediaType.equals(MediaType.APPLICATION_JSON)) {
body = projectValues;
} else if (mediaType.equals(MediaType.APPLICATION_XML)) {
body = new Project(projectValues);
} else {
throw new NotImplementedException("Project lookup is not implemented for media type '" + mediaType + "'");
}
The bad thing is that MediaType is not a enum but an ugly class.

Categories

Resources