Polishing in FragmentsRendering

See gh-33194
This commit is contained in:
rstoyanchev
2024-07-23 11:05:33 +01:00
parent 7c9bb24296
commit aa6b47bfce
3 changed files with 45 additions and 42 deletions

View File

@@ -32,11 +32,11 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Public API for HTML rendering from a collection or from a stream of
* {@link Fragment}s each with its own view and model. For use with
* view technologies such as <a href="https://htmx.org/">htmx</a> where multiple
* page fragments may be rendered in a single response. Supported as a return
* value from a WebFlux controller method.
* Public API for HTML rendering of a collection of fragments each with a view
* and independent model. For use with frontends technologies such as
* <a href="https://htmx.org/">htmx</a> where multiple page fragments may be
* rendered in one response. Supported as a return value from Spring WebFlux
* controller methods.
*
* <p>For full page rendering with a single model and view, use {@link Rendering}.
*
@@ -74,8 +74,8 @@ public interface FragmentsRendering {
}
/**
* Create a builder and add a fragment with a view name only, also
* inheriting model attributes from the model for the request.
* Variant of {@link #with(String, Map)} with a view name only, but also
* inheriting model attributes from the shared model for the request.
* @param viewName the name of the view for the fragment
* @return this builder
*/
@@ -84,14 +84,20 @@ public interface FragmentsRendering {
}
/**
* Create a builder to render with a collection of Fragments.
* Variant of {@link #with(String, Map)} with a collection of fragments.
* @param fragments the fragments to add; each fragment also inherits model
* attributes from the shared model for the request
* @return the created builder
*/
static Builder withCollection(Collection<Fragment> fragments) {
return new DefaultFragmentsRenderingBuilder(fragments);
}
/**
* Create a builder to render with a {@link Publisher} of Fragments.
* Variant of {@link #with(String, Map)} with a {@link Publisher} of fragments.
* @param fragmentsPublisher the fragments to add; each fragment also
* inherits model attributes from the shared model for the request
* @return the created builder
*/
static <P extends Publisher<Fragment>> Builder withPublisher(P fragmentsPublisher) {
return new DefaultFragmentsRenderingBuilder(fragmentsPublisher);
@@ -126,7 +132,7 @@ public interface FragmentsRendering {
Builder status(HttpStatusCode status);
/**
* Add the given, single header value under the given name.
* Add one or more header values under the given name.
* @param headerName the header name
* @param headerValues the header value(s)
* @return this builder
@@ -151,15 +157,16 @@ public interface FragmentsRendering {
Builder fragment(String viewName, Map<String, Object> model);
/**
* Add a fragment with a view name only, inheriting model attributes from
* the model for the request.
* Variant of {@link #fragment(String, Map)} with a view name only, where
* the fragment model also inherits model attributes from the shared
* model for the request.
* @param viewName the name of the view for the fragment
* @return this builder
*/
Builder fragment(String viewName);
/**
* Add a fragment.
* Variant of {@link #fragment(String, Map)} with a {@link Fragment}.
* @param fragment the fragment to add
* @return this builder
*/

View File

@@ -22,6 +22,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -54,25 +55,21 @@ import static org.springframework.web.testfixture.method.ResolvableMethod.on;
*/
public class FragmentViewResolutionResultHandlerTests {
private static final Fragment fragment1 = Fragment.create("fragment1", Map.of("foo", "Foo"));
private static final Fragment fragment2 = Fragment.create("fragment2", Map.of("bar", "Bar"));
static Stream<Arguments> arguments() {
Fragment f1 = Fragment.create("fragment1", Map.of("foo", "Foo"));
Fragment f2 = Fragment.create("fragment2", Map.of("bar", "Bar"));
Flux<Fragment> fragmentFlux = Flux.just(fragment1, fragment2).subscribeOn(Schedulers.boundedElastic());
return Stream.of(
Arguments.of(
FragmentsRendering.withPublisher(Flux.just(f1, f2).subscribeOn(Schedulers.boundedElastic()))
.headers(headers -> headers.setContentType(MediaType.TEXT_HTML))
.build(),
Arguments.of(FragmentsRendering.withPublisher(fragmentFlux).build(),
on(Handler.class).resolveReturnType(FragmentsRendering.class)),
Arguments.of(
FragmentsRendering.withCollection(List.of(f1, f2))
.headers(headers -> headers.setContentType(MediaType.TEXT_HTML))
.build(),
Arguments.of(FragmentsRendering.withCollection(List.of(fragment1, fragment2)).build(),
on(Handler.class).resolveReturnType(FragmentsRendering.class)),
Arguments.of(
Flux.just(f1, f2).subscribeOn(Schedulers.boundedElastic()),
Arguments.of(fragmentFlux,
on(Handler.class).resolveReturnType(Flux.class, Fragment.class)),
Arguments.of(
List.of(f1, f2),
Arguments.of(List.of(fragment1, fragment2),
on(Handler.class).resolveReturnType(List.class, Fragment.class)));
}
@@ -107,14 +104,14 @@ public class FragmentViewResolutionResultHandlerTests {
}
@SuppressWarnings("unused")
@SuppressWarnings({"unused", "DataFlowIssue"})
private static class Handler {
FragmentsRendering rendering() { return null; }
FragmentsRendering render() { return null; }
Flux<Fragment> fragmentFlux() { return null; }
Flux<Fragment> renderFlux() { return null; }
List<Fragment> fragmentList() { return null; }
List<Fragment> renderList() { return null; }
}

View File

@@ -27,11 +27,11 @@ import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.SmartView;
/**
* Public API for HTML rendering a collection fragments each with its own view
* and model. For use with view technologies such as
* Public API for HTML rendering of a collection of fragments each with a view
* and independent model. For use with frontends technologies such as
* <a href="https://htmx.org/">htmx</a> where multiple page fragments may be
* rendered in a single response. Supported as a return value from a Spring MVC
* controller method.
* rendered in one response. Supported as a return value from Spring MVC
* controller methods.
*
* @author Rossen Stoyanchev
* @since 6.2
@@ -51,8 +51,7 @@ public interface FragmentsRendering extends SmartView {
/**
* Create a builder for {@link FragmentsRendering}, adding a fragment with
* the given view name and model.
* Create a builder and add a fragment with a view name and a model.
* @param viewName the name of the view for the fragment
* @param model attributes for the fragment in addition to model
* attributes inherited from the shared model for the request
@@ -96,7 +95,7 @@ public interface FragmentsRendering extends SmartView {
Builder status(HttpStatusCode status);
/**
* Add the given, single header value under the given name.
* Add one or more header values under the given name.
* @param headerName the header name
* @param headerValues the header value(s)
* @return this builder
@@ -121,15 +120,15 @@ public interface FragmentsRendering extends SmartView {
Builder fragment(String viewName, Map<String, Object> model);
/**
* Add a fragment with a view name only, inheriting model attributes from
* the model for the request.
* Variant of {@link #fragment(String, Map)} with a view name only, but
* also inheriting model attributes from the shared model for the request.
* @param viewName the name of the view for the fragment
* @return this builder
*/
Builder fragment(String viewName);
/**
* Add a fragment.
* Variant of {@link #fragment(String, Map)} with a {@link ModelAndView}.
* @param fragment the fragment to add; the fragment also inherits model
* attributes from the shared model for the request
* @return this builder
@@ -137,7 +136,7 @@ public interface FragmentsRendering extends SmartView {
Builder fragment(ModelAndView fragment);
/**
* Add a collection of fragments.
* Variant of {@link #fragment(String, Map)} with a collection of {@link ModelAndView}s.
* @param fragments the fragments to add; each fragment also inherits model
* attributes from the shared model for the request
* @return this builder