Search code examples
kotlinmicronaut

Micronaut - Bind Get parameter object in Controller


I am implementing a Controller with a GET endpoint that is ought to receive the following request: /mycontroller?myDate=2019-05-01

My data class looks like this

data class MyData(
   val myDate: LocalDate
)

And my controller:

@Controller
class MyController {

  @Get("{?mydata*}")
  fun getMyEndpoint(mydata: MyData)...

}

Micronaut only binds the request in case I provide a default constructor for MyData, thus make myDate nullable or provide a default value - neither of those is what I wish to do.

Is there a way to get this working without providing the default constructor? Jackson e.g. can also handle it.

Thanks :)


Solution

  • Full working example:

    import io.micronaut.core.convert.ConversionContext
    import io.micronaut.core.convert.TypeConverter
    import io.micronaut.http.annotation.Controller
    import io.micronaut.http.annotation.Get
    import java.time.LocalDate
    import java.util.*
    import javax.inject.Singleton
    
    @Controller("/base")
    class MyController {
    
       @Get("/path")
       fun getMyEndpoint(myData: MyData) {
          println("MyData: $myData")
       }
    
    }
    
    data class MyData(
       val myDate: LocalDate
    )
    
    @Singleton
    class MyDataConverter : TypeConverter<String, MyData> {
       override fun convert(obj: String, targetType: Class<MyData>, context: ConversionContext?): Optional<MyData> =
          Optional.of(MyData(myDate = LocalDate.parse(obj)))
    }
    

    Pro tip: if you are using Jackson and Kotlin don't forget to include the jackson-module-kotlin dependency:

    compile "com.fasterxml.jackson.module:jackson-module-kotlin:$YourJacksonVersionHere"