Thymeleaf add multiple parameters to URL in one go - spring

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.

Related

Creating custom requestParam in springboot controller

i have a use case where the user can send following params with get request
GET localhost/8080/users?filter=alex
OR
GET localhost/8080/users?suffixFilter=lex
OR
GET localhost/8080/users?prefixFilter=a
is it possible to add only one request param instead of 3 in controller
e.g.
instead of
#GetMapping("/users")
#ResponseBody
public String getFoos(#RequestParam String filter, #RequestParam String prefixFilter , #RequestParam String suffixFilter) {
return "ID: " + id;
}
is it possible to create a dynamic one which includes those three variantes? I was thinking creating class like this
public class FilterCreteria {
private String filter;
private String suffixFilter;
private String prefixFilter;
}
and then passing this to controller
#GetMapping("/users")
#ResponseBody
public String getFoos(#RequestParam FilterCreateria filter) {
return "ID: " + id;
}
the problem is if i send filter=alex the other attributes in the class FilterCreteria is null and i want to avoid this null.
What i searching for:
is there other way of making this possible?
if my suggestion is ok, how to avoid null attributes when the user only sends one queryparam like filter=alex?

Query parameters binding into DTO, how to ignore specific param?

Is there any good way to ignore some request query parameters from binding to DTO parameters?
#Data // setters and getters
class Dto {
private String param1;
private String param2;
}
#GetMapping("/hello-world")
#ResponseBody
public ResponseEntity<Dto> sayHello(Dto params)
{ ... }
I would like to exclude binding of specific param in such case.
After some research I can't find any solution for it, any help?

Spring MVC forward appending request parameter values comma separated when we have same parameter name for topRequest and forward request

Spring MVC forward appending request parameter values comma separated when we have same parameter name for topRequest and forward request
#RequestMapping(path = "/details")
public ModelAndView details(#ModelAttribute final DetailsForm detailsForm){
//DetailsForm contain a parameter called destinationId with value 1234
final ModelAndView mav = new ModelAndView();
//Some logic to get targeted destinationId (7890) using destinationId (1234) from detailForm
mav.setViewName("forward:/search?destinationId=7890");
return mav;
}
#RequestMapping(path = "/search")
public ModelAndView details(#ModelAttribute final SearchForm searchForm){
//Here I tried to get destinationId from model-attribute searchForm
final Integer destinationId = searchForm.getDestinationId();
//Then it returned me 1234,7890
}
Can someone please help me out how to resolve this. I want to get only 7890.
I am interested in the answer also. I also hit this problem hacked it by adding a method:
private String getLastPartFromFormValue(final String value) {
if (value == null)
return null;
String[] parts = value.split(",");
return parts[parts.length -1];
}
Just for sake of knowledge.
If you have a method, and you have a query param named thing and have an object annotated with #ModelAttribute and, in that object you have a field with the same name of your query param, you can expect that behavior.
For example:
#PostMapping(value = "/my-awesome-path")
public String myAwesomeMethod(
#RequestParam(name = "token", required = false) final String token,
#ModelAttribute("formData") final MyFormData formData) {
//class fields and members...
And, in the MyFormData you have this:
public class MyFormData{
private String token;
//other fields, getters and setters...
You will receive the query param token with the value duplicated and comma separated as well as in the MyFormData object.
The alternative is check the casuistic and change the parameter name or redesign if it's necessary.
In the example the query param name is changed like this:
#PostMapping(value = "/my-awesome-path")
public String myAwesomeMethod(
#RequestParam(name = "custom-token", required = false) final String customToken,
#ModelAttribute("formData") final MyFormData formData) {
//class fields and members...
And the values are not more duplicated nor comma separated.
Cheers.

Change #RequestBody object based on #PathVariable

Below is my application code
#RequestMapping(value = "app/{version}/register", method = RequestMethod.POST, consumes = "application/json")
#ResponseBody
public RegisterMemberResponse registerMember(#Valid #RequestBody RegisterMemberRequest request,#PathVariable Integer version){
return registerservice.register(request);
}
for app version 1 my RegisterMemberRequest class is
public class RegisterMemberRequest{
#NotNull
private String firstName;
#NotNull
private String lastName;
//gatter & setter...
}
and for app version 2 my request class is
public class LatestRegisterMemberRequest extends RegisterMemberRequest{
#NotNull
private String middleName;
//getter & setter...
}
so how i can i change my registerMember() method in such a way that i can serve both version 1 & 2 request uri.
If you want to hardcode the version number into the url (which I would not recommend), you could easily use two different controller methods with hardcoded paths like app/v1/register and app/v2/register.
Another way would be to use content negotiation and route the requests according to a given content-type, e.g. application/vnd+<YOURCOMPANY>.<DATATYPE_AND_VERSION>+json, also using separate rest controller methods annotated with #Consumes.
I think you can make use of Requestmapping-uri-templates-regex , version number will be the #PathVariable write your business logic to decide what should be the response body depends on pathvariable version.

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