org.thymeleaf.spring5.context.webflux.IReactiveDataDriverContextVariable Maven / Gradle / Ivy
Show all versions of thymeleaf-spring5 Show documentation
/*
* =============================================================================
*
* Copyright (c) 2011-2018, The THYMELEAF team (http://www.thymeleaf.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* =============================================================================
*/
package org.thymeleaf.spring5.context.webflux;
import org.reactivestreams.Publisher;
import org.springframework.core.ReactiveAdapterRegistry;
/**
*
* Interface to be implemented by context variables wrapping asynchronous objects in the form
* of reactive data streams which are meant to drive the reactive-friendly execution of a
* template.
*
*
* The presence of a variable of this type in the context sets the engine into data-driven
* mode, and only one of these variables is allowed to appear in the context for template execution.
*
*
* Using Reactive Streams terminology, this makes Thymeleaf act as a {@link org.reactivestreams.Processor}, given
* it will be a {@link org.reactivestreams.Subscriber} to the data-driver stream, and at the same time a
* {@link org.reactivestreams.Publisher} of output buffers (usually containing HTML markup).
*
*
* Templates executed in data-driven mode are expected to contain some kind iteration
* on the data-driver variable, normally by means of a {@code th:each} attribute. This iteration
* should be unique. Also note that, if this iteration is not present (or it doesn't end up being
* executed due to template logic), it is not guaranteed that the data-driven stream will not
* be consumed anyway -at least partially- depending on the use that the specific server implementation might make
* of the Reactor's back-pressure mechanism.
*
*
* Data-driver context variables are required to be multi-valued.
* Being multi-valued does not mean to necessarily return more than one value,
* but simply to have the capability to do so. E.g. a {@link reactor.core.publisher.Flux} object will
* be considered multi-valued even if it publishes none or just one result, whereas a
* {@link reactor.core.publisher.Mono} object will be considered single-valued.
*
*
* The {@link #getBufferSizeElements()} property describes the size (in elements) of the buffers that
* will be created from the data-driver stream before triggering the execution of the template (for each buffer).
* Normally there is no need to execute the template engine and generate output for each element of data
* published by the data stream, so this buffering prevents Thymeleaf from executing more times than actually needed.
*
*
* The {@link ReactiveDataDriverContextVariable} class contains a sensible implementation of this interface,
* directly usable in most scenarios. Example use:
*
*
* @RequestMapping("/something")
* public String doSomething(final Model model) {
* final Publisher<Item> data = ...; // This has to be MULTI-VALUED (e.g. Flux)
* model.addAttribute("data", new ReactiveDataDriverContextVariable(data, 100));
* return "view";
* }
*
*
* And then at the template:
*
*
* <table>
* <tbody>
* <tr th:each="item : ${data}">
* <td th:text="${item}">some item...</td>
* </tr>
* </tbody>
* </table>
*
*
* @author Daniel Fernández
*
* @since 3.0.3
*
*/
public interface IReactiveDataDriverContextVariable {
/**
*
* Returns the reactive asynchronous object being wrapped, (perhaps) having been re-shaped into a
* {@link Publisher} stream.
*
*
* @param reactiveAdapterRegistry the Spring reactive adapter registry that should be used in order to transform
* other reactive implementations (RxJava, etc.) into
* {@link reactor.core.publisher.Flux}. Can be null (no adaptations will be
* available).
* @return the asynchronous object (as a {@link Publisher}).
*/
public Publisher