From c0679191739c7de90c6aeecbfc2e65e941b1bf5f Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Fri, 2 May 2025 08:19:18 +0100 Subject: [PATCH] Ensure Fragment can merge attributes Use a new map when merging as the original may be immutable. Closes gh-34848 --- .../web/reactive/result/view/Fragment.java | 6 +-- .../reactive/result/view/FragmentTests.java | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 spring-webflux/src/test/java/org/springframework/web/reactive/result/view/FragmentTests.java diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/Fragment.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/Fragment.java index f835b3f6805..446383eed9c 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/Fragment.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/view/Fragment.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -91,9 +91,7 @@ public final class Fragment { if (CollectionUtils.isEmpty(model.asMap())) { return; } - if (this.model == null) { - this.model = new LinkedHashMap<>(); - } + this.model = new LinkedHashMap<>(this.model != null ? this.model : Collections.emptyMap()); model.asMap().forEach((key, value) -> this.model.putIfAbsent(key, value)); } diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/FragmentTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/FragmentTests.java new file mode 100644 index 00000000000..10edd3b5add --- /dev/null +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/FragmentTests.java @@ -0,0 +1,49 @@ +/* + * Copyright 2002-2025 the original author or authors. + * + * 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 + * + * https://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.springframework.web.reactive.result.view; + +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import org.springframework.ui.ConcurrentModel; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Unit tests for {@link Fragment}. + * @author Rossen Stoyanchev + */ +public class FragmentTests { + + @Test + void mergeAttributes() { + Fragment fragment = Fragment.create("myView", Map.of("fruit", "apple")); + fragment.mergeAttributes(new ConcurrentModel("vegetable", "pepper")); + + assertThat(fragment.model()).containsExactly(Map.entry("fruit", "apple"), Map.entry("vegetable", "pepper")); + } + + @Test + void mergeAttributesCollision() { + Fragment fragment = Fragment.create("myView", Map.of("fruit", "apple")); + fragment.mergeAttributes(new ConcurrentModel("fruit", "orange")); + + assertThat(fragment.model()).containsExactly(Map.entry("fruit", "apple")); + } + +}