how to validate size of pathvariable that is string type to be exact value in spring boot? - spring-boot

How I can validate size of path variable to be exact size? Variable is string type.
#GetMapping("getLegal/{legalCode}")
public ResponseEntity getLegalFrom(
#PathVariable #Size(min = 9,max = 9) String legalCode) {
return sharedService.getLegal(legalCode);
}

You can use #PathVariable annotation with Regular Expressions. To do that Change your #GetMapping to
#GetMapping("getLegal/{legalCode:[a-zA-Z0-9]{9,9}}}")

Related

Spring multiple #PathVariable failure

when I try calling this endpoint with just this endpoint: /api/v1/data/{provider}/{subject} (I removed #pathvariable dataset parameter when I got rid of the dataset path) I am able to successfully call my API. However, when I add an additional pathvariable (dataset in this case), I can't seem to hit my endpoint anymore. Is there some restriction on number of path variables? Not sure what I'm doing wrong.
#GetMapping("/api/v1/data/{provider}/{subject}/{dataset}")
public List<List<String>> getEDXDatasetHead(
#PathVariable final String provider,
#PathVariable final String subject,
#PathVariable final String dataset,
#RequestParam(required = false, value = "date") final String date
)
https://localhost:8443/api/v1/data/testprovider/testsubject/testdataset
#GetMapping("/api/v1/data/{provider}/{subject}/{dataset}")
There is no particular limit on number of PathVariable that you can add to a method.
But if you want to call your API with many different number of PathVariables you need to add a method for each of them, otherwise spring is not able to understand that you are calling the same method with a shorter number of path variables:
#GetMapping("/api/v1/data/{provider}/{subject}/{dataset}")
public List<List<String>> getEDXDatasetHead(
#PathVariable final String provider,
#PathVariable final String subject,
#PathVariable final String dataset,
#RequestParam(required = false, value = "date") final String date
)
...
#GetMapping("/api/v1/data/{provider}/{subject}")
public List<List<String>> getEDXDatasetHead(
#PathVariable final String provider,
#PathVariable final String subject,
#RequestParam(required = false, value = "date") final String date
)
...
#GetMapping("/api/v1/data/{provider}")
public List<List<String>> getEDXDatasetHead(
#PathVariable final String provider,
#RequestParam(required = false, value = "date") final String date
)
Note: spring doesn't have a particular limitation on the number of PathVariable that can be used in a method. But there are limitations on:
the size of the generated url (if too long not all browser handle it correctly)
the format of the url (check if you url encoded the path variables when you build the url on the client side)

Wrapper type Path variable won't accept null value - Spring Boot

This is our Controller
#GetMapping(path = "/getUsersForHierarchy/{entity}/{hierId}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<UserInfo>> getUsersForHierarchy(#PathVariable(name = "entity", required = true) int entity,
#PathVariable(name = "hierId", required = true) Integer hierId) {
..................
..................
}
We are expecting two Path variables, one is of int type (entity) and the other is Integer type (hierId). hierId can be null or any numeric value and thats why its kept as Wrapper. But its gives error while firing the request like this
http://localhost:5010/v1/accountholder/userinfo/getUsersForHierarchy/5/null
Now a Wrapper is meant to accept null values, but we are getting error like this
Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; nested exception is java.lang.NumberFormatException: For input string: "null"
If we change Integer to String the call is getting inside the controller, but for further proceedings we need to use Integer.
We looked into this Spring MVC #Path variable with null value, and tried invoking the API with change in URL like this
http://localhost:5010/v1/accountholder/userinfo/getUsersForHierarchy/5/blaaa/null, but the error is still the same.
What should be done?
If you want it to be nullable you can achieve it with the following. First of all, if it's nullable the required property should be false. Also, considering required = true is the default, there's no need to specify it and if the name of the path variable matches the name of the corresponding variable you don't have to specify the name either.
#GetMapping(value = {
"/getUsersForHierarchy/{entity}/",
"/getUsersForHierarchy/{entity}/{hierId}"
},
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<UserInfo>> getUsersForHierarchy(
#PathVariable int entity,
#PathVariable(required = false) Integer hierId) {
}
Considering I don't like to deliberately allow a null value into the application, another nice to have could be having the hierId required with type Optional, so the following will give you a Optional.empty when just /getUsersForHierarchy/123/ is invoked and hierId is null. Otherwise it will populate the optional when hierId is provided invoking /getUsersForHierarchy/123/321:
#GetMapping(value = {
"/getUsersForHierarchy/{entity}/",
"/getUsersForHierarchy/{entity}/{hierId}"
},
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<UserInfo>> getUsersForHierarchy(
#PathVariable int entity,
#PathVariable Optional<Integer> hierId) {
}

#Valid for long data type is not working for mandatory check

I have the below input class and when i trigger the api without 'interactionId' param in the input,
I expect validation error message "interactionId cannot be empty" but the validation passes through which i guess could be due to the fact that interactionId has a default value of 0.
Can someone pls. help to enforce this validation on the 'long' parameter when its not given in input?
with #NotEmpty for the customerId param, its working as expected. Using #NotEmpty for the long param "interactionId" is throwing a different error that #notempty cannot be used for long.
public class Input {
#NotEmpty(message = "customerId cannot be empty")
private String customerId;
#Valid
#NotNull(message = "interactionId cannot be empty")
private long interactionId;
// setters and getters
}
my controller class:
#RestController
public class Controller {
#PostMapping(value="/detailed-customer-transaction", produces =
MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<Object> detailTransactions(#Valid #RequestBody Input
params)
{
return new ResponseEntity<>(Dao.detailTransactions(params), HttpStatus.OK);
}
Above issues is resolved after changing to Long instead of long.
Query #2
I need another help. I have a String input param which takes date-time format in below format. Given its a string parameter, how can i validate for the pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
long should be Long, because long is a primary type in java, not an object, so Long is an object that can be checked whether it is null

Thymeleaf add multiple parameters to URL in one go

Given I have MVC endpoint with mapping:
#RequestMapping
public String eventHistory(final Model model,
#PageableDefault(sort = {"id"}, direction = DESC) final Pageable pageable,
final EventHistoryFilter eventHistoryFilter) {
...
model.addAttribute("eventHistoryFilter", eventHistoryFilter);
}
where EventHistoryFilter is:
final class EventHistoryFilter {
private Long eventId;
private String eventType;
private String eventDateFrom;
private String eventDateTo;
...
}
and in thymeleaf template I would like to construct URL with parameters, e.g.:
th:href="#{/event-history(page=${page.number-1},eventId=${eventHistoryFilter.eventId},eventType=${eventHistoryFilter.eventType},eventDateFrom=${eventHistoryFilter.eventDateFrom},eventDateTo=${eventHistoryFilter.eventDateTo})}"
How can I add multiple parameters into URL in one go?
I didn't find it here: https://www.thymeleaf.org/doc/articles/standardurlsyntax.html#adding-parameters
I'd like to avoid specifying each parameter one by one.
EDIT:
I tried to use https://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html#building-uris-to-controllers
String url = MvcUriComponentsBuilder.fromMappingName("EHE#eventHistory").arg(2, eventHistoryFilter).build();
but resolved URL doesn't contain any request parameters.
and thymeleaf counterpart:
th:href="${#mvc.url('EHE#eventHistory').arg(2,__${eventHistoryFilter}__).build()}"
fails during evaluation.

How to handle a request with multiple parameters on Spring-MVC

I am sending following request that need to be handled by Spring-MVC but it does not.
http://localhost:2001/MyProject/flights/find?origin=LAX&destination=WA&departure=&arrival=&return=false
Code
#Controller
#RequestMapping("/flights")
public class FlightController {
#RequestMapping(value = "/find?origin={origin}&destination={destination}&departure={departure}&arrival={arrival}&return={return}", method = RequestMethod.GET)
public String findFlight(#PathVariable String origin,
String destination, Date departure, Date arrival, boolean return) {
That is not the correct way (or place) to use #PathVariable. You need to use #RequestParam.
#Controller
#RequestMapping("/flights")
public class FlightController {
#RequestMapping("/find")
public String findFlight(#RequestParam String origin
, #RequestParam String destination
, #RequestParam(required = false) Date departure
, #RequestParam(required = false) Date arrival
, #RequestParam(defaultValue = "false", required = false, value = "return") Boolean ret) { ... }
}
Note that return is a keyword in Java so you cannot use it as a method parameter name.
You will also have to add a java.beans.PropertyEditor for reading the dates because the dates will (presumably) be in a specific format.
Try this, may be it works:
#RequestMapping("/find")
public String findFlight(#RequestParam("origin") String origin
, #RequestParam("destination") String destination,....

Resources