org.thymeleaf.spring5.context.reactive.ReactiveLazyContextVariable Maven / Gradle / Ivy
Show all versions of thymeleaf-spring5 Show documentation
/*
* =============================================================================
*
* Copyright (c) 2011-2016, 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.reactive;
import java.util.Collections;
import org.reactivestreams.Publisher;
import org.springframework.core.ReactiveAdapterRegistry;
import org.thymeleaf.context.ILazyContextVariable;
import org.thymeleaf.context.LazyContextVariable;
import org.thymeleaf.util.Validate;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
*
* Implementation of the {@link org.thymeleaf.context.ILazyContextVariable} interface meant to contain
* a reactive data stream that should not be resolved until view is rendered.
*
*
* By being added to the context/model wrapped by an object of this class, reactive asynchronous objects will
* reach the execution phase of the view layer unresolved, and will only be resolved if they are really
* needed. So asynchronous variables that the template does not really need in the end (because template
* logic resolves in a way that doesn't make use of them) will never be consumed at all.
*
*
* Note that resolving this kind of objects means actually blocking and collecting
* its values.
*
*
* The reactive async object wrapped by this class will usually have the shape of an implementation of the
* {@link Publisher} interface, such as {@link reactor.core.publisher.Flux}. But other types of reactive
* artifacts are supported thanks to Spring's {@link org.springframework.core.ReactiveAdapterRegistry}
* mechanism.
*
*
* When lazily resolving these variables, this class mirrors the mechanism used by Spring for resolving
* asynchronous variables at the model of views:
*
*
* - Flux<T> or other multi-valued streams are resolved as
* List<T> so that they are iterable.
* - Mono<T> or other single-valued streams are resolved as
* T so that they are directly referenceable just like any other object.
*
*
* 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.
*
*
* Example use:
*
*
* @RequestMapping("/something")
* public String doSomething(final Model model) {
*
* final Publisher<Item> async = ...;
*
* // If 'async' is multi-valued, 'someData' will be usable as if it were of type List<Item>
* // If 'async' is single-valued, 'someData' will be usable as if it were of type Item
* model.addAttribute("someData", new ReactiveLazyContextVariable(async));
*
* return "view";
*
* }
*
*
* This class is NOT thread-safe. Thread-safety is not a requirement for context variables.
*
*
* @see ILazyContextVariable
*
* @author Daniel Fernández
*
* @since 3.0.3
*
*/
public class ReactiveLazyContextVariable
extends LazyContextVariable