Skip to content

Commit

Permalink
Allow @DefaultValue to be used on record components
Browse files Browse the repository at this point in the history
  • Loading branch information
An1s9n authored and wilkinsona committed Mar 4, 2022
1 parent 1793cee commit 976ed90
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 2 deletions.
Expand Up @@ -74,6 +74,7 @@
* @author Andy Wilkinson
* @author Kris De Volder
* @author Jonas Keßler
* @author Pavel Anisimov
*/
class ConfigurationMetadataAnnotationProcessorTests extends AbstractMetadataGenerationTests {

Expand Down Expand Up @@ -445,4 +446,24 @@ void multiConstructorRecordProperties(@TempDir File temp) throws IOException {
assertThat(metadata).doesNotHave(Metadata.withProperty("multi.some-integer"));
}

@Test
@EnabledForJreRange(min = JRE.JAVA_16)
void recordPropertiesWithDefaultValues(@TempDir File temp) throws IOException {
File exampleRecord = new File(temp, "ExampleRecord.java");
try (PrintWriter writer = new PrintWriter(new FileWriter(exampleRecord))) {
writer.println(
"@org.springframework.boot.configurationsample.ConfigurationProperties(\"record.defaults\")");
writer.println("public record ExampleRecord(");
writer.println("@org.springframework.boot.configurationsample.DefaultValue(\"An1s9n\") String someString,");
writer.println("@org.springframework.boot.configurationsample.DefaultValue(\"594\") Integer someInteger");
writer.println(") {");
writer.println("}");
}
ConfigurationMetadata metadata = compile(exampleRecord);
assertThat(metadata)
.has(Metadata.withProperty("record.defaults.some-string", String.class).withDefaultValue("An1s9n"));
assertThat(metadata)
.has(Metadata.withProperty("record.defaults.some-integer", Integer.class).withDefaultValue(594));
}

}
Expand Up @@ -27,8 +27,9 @@
* dependency on the real annotation).
*
* @author Stephane Nicoll
* @author Pavel Anisimov
*/
@Target({ ElementType.PARAMETER })
@Target({ ElementType.PARAMETER, ElementType.RECORD_COMPONENT })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DefaultValue {
Expand Down
Expand Up @@ -37,10 +37,11 @@
* must be constant.
*
* @author Madhura Bhave
* @author Pavel Anisimov
* @since 2.2.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.PARAMETER })
@Target({ ElementType.PARAMETER, ElementType.RECORD_COMPONENT })
@Documented
public @interface DefaultValue {

Expand Down
Expand Up @@ -16,23 +16,35 @@

package org.springframework.boot.context.properties.bind;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.io.TempDir;

import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.MockConfigurationPropertySource;
import org.springframework.boot.testsupport.compiler.TestCompiler;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionService;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.Assert;

import static org.assertj.core.api.Assertions.assertThat;
Expand All @@ -43,6 +55,7 @@
*
* @author Madhura Bhave
* @author Phillip Webb
* @author Pavel Anisimov
*/
class ValueObjectBinderTests {

Expand Down Expand Up @@ -357,6 +370,30 @@ void bindToAnnotationNamedParameter() {
assertThat(bound.getImportName()).isEqualTo("test");
}

@Test
@EnabledForJreRange(min = JRE.JAVA_16)
void bindToRecordWithDefaultValue(@TempDir File tempDir) throws IOException, ClassNotFoundException {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("test.record.property1", "value-from-config-1");
this.sources.add(source);
File recordProperties = new File(tempDir, "RecordProperties.java");
try (PrintWriter writer = new PrintWriter(new FileWriter(recordProperties))) {
writer.println("public record RecordProperties(");
writer.println(
"@org.springframework.boot.context.properties.bind.DefaultValue(\"default-value-1\") String property1,");
writer.println(
"@org.springframework.boot.context.properties.bind.DefaultValue(\"default-value-2\") String property2");
writer.println(") {");
writer.println("}");
}
TestCompiler compiler = new TestCompiler(tempDir);
compiler.getTask(Arrays.asList(recordProperties)).call();
ClassLoader ucl = new URLClassLoader(new URL[] { tempDir.toURI().toURL() });
Object bean = this.binder.bind("test.record", Class.forName("RecordProperties", true, ucl)).get();
assertThat(ReflectionTestUtils.getField(bean, "property1")).isEqualTo("value-from-config-1");
assertThat(ReflectionTestUtils.getField(bean, "property2")).isEqualTo("default-value-2");
}

private void noConfigurationProperty(BindException ex) {
assertThat(ex.getProperty()).isNull();
}
Expand Down

0 comments on commit 976ed90

Please sign in to comment.