diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationReactiveIntegrationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationReactiveIntegrationTests.java index 1133c0bcb1f9..f469cca47725 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationReactiveIntegrationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mustache/MustacheAutoConfigurationReactiveIntegrationTests.java @@ -107,7 +107,7 @@ public String layout(Model model) { @RequestMapping(path = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public String sse(Model model) { model.addAttribute("time", new Date()); - model.addAttribute("async.message", + model.addAttribute("async:message", Flux.just("Hello", "World") .delayElements(Duration.ofMillis(10))); model.addAttribute("title", "Hello App"); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/resources/mustache-templates/sse.html b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/mustache-templates/sse.html index 8d0b96b19342..da10c1581366 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/resources/mustache-templates/sse.html +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/mustache-templates/sse.html @@ -1,7 +1,7 @@ -{{#async.message}} +{{#async:message}} event: message -{{#ssedata}} +{{#sse:data}}

Title

{{{.}}} -{{/ssedata}} -{{/async.message}} +{{/sse:data}} +{{/async:message}} diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 492c7445ebdc..e722309985a6 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -3038,23 +3038,23 @@ There are some special features of the `MustacheView` that make it suitable for ===== Progressive Rendering -A model element of type `Publisher` will be left in the model (instead of expanding it before the view is rendered), if its name starts with "async." or "async:". The `View` is then rendered and flushed to the HTTP response as soon as each element is published. Browsers are really good at rendering partially complete HTML, so the flux elements will most likely be visible to the user as soon as they are available. This is useful for rendering the "main" content of a page if it is a list or a table, for instance. +A model element of type `Publisher` will be left in the model (instead of expanding it before the view is rendered), if its name starts with "async:". The `View` is then rendered and flushed to the HTTP response as soon as each element is published. Browsers are really good at rendering partially complete HTML, so the flux elements will most likely be visible to the user as soon as they are available. This is useful for rendering the "main" content of a page if it is a list or a table, for instance. ===== Sserver Sent Event (SSE) Support -To render a `View` with content type `text/event-stream` you need a model element of type `Publisher`, and also a template that includes that element (probably starts and ends with it). There is a convenience Lambda (`ssedata`) added to the model for you that prepends every line with `data:` - you can use it if you wish to simplify the rendering of the data elements. Two new lines are added after each item in `{{#ssedata}}`. E.g. with an element called `flux.events` of type `Flux`: +To render a `View` with content type `text/event-stream` you need a model element of type `Publisher`, and also a template that includes that element (probably starts and ends with it). There is a convenience Lambda (`ssedata`) added to the model for you that prepends every line with `data:` - you can use it if you wish to simplify the rendering of the data elements. Two new lines are added after each item in `{{#sse:data}}`. E.g. with an element called `async:events` of type `Flux`: ``` -{{#async.events}} +{{#async:events}} event: message id: {{id}} -{{#ssedata}} +{{#sse:data}}
Name: {{name}} Value: {{value}}
-{{/ssedata}} -{{/async.events}} +{{/sse:data}} +{{/async:events}} ``` the output will be diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/result/view/MustacheView.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/result/view/MustacheView.java index 832132c31744..e6f2df67f618 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/result/view/MustacheView.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/result/view/MustacheView.java @@ -114,7 +114,7 @@ protected Mono renderInternal(Map model, MediaType content Map map; if (sse) { map = new HashMap<>(model); - map.put("ssedata", new SseLambda()); + map.put("sse:data", new SseLambda()); } else { map = model; @@ -151,7 +151,7 @@ private Template compile(Resource resource) { protected Mono resolveAsyncAttributes(Map model) { Map result = new HashMap<>(); for (String key : model.keySet()) { - if (!key.startsWith("async.") && !key.startsWith("async:")) { + if (!key.startsWith("async:")) { result.put(key, model.get(key)); } else { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/result/view/MustacheViewTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/result/view/MustacheViewTests.java index 894db16ccc4f..b8ece1ba23db 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/result/view/MustacheViewTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/result/view/MustacheViewTests.java @@ -90,7 +90,7 @@ public void viewResolvesSseManual() { view.setUrl(this.templateUrl + "/sse.html"); view.setCharset(StandardCharsets.UTF_8.displayName()); view.setApplicationContext(this.context); - view.render(Collections.singletonMap("async.value", Flux.just("World", "Spring")), + view.render(Collections.singletonMap("async:value", Flux.just("World", "Spring")), MediaType.TEXT_EVENT_STREAM, this.exchange).block(Duration.ofSeconds(30)); assertThat(this.exchange.getResponse().getBodyAsString() .block(Duration.ofSeconds(30))).isEqualTo( @@ -106,7 +106,7 @@ public void viewResolvesSseData() { view.setUrl(this.templateUrl + "/ssedata.html"); view.setCharset(StandardCharsets.UTF_8.displayName()); view.setApplicationContext(this.context); - view.render(Collections.singletonMap("async.value", Flux.just("World", "Spring")), + view.render(Collections.singletonMap("async:value", Flux.just("World", "Spring")), MediaType.TEXT_EVENT_STREAM, this.exchange) .block(Duration.ofSeconds(300)); assertThat(this.exchange.getResponse().getBodyAsString() diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/result/view/sse.html b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/result/view/sse.html index 449615cae3fa..fe5765eabd5b 100644 --- a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/result/view/sse.html +++ b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/result/view/sse.html @@ -1,6 +1,6 @@ -{{#async.value}} +{{#async:value}} event: message data: {{.}} -{{/async.value}} \ No newline at end of file +{{/async:value}} \ No newline at end of file diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/result/view/ssedata.html b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/result/view/ssedata.html index 938d0eae52a5..58038b18260d 100644 --- a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/result/view/ssedata.html +++ b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/web/reactive/result/view/ssedata.html @@ -1,6 +1,6 @@ -{{#async.value}} +{{#async:value}} event: message -{{#ssedata}} +{{#sse:data}} {{.}} -{{/ssedata}} -{{/async.value}} \ No newline at end of file +{{/sse:data}} +{{/async:value}} \ No newline at end of file