#RequestParam is ignoring variables with a pipe - spring

I am calling `/path/to/search/mytable?filter=field1|value1,field2|value2
#RequestMapping(value = "/path/do/{blar}/{foo}", method = RequestMethod.GET)
public List<MyType> getTableData(#PathVariable("blar") String blar,
#PathVariable("foo") String foo,
#RequestParam(name= "filter", required = false) String filter,
#RequestParam(name= "sort", required = false) String sort) {
but for some reason having a pipe "|" in the text means that it doesn't get matched. Can someone help me understand what is going on?
I tried converting filter to String[] but if there is an pipe the whole thing is ignored and I get 400 back from the service.
Any help would be great.

Related

How to allow specific words using javax.validation.constraints.Pattern?

I would like to use javax.validation.constraints.Pattern for validation. The text should not be none or others.
Allowed Examples:
something
word
NOT allowed:
none
others
I am trying around but I dont catch my issue. Something like:
#NotNull
#Pattern(regexp = "(^none)")
String countryValue;
Thanks for your hint.
UPDATE:
As Anish said with the online regex validator, the regex ^(?!others|none) should be correct. But Spring-MVC still denied. Is there a special syntax to be used? I give more code to have a bigger picture:
Controller:
#PostMapping
public String post(#ModelAttribute #Valid DisclaimerFormDto disclaimerForm, BindingResult errors, ModelMap modelMap) {
if(errors.hasErrors()) {
errors.getAllErrors().forEach(System.out::println);
return "redirect:/disclaimer";
}
return "redirect:/product";
}
FormDto (with changes mentioned from Anish):
#Data
#ToString
public class DisclaimerFormDto {
#NotNull
#Pattern(regexp = "^(?!others|none)")
String countryValue;
}
Output of BindingResult:
Field error in object 'disclaimerFormDto' on field 'countryValue': rejected value [none]; codes [Pattern.disclaimerFormDto.countryValue,Pattern.countryValue,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [disclaimerFormDto.countryValue,countryValue]; arguments []; default message [countryValue],[Ljavax.validation.constraints.Pattern$Flag;#59374db6,^(?!(none|others)$).*$]; default message [muss auf Ausdruck "^(?!(none|others)$).*$" passen]
Try with this :
#NotNull
// #Pattern(regexp = "^(?!others|none)")
// updated to take any kind of string to match.
#Pattern(regexp = "^((?!(none|others)).)*$")
private String countryValue;
Check this regex example here: ^((?!(none|others)).)*$
Test case 1 : String like "abc"
Screenshot :
Test case 2 : Strings like "abc others", "abc none", "none" or "words"

#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) { ... }

Spring Same URL Different Request Parameter

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

Why am I getting "400 Bad Request" for this URL in Spring MVC?

The following URL results in a "400 Bad Request":
http://localhost:8080/springdata_web/rest/errors/test?from=2014-05-25T00:00:00.000Z&to=2014-05-27T00:00:00.000Z
The matching #RequestMapping is below. I can see I am definitely hitting this method because I see the Sysout line in the console using the following URL for example:
http://localhost:8080/springdata_web/rest/errors/test?from=&to=
So I guess it's to do with the Date type and Spring not accepting the format I'm passing in the request params but I don't see why.
#RequestMapping(value = "/test",
method = RequestMethod.GET,
produces = "application/json")
#ResponseBody
public Resource<List<ErrorsDTOEntity>> getAllErrors(
#RequestParam(value = "from", required = true) #DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Date from,
#RequestParam(value = "to", required = true) #DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Date to) {
System.out.println("getAllErrors(Date, Date);");
List<ErrorsDTOEntity> services = errorsDAO.getAllErrors(from, to);
Resource<List<ErrorsDTOEntity>> toReturn = new Resource<List<ErrorsDTOEntity>>(services);
toReturn.add(linkTo(methodOn(ErrorsController.class).getAllErrors(from, to)).withSelfRel());
return toReturn;
}
It was the format of the date in the URL. This URL-encoded request works:
http://localhost:8080/springdata_web/rest/errors/test?from=2014-05-25T00%3A00%3A00.000%2B0000&to=2014-05-27T00%3A00%3A00.000%2B0000
The date pattern you are passing for ( from / to) is not matching. Underltying pattern for is DateTimeFormat.ISO DATE_TIME:
yyyy-MM-dd'T'hh:mm:ss.SSSZ
so example time is as below :
2000-10-31T01:30:00.000-05:00
try whether following request work:
test?from=2000-10-31T01:30:00.000-05:00&to=2000-10-31T01:30:00.000-05:00
Spring Docs says :

Resources