DATACMNS-47 - Add support for JavaConfig based repository configuration.
Completely rewrote namespace bean definition parsing to be extendable more easily. Separated XML concerns from annotation based configuration. The central point to extend the namespace parsing for a certain module is now hidden behind the RepositoryConfigurationExtension interface (have a look at the RepositoryConfigurationExtensionSupport base class as well).
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2012 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.data.repository.config;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.StandardAnnotationMetadata;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AnnotationRepositoryConfigurationSource}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AnnotationRepositoryConfigurationSourceUnitTests {
|
||||
|
||||
RepositoryConfigurationSource source;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
AnnotationMetadata annotationMetadata = new StandardAnnotationMetadata(SampleConfiguration.class, true);
|
||||
source = new AnnotationRepositoryConfigurationSource(annotationMetadata, EnableRepositories.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsBasePackagesForClasses() {
|
||||
|
||||
Iterable<String> basePackages = source.getBasePackages();
|
||||
assertThat(basePackages, hasItem(AnnotationRepositoryConfigurationSourceUnitTests.class.getPackage().getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evaluatesExcludeFiltersCorrectly() {
|
||||
|
||||
Collection<String> candidates = source.getCandidates(new DefaultResourceLoader());
|
||||
assertThat(candidates, hasSize(1));
|
||||
assertThat(candidates, hasItem(MyRepository.class.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultsToPackageOfAnnotatedClass() {
|
||||
|
||||
AnnotationMetadata metadata = new StandardAnnotationMetadata(DefaultConfiguration.class);
|
||||
RepositoryConfigurationSource source = new AnnotationRepositoryConfigurationSource(metadata,
|
||||
EnableRepositories.class);
|
||||
|
||||
Iterable<String> packages = source.getBasePackages();
|
||||
assertThat(packages, hasItem(DefaultConfiguration.class.getPackage().getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsConfiguredBasePackage() {
|
||||
|
||||
AnnotationMetadata metadata = new StandardAnnotationMetadata(DefaultConfigurationWithBasePackage.class);
|
||||
RepositoryConfigurationSource source = new AnnotationRepositoryConfigurationSource(metadata,
|
||||
EnableRepositories.class);
|
||||
|
||||
Iterable<String> packages = source.getBasePackages();
|
||||
assertThat(packages, hasItem("foo"));
|
||||
}
|
||||
|
||||
public static class Person {
|
||||
|
||||
}
|
||||
|
||||
@EnableRepositories
|
||||
static class DefaultConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@EnableRepositories(basePackages = "foo")
|
||||
static class DefaultConfigurationWithBasePackage {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2012 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.data.repository.config;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DefaultRepositoryConfiguration}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DefaultRepositoryConfigurationUnitTests {
|
||||
|
||||
@Mock
|
||||
RepositoryConfigurationSource source;
|
||||
|
||||
@Test
|
||||
public void supportsBasicConfiguration() {
|
||||
|
||||
RepositoryConfiguration<RepositoryConfigurationSource> configuration = new DefaultRepositoryConfiguration<RepositoryConfigurationSource>(
|
||||
source, "com.acme.MyRepository");
|
||||
|
||||
assertThat(configuration.getBeanId(), is("myRepository"));
|
||||
assertThat(configuration.getConfigurationSource(), is(source));
|
||||
assertThat(configuration.getImplementationBeanName(), is("myRepositoryImpl"));
|
||||
assertThat(configuration.getImplementationClassName(), is("MyRepositoryImpl"));
|
||||
assertThat(configuration.getRepositoryInterface(), is("com.acme.MyRepository"));
|
||||
assertThat(configuration.getQueryLookupStrategyKey(), is((Object) Key.CREATE_IF_NOT_FOUND));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2012 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.data.repository.config;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface EnableRepositories {
|
||||
|
||||
String[] value() default {};
|
||||
|
||||
String[] basePackages() default {};
|
||||
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
|
||||
Filter[] includeFilters() default {};
|
||||
|
||||
Filter[] excludeFilters() default {};
|
||||
|
||||
Class<?> repositoryFactoryBeanClass() default RepositoryFactoryBeanSupport.class;
|
||||
|
||||
String namedQueriesLocation() default "";
|
||||
|
||||
String repositoryImplementationPostfix() default "Impl";
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2012 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.data.repository.config;
|
||||
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSourceUnitTests.Person;
|
||||
|
||||
interface MyOtherRepository extends Repository<Person, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2012 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.data.repository.config;
|
||||
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSourceUnitTests.Person;
|
||||
|
||||
interface MyRepository extends Repository<Person, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2012 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.data.repository.config;
|
||||
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.StandardAnnotationMetadata;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
|
||||
|
||||
/**
|
||||
* Integration test for {@link RepositoryBeanDefinitionRegistrarSupport}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RepositoryBeanDefinitionRegistrarSupportIntegrationTests {
|
||||
|
||||
@Mock
|
||||
BeanDefinitionRegistry registry;
|
||||
|
||||
@Test
|
||||
public void registersBeanDefinitionForFoundBean() {
|
||||
|
||||
AnnotationMetadata metadata = new StandardAnnotationMetadata(SampleConfiguration.class, true);
|
||||
DummyRegistrar registrar = new DummyRegistrar();
|
||||
registrar.registerBeanDefinitions(metadata, registry);
|
||||
|
||||
verify(registry, times(1)).registerBeanDefinition(eq("myRepository"), any(BeanDefinition.class));
|
||||
}
|
||||
|
||||
private static class DummyRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport#getAnnotation()
|
||||
*/
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotation() {
|
||||
return EnableRepositories.class;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport#getExtension()
|
||||
*/
|
||||
@Override
|
||||
protected RepositoryConfigurationExtension getExtension() {
|
||||
return new RepositoryConfigurationExtensionSupport() {
|
||||
|
||||
public String getRepositoryFactoryClassName() {
|
||||
return RepositoryFactoryBeanSupport.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getModulePrefix() {
|
||||
return "commons";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
* Copyright 2012 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.
|
||||
@@ -18,12 +18,15 @@ package org.springframework.data.repository.config;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.config.AbstractRepositoryConfigDefinitionParser.RepositoryComponentProvider;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.data.repository.sample.SampleAnnotatedRepository;
|
||||
|
||||
/**
|
||||
@@ -36,10 +39,22 @@ public class RepositoryComponentProviderUnitTests {
|
||||
@Test
|
||||
public void findsAnnotatedRepositoryInterface() {
|
||||
|
||||
RepositoryComponentProvider provider = new RepositoryComponentProvider(Repository.class);
|
||||
RepositoryComponentProvider provider = new RepositoryComponentProvider(Collections.<TypeFilter> emptyList());
|
||||
Set<BeanDefinition> components = provider.findCandidateComponents("org.springframework.data.repository.sample");
|
||||
|
||||
assertThat(components.size(), is(1));
|
||||
assertThat(components.iterator().next().getBeanClassName(), is(SampleAnnotatedRepository.class.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void limitsFoundRepositoriesToIncludeFiltersOnly() {
|
||||
|
||||
List<? extends TypeFilter> filters = Arrays.asList(new AssignableTypeFilter(MyOtherRepository.class));
|
||||
|
||||
RepositoryComponentProvider provider = new RepositoryComponentProvider(filters);
|
||||
Set<BeanDefinition> components = provider.findCandidateComponents("org.springframework.data.repository");
|
||||
|
||||
assertThat(components.size(), is(1));
|
||||
assertThat(components.iterator().next().getBeanClassName(), is(MyOtherRepository.class.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2012 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.data.repository.config;
|
||||
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
|
||||
@EnableRepositories(excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyOtherRepository.class), basePackageClasses = AnnotationRepositoryConfigurationSourceUnitTests.class)
|
||||
class SampleConfiguration {
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2008-2010 the original author or authors.
|
||||
* Copyright 2010-2012 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.
|
||||
@@ -15,13 +15,16 @@
|
||||
*/
|
||||
package org.springframework.data.repository.config;
|
||||
|
||||
import static org.mockito.Matchers.isA;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -32,6 +35,8 @@ import org.springframework.context.annotation.ClassPathScanningCandidateComponen
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.data.repository.config.TypeFilterParser.Type;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.SAXException;
|
||||
@@ -44,22 +49,24 @@ import org.xml.sax.SAXException;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class TypeFilterParserUnitTests {
|
||||
|
||||
private TypeFilterParser parser;
|
||||
private Element documentElement;
|
||||
static final Matcher<Iterable<? super AssignableTypeFilter>> IS_ASSIGNABLE_TYPE_FILTER = hasItem(Matchers
|
||||
.isA(AssignableTypeFilter.class));
|
||||
|
||||
TypeFilterParser parser;
|
||||
Element documentElement;
|
||||
|
||||
@Mock
|
||||
private ClassLoader classLoader;
|
||||
ReaderContext context;
|
||||
@Mock
|
||||
ClassLoader classLoader;
|
||||
|
||||
@Mock
|
||||
private ReaderContext context;
|
||||
|
||||
@Mock
|
||||
private ClassPathScanningCandidateComponentProvider scanner;
|
||||
ClassPathScanningCandidateComponentProvider scanner;
|
||||
|
||||
@Before
|
||||
public void setUp() throws SAXException, IOException, ParserConfigurationException {
|
||||
|
||||
parser = new TypeFilterParser(classLoader, context);
|
||||
parser = new TypeFilterParser(context, classLoader);
|
||||
|
||||
Resource sampleXmlFile = new ClassPathResource("type-filter-test.xml", TypeFilterParserUnitTests.class);
|
||||
|
||||
@@ -74,9 +81,8 @@ public class TypeFilterParserUnitTests {
|
||||
|
||||
Element element = DomUtils.getChildElementByTagName(documentElement, "firstSample");
|
||||
|
||||
parser.parseFilters(element, scanner);
|
||||
|
||||
verify(scanner, atLeastOnce()).addIncludeFilter(isA(AssignableTypeFilter.class));
|
||||
Iterable<TypeFilter> filters = parser.parseTypeFilters(element, Type.INCLUDE);
|
||||
assertThat(filters, IS_ASSIGNABLE_TYPE_FILTER);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -84,8 +90,7 @@ public class TypeFilterParserUnitTests {
|
||||
|
||||
Element element = DomUtils.getChildElementByTagName(documentElement, "secondSample");
|
||||
|
||||
parser.parseFilters(element, scanner);
|
||||
|
||||
verify(scanner, atLeastOnce()).addExcludeFilter(isA(AssignableTypeFilter.class));
|
||||
Iterable<TypeFilter> filters = parser.parseTypeFilters(element, Type.EXCLUDE);
|
||||
assertThat(filters, IS_ASSIGNABLE_TYPE_FILTER);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user