6.13.1 Using the @Body Annotation
To parse the request body, you first indicate to Micronaut which parameter receives the data with the Body annotation.
The following example implements a simple echo server that echoes the body sent in the request:
Using the @Body annotation
import io.micronaut.http.HttpResponse;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Post;
import javax.validation.constraints.Size;
@Controller("/receive")
public class MessageController {
@Post(value = "/echo", consumes = MediaType.TEXT_PLAIN) (1)
String echo(@Size(max = 1024) @Body String text) { (2)
return text; (3)
}
}
Using the @Body annotation
import io.micronaut.http.HttpResponse
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Body
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import javax.validation.constraints.Size
@Controller("/receive")
class MessageController {
@Post(value = "/echo", consumes = MediaType.TEXT_PLAIN) (1)
String echo(@Size(max = 1024) @Body String text) { (2)
text (3)
}
}
Using the @Body annotation
import io.micronaut.http.HttpResponse
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Body
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import javax.validation.constraints.Size
@Controller("/receive")
open class MessageController {
@Post(value = "/echo", consumes = [MediaType.TEXT_PLAIN]) (1)
open fun echo(@Size(max = 1024) @Body text: String): String { (2)
return text (3)
}
}
1 | The Post annotation is used with a MediaType of text/plain (the default is application/json ). |
2 | The 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. |
3 | The 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 limits 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 Reactor
, RxJava
,or Akka
) that supports the Reactive streams implementation and stream the data it becomes available:
Using Reactive Streams to Read the request body
import io.micronaut.http.HttpResponse;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Post;
import javax.validation.constraints.Size;
@Controller("/receive")
public class MessageController {
@Post(value = "/echo-publisher", consumes = MediaType.TEXT_PLAIN) (1)
@SingleResult
Publisher<HttpResponse<String>> echoFlow(@Body Publisher<String> text) { (2)
return Flux.from(text)
.collect(StringBuffer::new, StringBuffer::append) (3)
.map(buffer -> HttpResponse.ok(buffer.toString()));
}
}
Using Reactive Streams to Read the request body
import io.micronaut.http.HttpResponse
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Body
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import javax.validation.constraints.Size
@Controller("/receive")
class MessageController {
@Post(value = "/echo-publisher", consumes = MediaType.TEXT_PLAIN) (1)
@SingleResult
Publisher<HttpResponse<String>> echoFlow(@Body Publisher<String> text) { (2)
return Flux.from(text)
.collect({ x -> new StringBuffer() }, { StringBuffer sb, String s -> sb.append(s) }) (3)
.map({ buffer -> HttpResponse.ok(buffer.toString()) });
}
}
Using Reactive Streams to Read the request body
import io.micronaut.http.HttpResponse
import io.micronaut.http.MediaType
import io.micronaut.http.annotation.Body
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Post
import javax.validation.constraints.Size
@Controller("/receive")
open class MessageController {
@Post(value = "/echo-publisher", consumes = [MediaType.TEXT_PLAIN]) (1)
@SingleResult
open fun echoFlow(@Body text: Publisher<String>): Publisher<HttpResponse<String>> { (2)
return Flux.from(text)
.collect({ StringBuffer() }, { obj, str -> obj.append(str) }) (3)
.map { buffer -> HttpResponse.ok(buffer.toString()) }
}
}
1 | In this case the method is altered to receive and return an Publisher type. |
2 | This example uses Project Reactor and returns a single item. Because of that the response type is annotated also with SingleResult. Micronaut only emits the response once the operation completes without blocking. |
3 | The collect method is used to accumulate the data in this simulated example, but it could for example write the data to a logging service, database, etc. chunk by chunk |
Body arguments of types that do not require conversion cause Micronaut to skip decoding of the request! |