Skip to content

Commit 608b6c4

Browse files
committed
Merge branch '3.3.x' into 3.4.x
Closes gh-44456
2 parents 4d137d4 + 3de189a commit 608b6c4

File tree

313 files changed

+2899
-1279
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

313 files changed

+2899
-1279
lines changed

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/BeanDefinitionLoaderTests.java

+31-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323

2424
import org.springframework.boot.sampleconfig.MyComponent;
2525
import org.springframework.boot.sampleconfig.MyNamedComponent;
26+
import org.springframework.boot.testsupport.classpath.resources.WithResource;
2627
import org.springframework.context.support.StaticApplicationContext;
2728
import org.springframework.core.io.ClassPathResource;
2829

@@ -72,26 +73,43 @@ void loadJsr330Class() {
7273
}
7374

7475
@Test
76+
@WithSampleBeansXmlResource
7577
void loadXmlResource() {
76-
ClassPathResource resource = new ClassPathResource("sample-beans.xml", getClass());
78+
ClassPathResource resource = new ClassPathResource("org/springframework/boot/sample-beans.xml");
7779
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry, resource);
7880
assertThat(load(loader)).isOne();
7981
assertThat(this.registry.containsBean("myXmlComponent")).isTrue();
8082

8183
}
8284

8385
@Test
86+
@WithResource(name = "org/springframework/boot/sample-beans.groovy", content = """
87+
import org.springframework.boot.sampleconfig.MyComponent;
88+
89+
beans {
90+
myGroovyComponent(MyComponent) {}
91+
}
92+
""")
8493
void loadGroovyResource() {
85-
ClassPathResource resource = new ClassPathResource("sample-beans.groovy", getClass());
94+
ClassPathResource resource = new ClassPathResource("org/springframework/boot/sample-beans.groovy");
8695
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry, resource);
8796
assertThat(load(loader)).isOne();
8897
assertThat(this.registry.containsBean("myGroovyComponent")).isTrue();
8998

9099
}
91100

92101
@Test
102+
@WithResource(name = "org/springframework/boot/sample-namespace.groovy", content = """
103+
import org.springframework.boot.sampleconfig.MyComponent;
104+
105+
beans {
106+
xmlns([ctx:'http://www.springframework.org/schema/context'])
107+
ctx.'component-scan'('base-package':'nonexistent')
108+
myGroovyComponent(MyComponent) {}
109+
}
110+
""")
93111
void loadGroovyResourceWithNamespace() {
94-
ClassPathResource resource = new ClassPathResource("sample-namespace.groovy", getClass());
112+
ClassPathResource resource = new ClassPathResource("org/springframework/boot/sample-namespace.groovy");
95113
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry, resource);
96114
assertThat(load(loader)).isOne();
97115
assertThat(this.registry.containsBean("myGroovyComponent")).isTrue();
@@ -114,14 +132,22 @@ void loadClassName() {
114132
}
115133

116134
@Test
117-
void loadResourceName() {
135+
@WithSampleBeansXmlResource
136+
void loadXmlName() {
118137
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry,
119138
"classpath:org/springframework/boot/sample-beans.xml");
120139
assertThat(load(loader)).isOne();
121140
assertThat(this.registry.containsBean("myXmlComponent")).isTrue();
122141
}
123142

124143
@Test
144+
@WithResource(name = "org/springframework/boot/sample-beans.groovy", content = """
145+
import org.springframework.boot.sampleconfig.MyComponent;
146+
147+
beans {
148+
myGroovyComponent(MyComponent) {}
149+
}
150+
""")
125151
void loadGroovyName() {
126152
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry,
127153
"classpath:org/springframework/boot/sample-beans.groovy");

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SimpleMainTests.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -61,12 +61,14 @@ void configClassContext(CapturedOutput output) throws Exception {
6161
}
6262

6363
@Test
64+
@WithSampleBeansXmlResource
6465
void xmlContext(CapturedOutput output) throws Exception {
6566
SpringApplication.main(getArgs("org/springframework/boot/sample-beans.xml"));
6667
assertThat(output).contains(SPRING_STARTUP);
6768
}
6869

6970
@Test
71+
@WithSampleBeansXmlResource
7072
void mixedContext(CapturedOutput output) throws Exception {
7173
SpringApplication.main(getArgs(getClass().getName(), "org/springframework/boot/sample-beans.xml"));
7274
assertThat(output).contains(SPRING_STARTUP);

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationBannerPrinterTests.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
2222

2323
import org.springframework.aot.hint.RuntimeHints;
2424
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
25+
import org.springframework.boot.testsupport.classpath.resources.WithResource;
2526
import org.springframework.context.support.GenericApplicationContext;
2627
import org.springframework.core.io.Resource;
2728
import org.springframework.core.io.ResourceLoader;
@@ -47,9 +48,10 @@ void shouldRegisterRuntimeHints() {
4748
}
4849

4950
@Test
51+
@WithResource(name = "banner.txt", content = "\uD83D\uDE0D Spring Boot! \uD83D\uDE0D")
5052
void shouldUseUtf8() {
5153
ResourceLoader resourceLoader = new GenericApplicationContext();
52-
Resource resource = resourceLoader.getResource("classpath:/banner-utf8.txt");
54+
Resource resource = resourceLoader.getResource("classpath:banner.txt");
5355
SpringApplicationBannerPrinter printer = new SpringApplicationBannerPrinter(resourceLoader,
5456
new ResourceBanner(resource));
5557
Log log = mock(Log.class);

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java

+22-4
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import org.springframework.boot.context.event.SpringApplicationEvent;
7373
import org.springframework.boot.convert.ApplicationConversionService;
7474
import org.springframework.boot.testsupport.classpath.ForkedClassPath;
75+
import org.springframework.boot.testsupport.classpath.resources.WithResource;
7576
import org.springframework.boot.testsupport.system.CapturedOutput;
7677
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
7778
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
@@ -225,19 +226,24 @@ void sourcesMustBeAccessible() {
225226
}
226227

227228
@Test
229+
@WithResource(name = "banner.txt", content = "Running a Test!")
228230
void customBanner(CapturedOutput output) {
229231
SpringApplication application = spy(new SpringApplication(ExampleConfig.class));
230232
application.setWebApplicationType(WebApplicationType.NONE);
231-
this.context = application.run("--spring.banner.location=classpath:test-banner.txt");
233+
this.context = application.run();
232234
assertThat(output).startsWith("Running a Test!");
235+
233236
}
234237

235238
@Test
239+
@WithResource(name = "banner.txt", content = """
240+
Running a Test!
241+
242+
${test.property}""")
236243
void customBannerWithProperties(CapturedOutput output) {
237244
SpringApplication application = spy(new SpringApplication(ExampleConfig.class));
238245
application.setWebApplicationType(WebApplicationType.NONE);
239-
this.context = application.run("--spring.banner.location=classpath:test-banner-with-placeholder.txt",
240-
"--test.property=123456");
246+
this.context = application.run("--test.property=123456");
241247
assertThat(output).containsPattern("Running a Test!\\s+123456");
242248
}
243249

@@ -288,6 +294,7 @@ void enableBannerInLogViaProperty(CapturedOutput output) {
288294
}
289295

290296
@Test
297+
@WithResource(name = "bindtoapplication.properties", content = "spring.main.banner-mode=off")
291298
void triggersConfigFileApplicationListenerBeforeBinding() {
292299
SpringApplication application = new SpringApplication(ExampleConfig.class);
293300
application.setWebApplicationType(WebApplicationType.NONE);
@@ -539,6 +546,7 @@ void commandLinePropertySourceEnhancesEnvironment() {
539546
}
540547

541548
@Test
549+
@WithResource(name = "application.properties", content = "foo=bucket")
542550
void propertiesFileEnhancesEnvironment() {
543551
SpringApplication application = new SpringApplication(ExampleConfig.class);
544552
application.setWebApplicationType(WebApplicationType.NONE);
@@ -571,6 +579,8 @@ void additionalProfilesOrderedBeforeActiveProfiles() {
571579
}
572580

573581
@Test
582+
@WithResource(name = "application.properties", content = "my.property=fromapplicationproperties")
583+
@WithResource(name = "application-other.properties", content = "my.property=fromotherpropertiesfile")
574584
void addProfilesOrderWithProperties() {
575585
SpringApplication application = new SpringApplication(ExampleConfig.class);
576586
application.setWebApplicationType(WebApplicationType.NONE);
@@ -583,6 +593,7 @@ void addProfilesOrderWithProperties() {
583593
}
584594

585595
@Test
596+
@WithResource(name = "application.properties", content = "foo=bucket")
586597
void emptyCommandLinePropertySourceNotAdded() {
587598
SpringApplication application = new SpringApplication(ExampleConfig.class);
588599
application.setWebApplicationType(WebApplicationType.NONE);
@@ -813,11 +824,13 @@ void loadSources() {
813824
}
814825

815826
@Test
827+
@WithSampleBeansXmlResource
828+
@WithResource(name = "application.properties", content = "sample.app.test.prop=*")
816829
void wildcardSources() {
817830
TestSpringApplication application = new TestSpringApplication();
818831
application.getSources().add("classpath*:org/springframework/boot/sample-${sample.app.test.prop}.xml");
819832
application.setWebApplicationType(WebApplicationType.NONE);
820-
this.context = application.run();
833+
this.context = application.run("--spring.config.location=classpath:/");
821834
}
822835

823836
@Test
@@ -1138,6 +1151,8 @@ void reactiveApplicationConfiguredViaAPropertyHasTheCorrectTypeOfContextAndEnvir
11381151
}
11391152

11401153
@Test
1154+
@WithResource(name = "application-withwebapplicationtype.yml",
1155+
content = "spring.main.web-application-type: reactive")
11411156
void environmentIsConvertedIfTypeDoesNotMatch() {
11421157
ConfigurableApplicationContext context = new SpringApplication(ExampleReactiveWebConfig.class)
11431158
.run("--spring.profiles.active=withwebapplicationtype");
@@ -1194,6 +1209,7 @@ void circularReferencesCanBeEnabled() {
11941209
}
11951210

11961211
@Test
1212+
@WithResource(name = "custom-config/application.yml", content = "hello: world")
11971213
void relaxedBindingShouldWorkBeforeEnvironmentIsPrepared() {
11981214
SpringApplication application = new SpringApplication(ExampleConfig.class);
11991215
application.setWebApplicationType(WebApplicationType.NONE);
@@ -1328,6 +1344,8 @@ void bindsEnvironmentPrefixToSpringApplication() {
13281344
}
13291345

13301346
@Test
1347+
@WithResource(name = "spring-application-config-property-source.properties",
1348+
content = "test.name=spring-application-config-property-source")
13311349
void movesConfigClassPropertySourcesToEnd() {
13321350
SpringApplication application = new SpringApplication(PropertySourceConfig.class);
13331351
application.setWebApplicationType(WebApplicationType.NONE);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2012-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot;
18+
19+
import java.lang.annotation.ElementType;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.RetentionPolicy;
22+
import java.lang.annotation.Target;
23+
24+
import org.springframework.boot.testsupport.classpath.resources.WithResource;
25+
26+
/**
27+
* Makes an {@code org/springframework/boot/sample-beans.xml} resource available from the
28+
* thread context classloader.
29+
*
30+
* @author Andy Wilkinson
31+
*/
32+
@Retention(RetentionPolicy.RUNTIME)
33+
@Target(ElementType.METHOD)
34+
@WithResource(name = "org/springframework/boot/sample-beans.xml",
35+
content = """
36+
<?xml version="1.0" encoding="UTF-8"?>
37+
<beans xmlns="http://www.springframework.org/schema/beans"
38+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
39+
xmlns:context="http://www.springframework.org/schema/context"
40+
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
41+
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
42+
<bean id="myXmlComponent" class="org.springframework.boot.sampleconfig.MyComponent"/>
43+
</beans>
44+
""")
45+
@interface WithSampleBeansXmlResource {
46+
47+
}

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/builder/SpringApplicationBuilderTests.java

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
2929
import org.springframework.boot.SpringApplication;
3030
import org.springframework.boot.SpringApplicationShutdownHookInstance;
3131
import org.springframework.boot.WebApplicationType;
32+
import org.springframework.boot.testsupport.classpath.resources.WithResource;
3233
import org.springframework.context.ApplicationContext;
3334
import org.springframework.context.ConfigurableApplicationContext;
3435
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -72,14 +73,21 @@ private void close(ApplicationContext context) {
7273
}
7374

7475
@Test
76+
@WithResource(name = "application.properties", content = """
77+
b=file
78+
c=file
79+
""")
80+
@WithResource(name = "application-foo.properties", content = "b=profile-specific-file")
7581
void profileAndProperties() {
7682
SpringApplicationBuilder application = new SpringApplicationBuilder().sources(ExampleConfig.class)
7783
.contextFactory(ApplicationContextFactory.ofContextClass(StaticApplicationContext.class))
7884
.profiles("foo")
79-
.properties("foo=bar");
85+
.properties("a=default");
8086
this.context = application.run();
8187
assertThat(this.context).isInstanceOf(StaticApplicationContext.class);
82-
assertThat(this.context.getEnvironment().getProperty("foo")).isEqualTo("bucket");
88+
assertThat(this.context.getEnvironment().getProperty("a")).isEqualTo("default");
89+
assertThat(this.context.getEnvironment().getProperty("b")).isEqualTo("profile-specific-file");
90+
assertThat(this.context.getEnvironment().getProperty("c")).isEqualTo("file");
8391
assertThat(this.context.getEnvironment().acceptsProfiles(Profiles.of("foo"))).isTrue();
8492
}
8593

@@ -194,6 +202,7 @@ void parentFirstCreation() {
194202
}
195203

196204
@Test
205+
@WithResource(name = "application-node.properties", content = "bar=spam")
197206
void parentFirstCreationWithProfileAndDefaultArgs() {
198207
SpringApplicationBuilder application = new SpringApplicationBuilder(ExampleConfig.class).profiles("node")
199208
.properties("transport=redis")

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/annotation/ImportCandidatesTests.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@
2323

2424
import org.junit.jupiter.api.Test;
2525

26+
import org.springframework.boot.testsupport.classpath.resources.WithResource;
27+
2628
import static org.assertj.core.api.Assertions.assertThat;
2729

2830
/**
@@ -32,7 +34,18 @@
3234
*/
3335
class ImportCandidatesTests {
3436

37+
private static final String IMPORTS_FILE = "META-INF/spring/org.springframework.boot.context.annotation.ImportCandidatesTests$TestAnnotation.imports";
38+
3539
@Test
40+
@WithResource(name = IMPORTS_FILE, content = """
41+
# A comment spanning a complete line
42+
class1
43+
44+
class2 # with comment at the end
45+
# Comment with some whitespace in front
46+
class3
47+
48+
""")
3649
void loadReadsFromClasspathFile() {
3750
ImportCandidates candidates = ImportCandidates.load(TestAnnotation.class, null);
3851
assertThat(candidates).containsExactly("class1", "class2", "class3");

0 commit comments

Comments
 (0)