Binding from Multiple Bindable values

Instead of binding just Query values, it is also possible to bind any Bindable value to POJO (e.g. when you want to bind HttpRequest, @PathVariable, @QueryValue and @Header to single POJO). This can be achieved with @RequestBean annotation and custom Bean class that has fields with Bindable annotations or fields that can be bound by type (e.g. HttpRequest, BasicAuth, Authentication etc.). For example:

Binding Bindable values to POJO

  1. @Controller("/api")
  2. public class MovieTicketController {
  3. // You can also omit query parameters like:
  4. // @Get("/movie/ticket/{movieId}
  5. @Get("/movie/ticket/{movieId}{?minPrice,maxPrice}")
  6. public HttpStatus list(@Valid @RequestBean MovieTicketBean bean) {
  7. return HttpStatus.OK;
  8. }
  9. }

Binding Bindable values to POJO

  1. @Controller("/api")
  2. class MovieTicketController {
  3. // You can also omit query parameters like:
  4. // @Get("/movie/ticket/{movieId}
  5. @Get("/movie/ticket/{movieId}{?minPrice,maxPrice}")
  6. HttpStatus list(@Valid @RequestBean MovieTicketBean bean) {
  7. return HttpStatus.OK
  8. }
  9. }

Binding Bindable values to POJO

  1. @Controller("/api")
  2. open class MovieTicketController {
  3. // You can also omit query parameters like:
  4. // @Get("/movie/ticket/{movieId}
  5. @Get("/movie/ticket/{movieId}{?minPrice,maxPrice}")
  6. open fun list(@Valid @RequestBean bean: MovieTicketBean): HttpStatus {
  7. return HttpStatus.OK
  8. }
  9. }

Bean definition

  1. @Introspected
  2. public class MovieTicketBean {
  3. private HttpRequest<?> httpRequest;
  4. @PathVariable
  5. private String movieId;
  6. @Nullable
  7. @QueryValue
  8. @PositiveOrZero
  9. private Double minPrice;
  10. @Nullable
  11. @QueryValue
  12. @PositiveOrZero
  13. private Double maxPrice;
  14. public MovieTicketBean(HttpRequest<?> httpRequest, String movieId, Double minPrice, Double maxPrice) {
  15. this.httpRequest = httpRequest;
  16. this.movieId = movieId;
  17. this.minPrice = minPrice;
  18. this.maxPrice = maxPrice;
  19. }
  20. public HttpRequest<?> getHttpRequest() {
  21. return httpRequest;
  22. }
  23. public String getMovieId() {
  24. return movieId;
  25. }
  26. @Nullable
  27. public Double getMaxPrice() {
  28. return maxPrice;
  29. }
  30. @Nullable
  31. public Double getMinPrice() {
  32. return minPrice;
  33. }
  34. }

Bean definition

  1. @Introspected
  2. class MovieTicketBean {
  3. private HttpRequest<?> httpRequest
  4. @PathVariable
  5. String movieId
  6. @Nullable
  7. @QueryValue
  8. @PositiveOrZero
  9. Double minPrice
  10. @Nullable
  11. @QueryValue
  12. @PositiveOrZero
  13. Double maxPrice
  14. }

Bean definition

  1. @Introspected
  2. data class MovieTicketBean(val httpRequest: HttpRequest<Any>,
  3. @field:PathVariable val movieId: String,
  4. @field:QueryValue @field:PositiveOrZero @field:Nullable val minPrice: Double,
  5. @field:QueryValue @field:PositiveOrZero @field:Nullable val maxPrice: Double)

Bean class has to be introspected with @Introspected. It can be one of:

  1. Mutable Bean class with setters and getters

  2. Immutable Bean class with getters and all argument constructor (or @Creator annotation on a constructor or static method). Arguments of constructor have to match field names so object can be constructed without reflection.

Since Java does not retain argument names in the byte code, you have to compile code with -parameters in case you want to use Immutable Bean class from another Jar. Another option is to extend Bean class in your source.