From 00b9a8811ddea6bd90e63457f94b4b4b23f39d94 Mon Sep 17 00:00:00 2001 From: Saraswathy Hariharakrishnan Date: Thu, 15 Jul 2021 15:21:13 -0700 Subject: [PATCH 1/2] Support comma-separated basePackage values in EntityScan See gh-27355 --- .../autoconfigure/domain/EntityScanPackages.java | 6 +++++- .../autoconfigure/domain/EntityScannerTests.java | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/EntityScanPackages.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/EntityScanPackages.java index 185a90fd57..4a17db7b29 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/EntityScanPackages.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/EntityScanPackages.java @@ -30,6 +30,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.Environment; @@ -141,7 +142,10 @@ public class EntityScanPackages { .fromMap(metadata.getAnnotationAttributes(EntityScan.class.getName())); Set packagesToScan = new LinkedHashSet<>(); for (String basePackage : attributes.getStringArray("basePackages")) { - addResolvedPackage(basePackage, packagesToScan); + String[] tokenized = StringUtils.tokenizeToStringArray( + this.environment.resolvePlaceholders(basePackage), + ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); + Collections.addAll(packagesToScan, tokenized); } for (Class basePackageClass : attributes.getClassArray("basePackageClasses")) { addResolvedPackage(ClassUtils.getPackageName(basePackageClass), packagesToScan); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/domain/EntityScannerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/domain/EntityScannerTests.java index e78e03aec8..22300e2e26 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/domain/EntityScannerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/domain/EntityScannerTests.java @@ -25,6 +25,7 @@ import javax.persistence.Entity; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; +import org.springframework.boot.autoconfigure.data.jpa.city.City; import org.springframework.boot.autoconfigure.domain.scan.a.EmbeddableA; import org.springframework.boot.autoconfigure.domain.scan.a.EntityA; import org.springframework.boot.autoconfigure.domain.scan.b.EmbeddableB; @@ -119,6 +120,20 @@ class EntityScannerTests { assertThat(annotationTypeFilter.getValue().getAnnotationType()).isEqualTo(Entity.class); } + @Test + void scanShouldScanCommaSeparatedPackagesInPlaceholderPackage() throws Exception { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + TestPropertyValues.of( + "com.example.entity-package=org.springframework.boot.autoconfigure.domain.scan,org.springframework.boot.autoconfigure.data.jpa.city") + .applyTo(context); + context.register(ScanPlaceholderConfig.class); + context.refresh(); + EntityScanner scanner = new EntityScanner(context); + Set> scanned = scanner.scan(Entity.class); + assertThat(scanned).containsOnly(EntityA.class, EntityB.class, EntityC.class, City.class); + context.close(); + } + private static class TestEntityScanner extends EntityScanner { private final ClassPathScanningCandidateComponentProvider candidateComponentProvider; From 7bae960d78f1cd3b99d2a8744be07d2f243c0719 Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Thu, 15 Jul 2021 15:40:01 -0700 Subject: [PATCH 2/2] Polish "Support comma-separated basePackage values in EntityScan" See gh-27355 --- .../boot/autoconfigure/domain/EntityScanPackages.java | 6 +----- .../boot/autoconfigure/domain/EntityScannerTests.java | 5 ++--- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/EntityScanPackages.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/EntityScanPackages.java index 4a17db7b29..e0c27c2cf1 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/EntityScanPackages.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/domain/EntityScanPackages.java @@ -148,7 +148,7 @@ public class EntityScanPackages { Collections.addAll(packagesToScan, tokenized); } for (Class basePackageClass : attributes.getClassArray("basePackageClasses")) { - addResolvedPackage(ClassUtils.getPackageName(basePackageClass), packagesToScan); + packagesToScan.add(this.environment.resolvePlaceholders(ClassUtils.getPackageName(basePackageClass))); } if (packagesToScan.isEmpty()) { String packageName = ClassUtils.getPackageName(metadata.getClassName()); @@ -158,10 +158,6 @@ public class EntityScanPackages { return packagesToScan; } - private void addResolvedPackage(String packageName, Set packagesToScan) { - packagesToScan.add(this.environment.resolvePlaceholders(packageName)); - } - } static class EntityScanPackagesBeanDefinition extends GenericBeanDefinition { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/domain/EntityScannerTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/domain/EntityScannerTests.java index 22300e2e26..36c2cc3160 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/domain/EntityScannerTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/domain/EntityScannerTests.java @@ -25,7 +25,6 @@ import javax.persistence.Entity; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; -import org.springframework.boot.autoconfigure.data.jpa.city.City; import org.springframework.boot.autoconfigure.domain.scan.a.EmbeddableA; import org.springframework.boot.autoconfigure.domain.scan.a.EntityA; import org.springframework.boot.autoconfigure.domain.scan.b.EmbeddableB; @@ -124,13 +123,13 @@ class EntityScannerTests { void scanShouldScanCommaSeparatedPackagesInPlaceholderPackage() throws Exception { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); TestPropertyValues.of( - "com.example.entity-package=org.springframework.boot.autoconfigure.domain.scan,org.springframework.boot.autoconfigure.data.jpa.city") + "com.example.entity-package=org.springframework.boot.autoconfigure.domain.scan.a,org.springframework.boot.autoconfigure.domain.scan.b") .applyTo(context); context.register(ScanPlaceholderConfig.class); context.refresh(); EntityScanner scanner = new EntityScanner(context); Set> scanned = scanner.scan(Entity.class); - assertThat(scanned).containsOnly(EntityA.class, EntityB.class, EntityC.class, City.class); + assertThat(scanned).containsOnly(EntityA.class, EntityB.class); context.close(); }