Spring MVC: Complex object as GET @RequestParam
I will add some short example from me.
The DTO class:
public class SearchDTO {
private Long id[];
public Long[] getId() {
return id;
}
public void setId(Long[] id) {
this.id = id;
}
// reflection toString from apache commons
@Override
public String toString() {
return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
Request mapping inside controller class:
@RequestMapping(value="/handle", method=RequestMethod.GET)
@ResponseBody
public String handleRequest(SearchDTO search) {
LOG.info("criteria: {}", search);
return "OK";
}
Query:
http://localhost:8080/app/handle?id=353,234
Result:
[http-apr-8080-exec-7] INFO c.g.g.r.f.w.ExampleController.handleRequest:59 - criteria: SearchDTO[id={353,234}]
I hope it helps :)
UPDATE / KOTLIN
Because currently I'm working a lot of with Kotlin if someone wants to define similar DTO the class in Kotlin should have the following form:
class SearchDTO {
var id: Array<Long>? = arrayOf()
override fun toString(): String {
// to string implementation
}
}
With the data
class like this one:
data class SearchDTO(var id: Array<Long> = arrayOf())
the Spring (tested in Boot) returns the following error for request mentioned in answer:
"Failed to convert value of type 'java.lang.String[]' to required type 'java.lang.Long[]'; nested exception is java.lang.NumberFormatException: For input string: \"353,234\""
The data class will work only for the following request params form:
http://localhost:8080/handle?id=353&id=234
Be aware of this!
Since the question on how to set fields mandatory pops up under each post, I wrote a small example on how to set fields as required:
public class ExampleDTO {
@NotNull
private String mandatoryParam;
private String optionalParam;
@DateTimeFormat(iso = ISO.DATE) //accept Dates only in YYYY-MM-DD
@NotNull
private LocalDate testDate;
public String getMandatoryParam() {
return mandatoryParam;
}
public void setMandatoryParam(String mandatoryParam) {
this.mandatoryParam = mandatoryParam;
}
public String getOptionalParam() {
return optionalParam;
}
public void setOptionalParam(String optionalParam) {
this.optionalParam = optionalParam;
}
public LocalDate getTestDate() {
return testDate;
}
public void setTestDate(LocalDate testDate) {
this.testDate = testDate;
}
}
//Add this to your rest controller class
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String testComplexObject (@Valid ExampleDTO e){
System.out.println(e.getMandatoryParam() + " " + e.getTestDate());
return "Does this work?";
}
You can absolutely do that, just remove the @RequestParam
annotation, Spring will cleanly bind your request parameters to your class instance:
public @ResponseBody List<MyObject> myAction(
@RequestParam(value = "page", required = false) int page,
MyObject myObject)