In Spring Boot, for Webflux projects, we request a stream of data by sending a header - "Accept: application/stream+json" in the HTTP Request.
If we send, "Accept: application/json", we get get a valid Json.
In Micronaut, however, if I send "Accept: application/stream+json", it throws an error.
{
"message": "Specified Accept Types [application/x-json-stream] not supported. Supported types: [application/json]",
"_links": {
"self": {
"href": "/carts/reactive",
"templated": false
}
}
}
What is the equivalent of "Accept: application/stream+json" in Micronaut?
What is the equivalent of "Accept: application/stream+json" in Micronaut?
As already mentioned in the comments, it's application/x-json-stream
. (Sadly there's no one established standard for the content type for streaming json, at least not yet.)
The question here is to how the client can control the response type - Json/stream. You are using produces = {MediaType.APPLICATION_JSON_STREAM, which means the return type is always stream. In spring boot, we can use Accept header to control what response type we want. I was expecting the same behaviour from Micronaut.
Micronaut can do that too - you can pass more than one value to the produces
parameter, and it will return either streamed or standard JSON accordingly:
@Get(value = "/", produces = {MediaType.APPLICATION_JSON_STREAM, MediaType.APPLICATION_JSON})
public Flux<Foo> getFoos() {
return Flux.range(1, 3).map(i -> new Foo("Number " + i));
}
@Value
class Foo {
private String content;
}
Then we can query the endpoint with either application/x-json-stream
to retrieve a JSON stream:
> curl localhost:8080 -H "Accept: application/x-json-stream"
{"content":"Number 1"}{"content":"Number 2"}{"content":"Number 3"}
...or plain application/json
to retrieve a standard JSON array:
> curl localhost:8080 -H "Accept: application/json"
[{"content":"Number 1"},{"content":"Number 2"},{"content":"Number 3"}]
If you want more custom control over the behaviour for each type of accept header, then you can just define separate controller methods entirely:
@Get(value = "/", produces = MediaType.APPLICATION_JSON_STREAM)
public Flux<Foo> getFoosStream() {
return Flux.range(1, 3).map(i -> new Foo("Reactive " + i));
}
@Get(value = "/", produces = MediaType.APPLICATION_JSON)
public List<Foo> getFoosStandard() {
return List.of(new Foo("Standard 1"), new Foo("Standard 2"), new Foo("Standard 3"));
}
...and depending on the header you send, a different method will be executed (as above you'll be able to see the difference with a standard curl command.)