Browse Source
Add a new `@EntiyScan` annotation that's used by auto-configuration to: * Set JPA packagesToScan. * Set Neo4J's SessionFactory packages. * Set the initial entity set for Spring Data MongoDB, Cassandra and Couchbase mapping contexts. Additionally deprecate `@org.springframework.boot.orm.jpa.EntityScan`. See gh-6142pull/6225/head
27 changed files with 1030 additions and 149 deletions
@ -0,0 +1,93 @@
@@ -0,0 +1,93 @@
|
||||
/* |
||||
* Copyright 2012-2016 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 |
||||
* |
||||
* http://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.boot.autoconfigure.domain; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
import org.springframework.context.annotation.Import; |
||||
import org.springframework.core.annotation.AliasFor; |
||||
|
||||
/** |
||||
* Configures the base packages used by auto-configuration when scanning for entity |
||||
* classes. |
||||
* <p> |
||||
* Using {@code @EntityScan} will cause auto-configuration to: |
||||
* <ul> |
||||
* <li>Set the |
||||
* {@link org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean#setPackagesToScan(String...) |
||||
* packages scanned} for JPA entities.</li> |
||||
* <li>Set the packages used with Neo4J's {@link org.neo4j.ogm.session.SessionFactory |
||||
* SessionFactory}.</li> |
||||
* <li>Set the |
||||
* {@link org.springframework.data.mapping.context.AbstractMappingContext#setInitialEntitySet(java.util.Set) |
||||
* initial entity set} used with Spring Data |
||||
* {@link org.springframework.data.mongodb.core.mapping.MongoMappingContext MongoDB}, |
||||
* {@link org.springframework.data.cassandra.mapping.CassandraMappingContext Cassandra} |
||||
* and {@link org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext |
||||
* Couchbase} mapping contexts.</li> |
||||
* </ul> |
||||
* <p> |
||||
* One of {@link #basePackageClasses()}, {@link #basePackages()} or its alias |
||||
* {@link #value()} may be specified to define specific packages to scan. If specific |
||||
* packages are not defined scanning will occur from the package of the class with this |
||||
* annotation. |
||||
* |
||||
* @author Phillip Webb |
||||
* @since 1.4.0 |
||||
* @see EntityScanPackages |
||||
*/ |
||||
@Target(ElementType.TYPE) |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Documented |
||||
@Import(EntityScanPackages.Registrar.class) |
||||
public @interface EntityScan { |
||||
|
||||
/** |
||||
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation |
||||
* declarations e.g.: {@code @EntityScan("org.my.pkg")} instead of |
||||
* {@code @EntityScan(basePackages="org.my.pkg")}. |
||||
* @return the base packages to scan |
||||
*/ |
||||
@AliasFor("basePackages") |
||||
String[] value() default {}; |
||||
|
||||
/** |
||||
* Base packages to scan for entities. {@link #value()} is an alias for (and mutually |
||||
* exclusive with) this attribute. |
||||
* <p> |
||||
* Use {@link #basePackageClasses()} for a type-safe alternative to String-based |
||||
* package names. |
||||
* @return the base packages to scan |
||||
*/ |
||||
@AliasFor("value") |
||||
String[] basePackages() default {}; |
||||
|
||||
/** |
||||
* Type-safe alternative to {@link #basePackages()} for specifying the packages to |
||||
* scan for entities. The package of each class specified will be scanned. |
||||
* <p> |
||||
* Consider creating a special no-op marker class or interface in each package that |
||||
* serves no purpose other than being referenced by this attribute. |
||||
* @return classes from the base packages to scan |
||||
*/ |
||||
Class<?>[] basePackageClasses() default {}; |
||||
|
||||
} |
||||
@ -0,0 +1,177 @@
@@ -0,0 +1,177 @@
|
||||
/* |
||||
* Copyright 2012-2016 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 |
||||
* |
||||
* http://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.boot.autoconfigure.domain; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Arrays; |
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.LinkedHashSet; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
import org.springframework.beans.factory.BeanFactory; |
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException; |
||||
import org.springframework.beans.factory.config.BeanDefinition; |
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues; |
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry; |
||||
import org.springframework.beans.factory.support.GenericBeanDefinition; |
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; |
||||
import org.springframework.core.Ordered; |
||||
import org.springframework.core.annotation.AnnotationAttributes; |
||||
import org.springframework.core.annotation.Order; |
||||
import org.springframework.core.type.AnnotationMetadata; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.ClassUtils; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* Class for storing {@link EntityScan @EntityScan} specified packages for reference later |
||||
* (e.g. by JPA auto-configuration). |
||||
* |
||||
* @author Phillip Webb |
||||
* @since 1.4.0 |
||||
* @see EntityScan |
||||
* @see EntityScanner |
||||
*/ |
||||
public class EntityScanPackages { |
||||
|
||||
private static final String BEAN = EntityScanPackages.class.getName(); |
||||
|
||||
private static final EntityScanPackages NONE = new EntityScanPackages(); |
||||
|
||||
private final List<String> packageNames; |
||||
|
||||
EntityScanPackages(String... packageNames) { |
||||
List<String> packages = new ArrayList<String>(); |
||||
for (String name : packageNames) { |
||||
if (StringUtils.hasText(name)) { |
||||
packages.add(name); |
||||
} |
||||
} |
||||
this.packageNames = Collections.unmodifiableList(packages); |
||||
} |
||||
|
||||
/** |
||||
* Return the package names specified from all {@link EntityScan @EntityScan} |
||||
* annotations. |
||||
* @return the entity scan package names |
||||
*/ |
||||
public List<String> getPackageNames() { |
||||
return this.packageNames; |
||||
} |
||||
|
||||
/** |
||||
* Return the {@link EntityScanPackages} for the given bean factory. |
||||
* @param beanFactory the source bean factory |
||||
* @return the {@link EntityScanPackages} for the bean factory (never {@code null}) |
||||
*/ |
||||
public static EntityScanPackages get(BeanFactory beanFactory) { |
||||
// Currently we only store a single base package, but we return a list to
|
||||
// allow this to change in the future if needed
|
||||
try { |
||||
return beanFactory.getBean(BEAN, EntityScanPackages.class); |
||||
} |
||||
catch (NoSuchBeanDefinitionException ex) { |
||||
return NONE; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Register the specified entity scan packages with the system. |
||||
* @param registry the source registry |
||||
* @param packageNames the package names to register |
||||
*/ |
||||
public static void register(BeanDefinitionRegistry registry, String... packageNames) { |
||||
Assert.notNull(registry, "Registry must not be null"); |
||||
Assert.notNull(packageNames, "PackageNames must not be null"); |
||||
register(registry, Arrays.asList(packageNames)); |
||||
} |
||||
|
||||
/** |
||||
* Register the specified entity scan packages with the system. |
||||
* @param registry the source registry |
||||
* @param packageNames the package names to register |
||||
*/ |
||||
public static void register(BeanDefinitionRegistry registry, |
||||
Collection<String> packageNames) { |
||||
Assert.notNull(registry, "Registry must not be null"); |
||||
Assert.notNull(packageNames, "PackageNames must not be null"); |
||||
if (registry.containsBeanDefinition(BEAN)) { |
||||
BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN); |
||||
ConstructorArgumentValues constructorArguments = beanDefinition |
||||
.getConstructorArgumentValues(); |
||||
constructorArguments.addIndexedArgumentValue(0, |
||||
addPackageNames(constructorArguments, packageNames)); |
||||
} |
||||
else { |
||||
GenericBeanDefinition beanDefinition = new GenericBeanDefinition(); |
||||
beanDefinition.setBeanClass(EntityScanPackages.class); |
||||
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, |
||||
packageNames.toArray(new String[packageNames.size()])); |
||||
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); |
||||
registry.registerBeanDefinition(BEAN, beanDefinition); |
||||
} |
||||
} |
||||
|
||||
private static String[] addPackageNames( |
||||
ConstructorArgumentValues constructorArguments, |
||||
Collection<String> packageNames) { |
||||
String[] existing = (String[]) constructorArguments |
||||
.getIndexedArgumentValue(0, String[].class).getValue(); |
||||
Set<String> merged = new LinkedHashSet<String>(); |
||||
merged.addAll(Arrays.asList(existing)); |
||||
merged.addAll(packageNames); |
||||
return merged.toArray(new String[merged.size()]); |
||||
} |
||||
|
||||
/** |
||||
* {@link ImportBeanDefinitionRegistrar} to store the base package from the importing |
||||
* configuration. |
||||
*/ |
||||
@Order(Ordered.HIGHEST_PRECEDENCE) |
||||
static class Registrar implements ImportBeanDefinitionRegistrar { |
||||
|
||||
@Override |
||||
public void registerBeanDefinitions(AnnotationMetadata metadata, |
||||
BeanDefinitionRegistry registry) { |
||||
register(registry, getPackagesToScan(metadata)); |
||||
} |
||||
|
||||
private Set<String> getPackagesToScan(AnnotationMetadata metadata) { |
||||
AnnotationAttributes attributes = AnnotationAttributes.fromMap( |
||||
metadata.getAnnotationAttributes(EntityScan.class.getName())); |
||||
String[] basePackages = attributes.getStringArray("basePackages"); |
||||
Class<?>[] basePackageClasses = attributes |
||||
.getClassArray("basePackageClasses"); |
||||
Set<String> packagesToScan = new LinkedHashSet<String>(); |
||||
packagesToScan.addAll(Arrays.asList(basePackages)); |
||||
for (Class<?> basePackageClass : basePackageClasses) { |
||||
packagesToScan.add(ClassUtils.getPackageName(basePackageClass)); |
||||
} |
||||
if (packagesToScan.isEmpty()) { |
||||
String packageName = ClassUtils.getPackageName(metadata.getClassName()); |
||||
Assert.state(!StringUtils.isEmpty(packageName), |
||||
"@EntityScan cannot be used with the default package"); |
||||
return Collections.singleton(packageName); |
||||
} |
||||
return packagesToScan; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,95 @@
@@ -0,0 +1,95 @@
|
||||
/* |
||||
* Copyright 2012-2016 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 |
||||
* |
||||
* http://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.boot.autoconfigure.domain; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
import java.util.Collections; |
||||
import java.util.HashSet; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition; |
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackages; |
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; |
||||
import org.springframework.core.type.filter.AnnotationTypeFilter; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.ClassUtils; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* An entity scanner that searches the classpath from a {@link EntityScan @EntityScan} |
||||
* specified packages. |
||||
* |
||||
* @author Phillip Webb |
||||
* @since 1.4.0 |
||||
*/ |
||||
public class EntityScanner { |
||||
|
||||
private final ApplicationContext context; |
||||
|
||||
/** |
||||
* Create a new {@link EntityScanner} instance. |
||||
* @param context the source application context |
||||
*/ |
||||
public EntityScanner(ApplicationContext context) { |
||||
Assert.notNull(context, "Context must not be null"); |
||||
this.context = context; |
||||
} |
||||
|
||||
/** |
||||
* Scan for entities with the specified annotations. |
||||
* @param annotationTypes the annotation types used on the entities |
||||
* @return a set of entity classes |
||||
* @throws ClassNotFoundException if an entity class cannot be loaded |
||||
*/ |
||||
@SafeVarargs |
||||
public final Set<Class<?>> scan(Class<? extends Annotation>... annotationTypes) |
||||
throws ClassNotFoundException { |
||||
List<String> packages = getPackages(); |
||||
if (packages.isEmpty()) { |
||||
return Collections.<Class<?>>emptySet(); |
||||
} |
||||
Set<Class<?>> entitySet = new HashSet<Class<?>>(); |
||||
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider( |
||||
false); |
||||
scanner.setEnvironment(this.context.getEnvironment()); |
||||
scanner.setResourceLoader(this.context); |
||||
for (Class<? extends Annotation> annotationType : annotationTypes) { |
||||
scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType)); |
||||
} |
||||
for (String basePackage : packages) { |
||||
if (StringUtils.hasText(basePackage)) { |
||||
for (BeanDefinition candidate : scanner |
||||
.findCandidateComponents(basePackage)) { |
||||
entitySet.add(ClassUtils.forName(candidate.getBeanClassName(), |
||||
this.context.getClassLoader())); |
||||
} |
||||
} |
||||
} |
||||
return entitySet; |
||||
} |
||||
|
||||
private List<String> getPackages() { |
||||
List<String> packages = EntityScanPackages.get(this.context).getPackageNames(); |
||||
if (packages.isEmpty() && AutoConfigurationPackages.has(this.context)) { |
||||
packages = AutoConfigurationPackages.get(this.context); |
||||
} |
||||
return packages; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,191 @@
@@ -0,0 +1,191 @@
|
||||
/* |
||||
* Copyright 2012-2016 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 |
||||
* |
||||
* http://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.boot.autoconfigure.domain; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
|
||||
import org.junit.After; |
||||
import org.junit.Rule; |
||||
import org.junit.Test; |
||||
import org.junit.rules.ExpectedException; |
||||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.core.annotation.AnnotationConfigurationException; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* Tests for {@link EntityScanPackages}. |
||||
* |
||||
* @author Phillip Webb |
||||
*/ |
||||
public class EntityScanPackagesTests { |
||||
|
||||
private AnnotationConfigApplicationContext context; |
||||
|
||||
@Rule |
||||
public ExpectedException thrown = ExpectedException.none(); |
||||
|
||||
@After |
||||
public void cleanup() { |
||||
if (this.context != null) { |
||||
this.context.close(); |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void getWhenNoneRegisteredShouldReturnNone() throws Exception { |
||||
this.context = new AnnotationConfigApplicationContext(); |
||||
this.context.refresh(); |
||||
EntityScanPackages packages = EntityScanPackages.get(this.context); |
||||
assertThat(packages).isNotNull(); |
||||
assertThat(packages.getPackageNames()).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void getShouldReturnRegisterPackages() throws Exception { |
||||
this.context = new AnnotationConfigApplicationContext(); |
||||
EntityScanPackages.register(this.context, "a", "b"); |
||||
EntityScanPackages.register(this.context, "b", "c"); |
||||
this.context.refresh(); |
||||
EntityScanPackages packages = EntityScanPackages.get(this.context); |
||||
assertThat(packages.getPackageNames()).containsExactly("a", "b", "c"); |
||||
} |
||||
|
||||
@Test |
||||
public void registerFromArrayWhenRegistryIsNullShouldThrowException() |
||||
throws Exception { |
||||
this.thrown.expect(IllegalArgumentException.class); |
||||
this.thrown.expectMessage("Registry must not be null"); |
||||
EntityScanPackages.register(null); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void registerFromArrayWhenPackageNamesIsNullShouldThrowException() |
||||
throws Exception { |
||||
this.context = new AnnotationConfigApplicationContext(); |
||||
this.thrown.expect(IllegalArgumentException.class); |
||||
this.thrown.expectMessage("PackageNames must not be null"); |
||||
EntityScanPackages.register(this.context, (String[]) null); |
||||
} |
||||
|
||||
@Test |
||||
public void registerFromCollectionWhenRegistryIsNullShouldThrowException() |
||||
throws Exception { |
||||
this.thrown.expect(IllegalArgumentException.class); |
||||
this.thrown.expectMessage("Registry must not be null"); |
||||
EntityScanPackages.register(null, Collections.<String>emptyList()); |
||||
} |
||||
|
||||
@Test |
||||
public void registerFromCollectionWhenPackageNamesIsNullShouldThrowException() |
||||
throws Exception { |
||||
this.context = new AnnotationConfigApplicationContext(); |
||||
this.thrown.expect(IllegalArgumentException.class); |
||||
this.thrown.expectMessage("PackageNames must not be null"); |
||||
EntityScanPackages.register(this.context, (Collection<String>) null); |
||||
} |
||||
|
||||
@Test |
||||
public void entityScanAnnotationWhenHasValueAttributeShouldSetupPackages() |
||||
throws Exception { |
||||
this.context = new AnnotationConfigApplicationContext( |
||||
EntityScanValueConfig.class); |
||||
EntityScanPackages packages = EntityScanPackages.get(this.context); |
||||
assertThat(packages.getPackageNames()).containsExactly("a"); |
||||
} |
||||
|
||||
@Test |
||||
public void entityScanAnnotationWhenHasBasePackagesAttributeShouldSetupPackages() |
||||
throws Exception { |
||||
this.context = new AnnotationConfigApplicationContext( |
||||
EntityScanBasePackagesConfig.class); |
||||
EntityScanPackages packages = EntityScanPackages.get(this.context); |
||||
assertThat(packages.getPackageNames()).containsExactly("b"); |
||||
} |
||||
|
||||
@Test |
||||
public void entityScanAnnotationWhenHasValueAndBasePackagesAttributeShouldThrow() |
||||
throws Exception { |
||||
this.thrown.expect(AnnotationConfigurationException.class); |
||||
this.context = new AnnotationConfigApplicationContext( |
||||
EntityScanValueAndBasePackagesConfig.class); |
||||
} |
||||
|
||||
@Test |
||||
public void entityScanAnnotationWhenHasBasePackageClassesAttributeShouldSetupPackages() |
||||
throws Exception { |
||||
this.context = new AnnotationConfigApplicationContext( |
||||
EntityScanBasePackageClassesConfig.class); |
||||
EntityScanPackages packages = EntityScanPackages.get(this.context); |
||||
assertThat(packages.getPackageNames()) |
||||
.containsExactly(getClass().getPackage().getName()); |
||||
} |
||||
|
||||
@Test |
||||
public void entityScanAnnotationWhenNoAttributesShouldSetupPackages() |
||||
throws Exception { |
||||
this.context = new AnnotationConfigApplicationContext( |
||||
EntityScanNoAttributesConfig.class); |
||||
EntityScanPackages packages = EntityScanPackages.get(this.context); |
||||
assertThat(packages.getPackageNames()) |
||||
.containsExactly(getClass().getPackage().getName()); |
||||
} |
||||
|
||||
@Test |
||||
public void entityScanAnnotationWhenLoadingFromMultipleConfigsShouldCombinePackages() |
||||
throws Exception { |
||||
this.context = new AnnotationConfigApplicationContext(EntityScanValueConfig.class, |
||||
EntityScanBasePackagesConfig.class); |
||||
EntityScanPackages packages = EntityScanPackages.get(this.context); |
||||
assertThat(packages.getPackageNames()).containsExactly("a", "b"); |
||||
} |
||||
|
||||
@Configuration |
||||
@EntityScan("a") |
||||
static class EntityScanValueConfig { |
||||
|
||||
} |
||||
|
||||
@Configuration |
||||
@EntityScan(basePackages = "b") |
||||
static class EntityScanBasePackagesConfig { |
||||
|
||||
} |
||||
|
||||
@Configuration |
||||
@EntityScan(value = "a", basePackages = "b") |
||||
static class EntityScanValueAndBasePackagesConfig { |
||||
|
||||
} |
||||
|
||||
@Configuration |
||||
@EntityScan(basePackageClasses = EntityScanPackagesTests.class) |
||||
static class EntityScanBasePackageClassesConfig { |
||||
|
||||
} |
||||
|
||||
@Configuration |
||||
@EntityScan |
||||
static class EntityScanNoAttributesConfig { |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,109 @@
@@ -0,0 +1,109 @@
|
||||
/* |
||||
* Copyright 2012-2016 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 |
||||
* |
||||
* http://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.boot.autoconfigure.domain; |
||||
|
||||
import java.util.Set; |
||||
|
||||
import javax.persistence.Embeddable; |
||||
import javax.persistence.Entity; |
||||
|
||||
import org.junit.Rule; |
||||
import org.junit.Test; |
||||
import org.junit.rules.ExpectedException; |
||||
|
||||
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; |
||||
import org.springframework.boot.autoconfigure.domain.scan.b.EntityB; |
||||
import org.springframework.boot.autoconfigure.domain.scan.c.EmbeddableC; |
||||
import org.springframework.boot.autoconfigure.domain.scan.c.EntityC; |
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* Tests for {@link EntityScanner}. |
||||
* |
||||
* @author Phillip Webb |
||||
*/ |
||||
public class EntityScannerTests { |
||||
|
||||
@Rule |
||||
public ExpectedException thrown = ExpectedException.none(); |
||||
|
||||
@Test |
||||
public void createWhenContextIsNullShouldThrowException() throws Exception { |
||||
this.thrown.expect(IllegalArgumentException.class); |
||||
this.thrown.expectMessage("Context must not be null"); |
||||
new EntityScanner(null); |
||||
} |
||||
|
||||
@Test |
||||
public void scanShouldScanFromSinglePackage() throws Exception { |
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( |
||||
ScanConfig.class); |
||||
EntityScanner scanner = new EntityScanner(context); |
||||
Set<Class<?>> scanned = scanner.scan(Entity.class); |
||||
assertThat(scanned).containsOnly(EntityA.class, EntityB.class, EntityC.class); |
||||
context.close(); |
||||
} |
||||
|
||||
@Test |
||||
public void scanShouldScanFromMultiplePackages() throws Exception { |
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( |
||||
ScanAConfig.class, ScanBConfig.class); |
||||
EntityScanner scanner = new EntityScanner(context); |
||||
Set<Class<?>> scanned = scanner.scan(Entity.class); |
||||
assertThat(scanned).containsOnly(EntityA.class, EntityB.class); |
||||
context.close(); |
||||
} |
||||
|
||||
@Test |
||||
public void scanShouldFilterOnAnnotation() throws Exception { |
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( |
||||
ScanConfig.class); |
||||
EntityScanner scanner = new EntityScanner(context); |
||||
assertThat(scanner.scan(Entity.class)).containsOnly(EntityA.class, EntityB.class, |
||||
EntityC.class); |
||||
assertThat(scanner.scan(Embeddable.class)).containsOnly(EmbeddableA.class, |
||||
EmbeddableB.class, EmbeddableC.class); |
||||
assertThat(scanner.scan(Entity.class, Embeddable.class)).containsOnly( |
||||
EntityA.class, EntityB.class, EntityC.class, EmbeddableA.class, |
||||
EmbeddableB.class, EmbeddableC.class); |
||||
context.close(); |
||||
} |
||||
|
||||
@Configuration |
||||
@EntityScan("org.springframework.boot.autoconfigure.domain.scan") |
||||
static class ScanConfig { |
||||
|
||||
} |
||||
|
||||
@Configuration |
||||
@EntityScan(basePackageClasses = EntityA.class) |
||||
static class ScanAConfig { |
||||
|
||||
} |
||||
|
||||
@Configuration |
||||
@EntityScan(basePackageClasses = EntityB.class) |
||||
static class ScanBConfig { |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2012-2016 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 |
||||
* |
||||
* http://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.boot.autoconfigure.domain.scan.a; |
||||
|
||||
import javax.persistence.Embeddable; |
||||
|
||||
@Embeddable |
||||
public class EmbeddableA { |
||||
|
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2012-2016 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 |
||||
* |
||||
* http://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.boot.autoconfigure.domain.scan.a; |
||||
|
||||
import javax.persistence.Entity; |
||||
|
||||
@Entity |
||||
public class EntityA { |
||||
|
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2012-2016 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 |
||||
* |
||||
* http://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.boot.autoconfigure.domain.scan.b; |
||||
|
||||
import javax.persistence.Embeddable; |
||||
|
||||
@Embeddable |
||||
public class EmbeddableB { |
||||
|
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2012-2016 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 |
||||
* |
||||
* http://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.boot.autoconfigure.domain.scan.b; |
||||
|
||||
import javax.persistence.Entity; |
||||
|
||||
@Entity |
||||
public class EntityB { |
||||
|
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2012-2016 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 |
||||
* |
||||
* http://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.boot.autoconfigure.domain.scan.c; |
||||
|
||||
import javax.persistence.Embeddable; |
||||
|
||||
@Embeddable |
||||
public class EmbeddableC { |
||||
|
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2012-2016 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 |
||||
* |
||||
* http://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.boot.autoconfigure.domain.scan.c; |
||||
|
||||
import javax.persistence.Entity; |
||||
|
||||
@Entity |
||||
public class EntityC { |
||||
|
||||
} |
||||
Loading…
Reference in new issue