Spring Same URL Different Request Parameter - spring

public String searchUserById(#RequestParam(value = "fileType", required = true) String fileType) {
System.out.println(fileType);
return "downloadexcel";
}
public String searchUserByName(#RequestParam(value = "fileType", required = true) String fileType, #RequestParam(value = "batchNo", required = true) String batchNo) {
System.out.println(fileType + " ----------- " + batchNo);
return "downloadexcel";
}
This kind of URL Patterns i need I found some relevant Questions but i am getting 400 bad request when hitting the url
1.http://localhost:8080/apna-shopee/download.htm?fileType=mani
2.http://localhost:8080/apna-shopee/download.htm?fileType=mani&batchNo=1001
Didn't find the correct solution.

visit following link this may help you to solve your issue
create two method for same url pattern with different arguments
You can also do this based on condition. just make simple method with two parameters and based on second parameter value you can perform appropriate action. i.e if second parameter value is null that means request done using only single parameter

Related

How to pass 2 or more variables using #PathParam in spring mvc? and suppose if I want to test it out using postman how to do that?

I'm trying to fetch value from db using JPA repository method
product findByIdNumberOrCifNumber(String idNumber , String cifNumber);
service class logic:-
public ResponseModel FindByCivIDOrCifNumber(String idNumber,String cifNumber) {
ResponseModel responseModel = new ResponseModel();
Optional<product> civId = Optional.ofNullable(productRepos.findByIdNumber(idNumber));
if (civId.isPresent()) {
responseModel.setResponse(productRepos.findByIdNumberOrCifNumber(idNumber,cifNumber));
} else {
errorModel errorModel1 = new errorModel();
enter image description here errorModel1.setErrorCode(productConstant.INVALID_REQUEST);
errorModel1.setErrorDescription("Requested Civil Id or CifNUmber is not present");
responseModel.setErrorModel(errorModel1);
}
return responseModel;
}
controller class:-
#GetMapping("/getByCifNoOrGetByIdNo")
public ResponseModel getProductByCifNoOrGetByIdNo(#RequestParam String idNumber,#RequestParam String cifNumber ) {
return productService.FindByCivIDOrCifNumber(idNumber,cifNumber);
}
post man:-
kindly help me out how to make it work:)
If you are looking for an answer to pass two or more path variables and test it with postman, you can try this.
#GetMapping("/api/mapping-name/{variable1}/{variable2}")
Here you will be getting two path variables which you can access by the syntax
#PathVariable("variable1") datatype variableName
Now in postman request url you can simply give the respective url, lets say:
https://localhost8080/api/mapping-name/:variable1/:variable2
which automaticaly will give you a key value section in the path variables section in the params with prepopulated key names as per the name you have given. In this case variable1 & variable2.
Give the respective value and it should work.

Is there any situation QueryString is present but HttpServletRequest.getParameterMap() is empty?

I have encouterd an odd situation while we are doing press testing in our test env. When the app load is high, the Query String will missing occasionally and the Spring will throw MissingServletRequestParameterException.
In order to find the root cause , I add some logs at the foremost Filter(code is shown below), and something weired happened.
public static void printRequestParameter(HttpServletRequest request) {
Map<String, String[]> parameterMap = request.getParameterMap();
log.info("Request URI : {}, method = {} , query string = {}", request.getRequestURI(), request.getMethod(), request.getQueryString());
if (MapUtils.isNotEmpty(parameterMap)) {
parameterMap.forEach((k, v) -> {
log.info("Request parameter name = {}, value = {}", k, ArrayUtils.isEmpty(v) ? Strings.EMPTY : Arrays.stream(v).collect(Collectors.joining(COMMA)));
});
}
}
The request.getParameterMap() is empty, but , the query string is not empty , and I got a log like :
Request URI : /a/b/c, method = POST , query string = foo=bar.
But no logs like:
Request parameter name = foo , value = bar
And our Controller use #RequestParam() String foo to receivce the parameter , finally , the Spring throws
MissingServletRequestParameterException Handler org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'foo' is not present
at org.springframework.web.method.annotation.RequestParamMethodArgumentResolver.handleMissingValue(RequestParamMethodArgumentResolver.java:204)
at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:114)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167)
at org.springframework.web.method.support.InvocableH
I just wonder, why the parameter in query string is not contained in parameterMap?
Note:
The odd behavior is only happened occasionally, at most time it's just works.
My spring boot version is 2.3.9.RELEASE and the embedded tomcat version is 9.0.43.
Any help is appreciated!
Since the specification does not allow ServletRequest.getParameterMap to throw any exception, any failure in parameter parsing will cause the parameter list to be empty.
To detect this situation you can log the "org.apache.catalina.parameter_parse_failed_reason" attribute of your request.
Examples of query strings that should fail:
?=noname,
?urlEncoding=%ue

#PathVariable of GetMapping in Spring throws an error when the input is #

I have made an autosuggest input field that automatically searches the database on every keypress. It works fine when i insert regular characters like letters and numbers but it gets spooky when you try start the search request with the character #. Doing that throws the error org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'long'; nested exception is java.lang.NumberFormatException: For input string: "get"
When i add some letters before the # (for example des#) it will throw an 404 page not found error and if i use the % character it will throw an 400 'unauthorized' error.
This strange behavior has probably something to do that i'm expecting a GetRequest instead of a PostRequest. If i turn it into a PostMapping i'm sure the errors will dissapear. But my question is; why is this happening? Does # have a special meaning? Why does spring seemingly try to convert # to a long value even though the pathvariable is typed as String? And why has the input string become "get" according to the error? I know that in an url # has a special meaning in that it signifies an href anchor but why should it be a special character for spring?
Heres the code of my getMapping
#GetMapping("/get/varietynames/{searchString}/{languageCode}")
public List<CropVarietyNameSelectionDTO> getCropVarietySelectionDTOBySearchString(#PathVariable("searchString") #NotBlank #Pattern(regexp = "^[A-Za-z0-9]+$", message = "Search input only allows for letters and numbers")
#Size(min = 1, max = 40, message = "Search input cannot exceed 40 characters") String searchString, #PathVariable("languageCode") String languageCode){
return seedService.getCropVarietySelectionDTOBySearchString(searchString,languageCode);
}
Edit
Request on the frontend side is:
private basePath:string = this.apiUrl + "/seed";
getCropVarietySelectionDTOBySearchString(searchString: string):Observable<CropVarietyNameSelectionDTO[]>{
return (searchString && (searchString.trim().length > 0)) ? this.http.post<CropVarietyNameSelectionDTO[]>(this.basePath + "/get/varietynames/" + this.languageService.getCodeOfPreferredLanguage(), searchString) : Observable.of([]);
}
this.apiUrl = localhost:4200
That is not the correct way or option to use #PathVariable annotation which indicates that a method parameter should be bound to a URI template variable. You need to use #RequestParam annotation which indicates that a method parameter should be bound to a web request parameter. You can see this answer that is a #RequestParam vs #PathVariable
#GetMapping("/get/varietynames")
public List<CropXXXDTO> getXXXXXhString(#RequestParam #NotBlank
#Pattern(regexp = "^xx+$", message = "xxxxx")
#Size(min = 1, max = 40, message = "xxxxx") String searchString,
#RequestParam(required = false, defaultValue = "EN") String languageCode){
return seedService.getXXXXtring(searchString, languageCode);
}
Then you can check the URL by following way:
/get/varietynames?searchString=XXXXX&languageCode=EN

Springboot controller request param for map always null

I'm trying to pass in a bunch of id's to create a filter.
The incoming request looks like (ignoring the pagination stuff, which works fine)
http://localhost:8080/news-items?filter%5B%5D=09c731de-7ed8-385d-849c-f4d6535137ab&filter%5B%5D=dd1ba187-2df9-3985-ad1c-a4cde2dfe669&modelPath=controller.newsItems&page=0&per_page=25
Where the filter param equals an ID, but there is a bunch of them, for example:
filter: [
"09c731de-7ed8-385d-849c-f4d6535137ab",
"dd1ba187-2df9-3985-ad1c-a4cde2dfe669"
],
I can't seem to collect the filters in the controller. At the moment I have
public String getFeeds(#RequestParam(value = "filter", required = false) MultiValueMap<String, String> filter, #RequestParam(value = "page", required = false) int page, #RequestParam(value = "per_page", required = false) int perPage) {
log.info("Filter: {}", filter);
}
However filter is always null. I've tried using a String rather than a map but that is also always null.
How do I go about accepting an unknown number of params in this manner? I get the feeling this is really simple but I'm just missing the obvious...
Turns out it was simple like I thought. When using a Map in the #RequestParam it takes all the incoming params, regardless of what they are.
So from what I can tell the correct solution is to do something like
#GetMapping(produces = APPLICATION_JSON)
public String getFeeds(#RequestParam MultiValueMap<String, String> params) {
params.forEach(//something);
}
I think what you are looking for is just an Array or a List, something like below :
public String getFeeds(#RequestParam(value = "filter", required = false) List<String> filters) { ... }

Reason for LinqToQuerystring attibute: LinqToQueryable

There is an attribute (LinqToQueryable) in the webapi package for LinqToQuerystring, but I wasn't able to find a good explanation how it works.
Does it modify the returning results?
Does it enable LinqToQuerystring? (but how do I get the querystring then?)
Other?
As it turns out, the attribute [LinqToQueryable] filters/orders/... the Queryable result when returning.
To get the querystring in webapi2 I created an extension method:
public static class RequestExtensions
{
public static string GetQueryString(this HttpRequestMessage request)
{
return request.GetQueryNameValuePairs().Select(x => x.Key + "=" + x.Value).Aggregate((i, j) => i + "&" + j);
}
}
But I suspect this could also be done with ODataRequestOptions as parameter for the (webapi)method instead of using the querystring. The only problem is I don't know how to convert this to a string.
The advantage for this ODataRequestOption is that you can easily couple validators.

Resources