6.12.1 Using the @Body Annotation

To parse the request body, you first need to indicate to Micronaut the parameter which will receive the data. This is done with the Body annotation.

The following example implements a simple echo server that echos the body sent in the request:

Using the @Body annotation

  1. import io.micronaut.http.HttpResponse;
  2. import io.micronaut.http.MediaType;
  3. import io.micronaut.http.MutableHttpResponse;
  4. import io.micronaut.http.annotation.Body;
  5. import io.micronaut.http.annotation.Controller;
  6. import io.micronaut.http.annotation.Post;
  7. import io.reactivex.Flowable;
  8. import io.reactivex.Single;
  9. import javax.validation.constraints.Size;
  10. @Post(value = "/echo", consumes = MediaType.TEXT_PLAIN) (1)
  11. String echo(@Size(max = 1024) @Body String text) { (2)
  12. return text; (3)
  13. }

Using the @Body annotation

  1. import io.micronaut.http.MediaType
  2. import io.micronaut.http.MutableHttpResponse
  3. import io.micronaut.http.annotation.Body
  4. import io.micronaut.http.annotation.Controller
  5. import io.micronaut.http.annotation.Post
  6. import io.reactivex.Flowable
  7. import io.reactivex.Single
  8. import javax.validation.constraints.Size
  9. @Post(value = "/echo", consumes = MediaType.TEXT_PLAIN) (1)
  10. String echo(@Size(max = 1024) @Body String text) { (2)
  11. text (3)
  12. }

Using the @Body annotation

  1. import io.micronaut.http.HttpResponse
  2. import io.micronaut.http.MediaType
  3. import io.micronaut.http.MutableHttpResponse
  4. import io.micronaut.http.annotation.Body
  5. import io.micronaut.http.annotation.Controller
  6. import io.micronaut.http.annotation.Post
  7. import io.reactivex.Flowable
  8. import io.reactivex.Single
  9. import javax.validation.constraints.Size
  10. @Controller("/receive")
  11. open class MessageController {
  12. @Post(value = "/echo", consumes = [MediaType.TEXT_PLAIN]) (1)
  13. open fun echo(@Size(max = 1024) @Body text: String): String { (2)
  14. return text (3)
  15. }
  16. }
1The Post annotation is used with a MediaType of text/plain (the default is application/json).
2The Body annotation is used with a javax.validation.constraints.Size that limits the size of the body to at most 1MB. This constraint does not limit the amount of data read/buffered by the server.
3The body is returned as the result of the method

Note that reading the request body is done in a non-blocking manner in that the request contents are read as the data becomes available and accumulated into the String passed to the method.

The micronaut.server.maxRequestSize setting in application.yml will limit the size of the data (the default maximum request size is 10MB) read/buffered by the server. @Size is not a replacement for this setting.

Regardless of the limit, for a large amount of data accumulating the data into a String in-memory may lead to memory strain on the server. A better approach is to include a Reactive library in your project (such as RxJava 2.x, Reactor or Akka) that supports the Reactive streams implementation and stream the data it becomes available:

Using RxJava 2 to Read the request body

  1. @Post(value = "/echo-flow", consumes = MediaType.TEXT_PLAIN) (1)
  2. Single<MutableHttpResponse<String>> echoFlow(@Body Flowable<String> text) { (2)
  3. return text.collect(StringBuffer::new, StringBuffer::append) (3)
  4. .map(buffer ->
  5. HttpResponse.ok(buffer.toString())
  6. );
  7. }

Using RxJava 2 to Read the request body

  1. @Post(value = "/echo-flow", consumes = MediaType.TEXT_PLAIN) (1)
  2. Single<MutableHttpResponse<String>> echoFlow(@Body Flowable<String> text) { (2)
  3. return text.collect({ x -> new StringBuffer()}, { StringBuffer sb, String s -> sb.append(s)}) (3)
  4. .map({ buffer ->
  5. HttpResponse.ok(buffer.toString())
  6. });
  7. }

Using RxJava 2 to Read the request body

  1. @Post(value = "/echo-flow", consumes = [MediaType.TEXT_PLAIN]) (1)
  2. open fun echoFlow(@Body text: Flowable<String>): Single<MutableHttpResponse<String>> { (2)
  3. return text.collect({ StringBuffer() }, { obj, str -> obj.append(str) }) (3)
  4. .map { buffer -> HttpResponse.ok(buffer.toString()) }
  5. }
1In this case the method is altered to receive and return an RxJava 2.x Flowable type
2A Single is returned so that Micronaut will only emit the response once the operation completes without blocking.
3The collect method is used to accumulate the data in this simulated example, but it could for example write the data to logging service, database or whatever chunk by chunk
Body arguments of types that do not require conversion will cause Micronaut to skip decoding of the request!