Skip to content

Commit e4a84df

Browse files
committed
DATACMNS-1261 - Apply Java 8 Functional types and Lambdas to simplify parsing logic in Repository configuration.
Additionally, fix up Exception error messages and edit Javadoc.
1 parent ff22d0c commit e4a84df

10 files changed

+213
-65
lines changed

src/main/java/org/springframework/data/config/ConfigurationUtils.java

+8-14
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,13 @@ public interface ConfigurationUtils {
3737
* @return
3838
* @throws IllegalArgumentException if no {@link ResourceLoader} can be obtained from the {@link XmlReaderContext}.
3939
*/
40-
public static ResourceLoader getRequiredResourceLoader(XmlReaderContext context) {
40+
static ResourceLoader getRequiredResourceLoader(XmlReaderContext context) {
4141

4242
Assert.notNull(context, "XmlReaderContext must not be null!");
4343

4444
ResourceLoader resourceLoader = context.getResourceLoader();
4545

46-
if (resourceLoader == null) {
47-
throw new IllegalArgumentException("Could not obtain ResourceLoader from XmlReaderContext!");
48-
}
46+
Assert.notNull(resourceLoader, "Could not obtain ResourceLoader from XmlReaderContext!");
4947

5048
return resourceLoader;
5149
}
@@ -57,7 +55,7 @@ public static ResourceLoader getRequiredResourceLoader(XmlReaderContext context)
5755
* @return
5856
* @throws IllegalArgumentException if no {@link ClassLoader} can be obtained from the given {@link XmlReaderContext}.
5957
*/
60-
public static ClassLoader getRequiredClassLoader(XmlReaderContext context) {
58+
static ClassLoader getRequiredClassLoader(XmlReaderContext context) {
6159
return getRequiredClassLoader(getRequiredResourceLoader(context));
6260
}
6361

@@ -68,15 +66,13 @@ public static ClassLoader getRequiredClassLoader(XmlReaderContext context) {
6866
* @return
6967
* @throws IllegalArgumentException if the given {@link ResourceLoader} does not expose a {@link ClassLoader}.
7068
*/
71-
public static ClassLoader getRequiredClassLoader(ResourceLoader resourceLoader) {
69+
static ClassLoader getRequiredClassLoader(ResourceLoader resourceLoader) {
7270

7371
Assert.notNull(resourceLoader, "ResourceLoader must not be null!");
7472

7573
ClassLoader classLoader = resourceLoader.getClassLoader();
7674

77-
if (classLoader == null) {
78-
throw new IllegalArgumentException("Could not obtain ClassLoader from ResourceLoader!");
79-
}
75+
Assert.notNull(classLoader, "Could not obtain ClassLoader from ResourceLoader!");
8076

8177
return classLoader;
8278
}
@@ -88,16 +84,14 @@ public static ClassLoader getRequiredClassLoader(ResourceLoader resourceLoader)
8884
* @return
8985
* @throws IllegalArgumentException if the given {@link BeanDefinition} does not contain a bean class name.
9086
*/
91-
public static String getRequiredBeanClassName(BeanDefinition beanDefinition) {
87+
static String getRequiredBeanClassName(BeanDefinition beanDefinition) {
9288

9389
Assert.notNull(beanDefinition, "BeanDefinition must not be null!");
9490

9591
String result = beanDefinition.getBeanClassName();
9692

97-
if (result == null) {
98-
throw new IllegalArgumentException(
99-
String.format("Could not obtain required bean class name from BeanDefinition!", beanDefinition));
100-
}
93+
Assert.notNull(result, String.format("Could not obtain required bean class name from BeanDefinition [%s]!",
94+
beanDefinition));
10195

10296
return result;
10397
}

src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,8 @@ public AnnotationRepositoryConfigurationSource(AnnotationMetadata metadata, Clas
9393

9494
Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(annotation.getName());
9595

96-
if (annotationAttributes == null) {
97-
throw new IllegalStateException(String.format("Unable to obtain annotation attributes for %s!", annotation));
98-
}
96+
Assert.state(annotationAttributes != null,
97+
String.format("Unable to obtain annotation attributes for %s!", annotation));
9998

10099
this.attributes = new AnnotationAttributes(annotationAttributes);
101100
this.enableAnnotationMetadata = new StandardAnnotationMetadata(annotation);

src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,13 @@ public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanD
7676
AnnotationRepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(
7777
annotationMetadata, getAnnotation(), resourceLoader, environment, registry);
7878

79-
RepositoryConfigurationExtension extension = getExtension();
80-
RepositoryConfigurationUtils.exposeRegistration(extension, registry, configurationSource);
79+
RepositoryConfigurationExtension configurationExtension = getExtension();
80+
RepositoryConfigurationUtils.exposeRegistration(configurationExtension, registry, configurationSource);
8181

82-
RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configurationSource, resourceLoader,
83-
environment);
82+
RepositoryConfigurationDelegate delegate =
83+
new RepositoryConfigurationDelegate(configurationSource, resourceLoader, environment);
8484

85-
delegate.registerRepositoriesIn(registry, extension);
85+
delegate.registerRepositoriesIn(registry, configurationExtension);
8686
}
8787

8888
/**

src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java

+15-17
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.springframework.data.repository.Repository;
3737
import org.springframework.data.repository.RepositoryDefinition;
3838
import org.springframework.data.repository.util.ClassUtils;
39+
import org.springframework.data.util.IterableUtils;
3940
import org.springframework.util.Assert;
4041

4142
/**
@@ -61,15 +62,12 @@ public RepositoryComponentProvider(Iterable<? extends TypeFilter> includeFilters
6162

6263
super(false);
6364

64-
Assert.notNull(includeFilters, "Include filters must not be null!");
6565
Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
6666

6767
this.registry = registry;
6868

69-
if (includeFilters.iterator().hasNext()) {
70-
for (TypeFilter filter : includeFilters) {
71-
addIncludeFilter(filter);
72-
}
69+
if (IterableUtils.isNotEmpty(includeFilters)) {
70+
includeFilters.forEach(this::addIncludeFilter);
7371
} else {
7472
super.addIncludeFilter(new InterfaceTypeFilter(Repository.class));
7573
super.addIncludeFilter(new AnnotationTypeFilter(RepositoryDefinition.class, true, true));
@@ -79,9 +77,11 @@ public RepositoryComponentProvider(Iterable<? extends TypeFilter> includeFilters
7977
}
8078

8179
/**
82-
* Custom extension of {@link #addIncludeFilter(TypeFilter)} to extend the added {@link TypeFilter}. For the
83-
* {@link TypeFilter} handed we'll have two filters registered: one additionally enforcing the
84-
* {@link RepositoryDefinition} annotation, the other one forcing the extension of {@link Repository}.
80+
* Custom extension of {@link ClassPathScanningCandidateComponentProvider#addIncludeFilter(TypeFilter)}
81+
* to extend the added {@link TypeFilter}.
82+
*
83+
* For the {@link TypeFilter} handed we will have two filters registered: one additionally enforcing the
84+
* {@link RepositoryDefinition} annotation and the other forcing the extension of {@link Repository}.
8585
*
8686
* @see ClassPathScanningCandidateComponentProvider#addIncludeFilter(TypeFilter)
8787
*/
@@ -123,11 +123,8 @@ public Set<BeanDefinition> findCandidateComponents(String basePackage) {
123123

124124
Set<BeanDefinition> candidates = super.findCandidateComponents(basePackage);
125125

126-
for (BeanDefinition candidate : candidates) {
127-
if (candidate instanceof AnnotatedBeanDefinition) {
128-
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
129-
}
130-
}
126+
candidates.stream().filter(bd -> bd instanceof AnnotatedBeanDefinition).forEach(bd ->
127+
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) bd));
131128

132129
return candidates;
133130
}
@@ -153,7 +150,8 @@ public boolean isConsiderNestedRepositoryInterfaces() {
153150
* Controls whether nested inner-class {@link Repository} interface definitions should be considered for automatic
154151
* discovery. This defaults to {@literal false}.
155152
*
156-
* @param considerNestedRepositoryInterfaces
153+
* @param considerNestedRepositoryInterfaces boolean value indicating whether nested inner-class {@link Repository}
154+
* interface definitions should be considered for automatic discovery.
157155
*/
158156
public void setConsiderNestedRepositoryInterfaces(boolean considerNestedRepositoryInterfaces) {
159157
this.considerNestedRepositoryInterfaces = considerNestedRepositoryInterfaces;
@@ -170,9 +168,9 @@ private static class InterfaceTypeFilter extends AssignableTypeFilter {
170168
/**
171169
* Creates a new {@link InterfaceTypeFilter}.
172170
*
173-
* @param targetType
171+
* @param targetType {@link Class type} of the interface.
174172
*/
175-
public InterfaceTypeFilter(Class<?> targetType) {
173+
private InterfaceTypeFilter(Class<?> targetType) {
176174
super(targetType);
177175
}
178176

@@ -202,7 +200,7 @@ private static class AllTypeFilter implements TypeFilter {
202200
*
203201
* @param delegates must not be {@literal null}.
204202
*/
205-
public AllTypeFilter(List<TypeFilter> delegates) {
203+
private AllTypeFilter(List<TypeFilter> delegates) {
206204

207205
Assert.notNull(delegates, "TypeFilter deleages must not be null!");
208206
this.delegates = delegates;

src/main/java/org/springframework/data/repository/config/RepositoryConfigurationDelegate.java

+20-15
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.springframework.core.env.StandardEnvironment;
3232
import org.springframework.core.io.ResourceLoader;
3333
import org.springframework.core.io.support.SpringFactoriesLoader;
34+
import org.springframework.data.repository.Repository;
3435
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
3536
import org.springframework.util.Assert;
3637

@@ -69,12 +70,13 @@ public class RepositoryConfigurationDelegate {
6970
public RepositoryConfigurationDelegate(RepositoryConfigurationSource configurationSource,
7071
ResourceLoader resourceLoader, Environment environment) {
7172

72-
this.isXml = configurationSource instanceof XmlRepositoryConfigurationSource;
73+
Assert.notNull(resourceLoader, "ResourceLoader must not be null!");
74+
7375
boolean isAnnotation = configurationSource instanceof AnnotationRepositoryConfigurationSource;
76+
this.isXml = configurationSource instanceof XmlRepositoryConfigurationSource;
7477

75-
Assert.isTrue(isXml || isAnnotation,
76-
"Configuration source must either be an Xml- or an AnnotationBasedConfigurationSource!");
77-
Assert.notNull(resourceLoader, "ResourceLoader must not be null!");
78+
Assert.isTrue(this.isXml || isAnnotation,
79+
"Configuration source must either be an XML-based or an Annotation-based RepositoryConfigurationSource!");
7880

7981
this.configurationSource = configurationSource;
8082
this.resourceLoader = resourceLoader;
@@ -83,12 +85,14 @@ public RepositoryConfigurationDelegate(RepositoryConfigurationSource configurati
8385
}
8486

8587
/**
86-
* Defaults the environment in case the given one is null. Used as fallback, in case the legacy constructor was
87-
* invoked.
88+
* Defaults the {@link Environment} in case the given one is {@literal null}.
89+
*
90+
* Used as fallback in case the legacy constructor was invoked.
8891
*
8992
* @param environment can be {@literal null}.
9093
* @param resourceLoader can be {@literal null}.
91-
* @return
94+
* @return the given {@link Environment} if not {@literal null} or an {@link Environment} obtained
95+
* from the {@link ResourceLoader} if {@link ResourceLoader} is {@link EnvironmentCapable}.
9296
*/
9397
private static Environment defaultEnvironment(@Nullable Environment environment,
9498
@Nullable ResourceLoader resourceLoader) {
@@ -104,21 +108,22 @@ private static Environment defaultEnvironment(@Nullable Environment environment,
104108
/**
105109
* Registers the found repositories in the given {@link BeanDefinitionRegistry}.
106110
*
107-
* @param registry
108-
* @param extension
109-
* @return {@link BeanComponentDefinition}s for all repository bean definitions found.
111+
* @param registry {@link BeanDefinitionRegistry} used to register {@link Repository Repositories}.
112+
* @param extension {@link RepositoryConfigurationExtension} containing store specific configuration meta-data.
113+
* @return {@link BeanComponentDefinition}s for all {@link Repository} bean definitions found.
110114
*/
111115
public List<BeanComponentDefinition> registerRepositoriesIn(BeanDefinitionRegistry registry,
112116
RepositoryConfigurationExtension extension) {
113117

114118
extension.registerBeansForRoot(registry, configurationSource);
115119

116-
RepositoryBeanDefinitionBuilder builder = new RepositoryBeanDefinitionBuilder(registry, extension, resourceLoader,
117-
environment);
120+
RepositoryBeanDefinitionBuilder builder =
121+
new RepositoryBeanDefinitionBuilder(registry, extension, resourceLoader, environment);
122+
118123
List<BeanComponentDefinition> definitions = new ArrayList<>();
119124

120-
for (RepositoryConfiguration<? extends RepositoryConfigurationSource> configuration : extension
121-
.getRepositoryConfigurations(configurationSource, resourceLoader, inMultiStoreMode)) {
125+
for (RepositoryConfiguration<? extends RepositoryConfigurationSource> configuration
126+
: extension.getRepositoryConfigurations(configurationSource, resourceLoader, inMultiStoreMode)) {
122127

123128
BeanDefinitionBuilder definitionBuilder = builder.build(configuration);
124129

@@ -152,7 +157,7 @@ public List<BeanComponentDefinition> registerRepositoriesIn(BeanDefinitionRegist
152157
* than a single type is considered a multi-store configuration scenario which will trigger stricter repository
153158
* scanning.
154159
*
155-
* @return
160+
* @return a boolean value indicating if multiple Spring Data store implementations are present on the classpath.
156161
*/
157162
private boolean multipleStoresDetected() {
158163

src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public Streamable<BeanDefinition> getCandidates(ResourceLoader loader) {
7272
scanner.setEnvironment(environment);
7373
scanner.setResourceLoader(loader);
7474

75-
getExcludeFilters().forEach(it -> scanner.addExcludeFilter(it));
75+
getExcludeFilters().forEach(scanner::addExcludeFilter);
7676

7777
return Streamable.of(() -> getBasePackages().stream()//
7878
.flatMap(it -> scanner.findCandidateComponents(it).stream()));

src/main/java/org/springframework/data/repository/query/Parameters.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package org.springframework.data.repository.query;
1717

18-
import static java.lang.String.*;
19-
2018
import java.lang.reflect.Method;
2119
import java.util.ArrayList;
2220
import java.util.Arrays;
@@ -41,11 +39,13 @@ public abstract class Parameters<S extends Parameters<S, T>, T extends Parameter
4139

4240
public static final List<Class<?>> TYPES = Arrays.asList(Pageable.class, Sort.class);
4341

44-
private static final String PARAM_ON_SPECIAL = format("You must not user @%s on a parameter typed %s or %s",
45-
Param.class.getSimpleName(), Pageable.class.getSimpleName(), Sort.class.getSimpleName());
46-
private static final String ALL_OR_NOTHING = String.format(
47-
"Either use @%s on all parameters except %s and %s typed once, or none at all!", Param.class.getSimpleName(),
48-
Pageable.class.getSimpleName(), Sort.class.getSimpleName());
42+
private static final String PARAM_ON_SPECIAL =
43+
String.format("You must not use @%s on a parameter typed %s or %s",
44+
Param.class.getSimpleName(), Pageable.class.getSimpleName(), Sort.class.getSimpleName());
45+
46+
private static final String ALL_OR_NOTHING =
47+
String.format("Either use @%s on all parameters except parameters of type %s and %s, or none at all!",
48+
Param.class.getSimpleName(), Pageable.class.getSimpleName(), Sort.class.getSimpleName());
4949

5050
private final ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
5151
private final int pageableIndex;

src/main/java/org/springframework/data/repository/query/QueryMethod.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,11 @@ public QueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory
6969

7070
Parameters.TYPES.stream()//
7171
.filter(type -> getNumberOfOccurences(method, type) > 1)//
72-
.findFirst().ifPresent(type -> {
72+
.findFirst()
73+
.ifPresent(type -> {
7374
throw new IllegalStateException(
74-
String.format("Method must only one argument of type %s! Offending method: %s", type.getSimpleName(),
75-
method.toString()));
75+
String.format("Method must only have one argument of type %s! Offending method: %s",
76+
type.getSimpleName(), method.toString()));
7677
});
7778

7879
this.method = method;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2012-2018 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+
* http://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+
package org.springframework.data.util;
17+
18+
import java.util.Collections;
19+
20+
import org.springframework.lang.NonNull;
21+
import org.springframework.lang.Nullable;
22+
23+
/**
24+
* Utility class for working with {@link Iterable} objects.
25+
*
26+
* @author John Blum
27+
* @see java.lang.Iterable
28+
* @since 2.1.0
29+
*/
30+
public abstract class IterableUtils {
31+
32+
/**
33+
* Determines whether the given {@link Iterable} is empty.
34+
*
35+
* @param iterable {@link Iterable} to evaluate; can be {@literal null}.
36+
* @return {@literal true} if the given {@link Iterable} is empty,
37+
* otherwise return {@literal false}.
38+
* @see #nullSafeIterable(Iterable)
39+
* @see java.lang.Iterable
40+
*/
41+
public static boolean isEmpty(@Nullable Iterable<?> iterable) {
42+
return !isNotEmpty(iterable);
43+
}
44+
45+
/**
46+
* Determines if the given {@link Iterable} is not empty.
47+
*
48+
* @param iterable {@link Iterable} to evaluate; can be {@literal null}.
49+
* @return {@literal true} if the given {@link Iterable} is not empty,
50+
* otherwise return {@literal false}.
51+
* @see #nullSafeIterable(Iterable)
52+
* @see java.lang.Iterable
53+
*/
54+
public static boolean isNotEmpty(@Nullable Iterable<?> iterable) {
55+
return nullSafeIterable(iterable).iterator().hasNext();
56+
}
57+
58+
/**
59+
* Protects against {@literal null} {@link Iterable} references.
60+
*
61+
* @param <T> {@link Class type} of elements contained by the {@link Iterable}.
62+
* @param it {@link Iterable} to safe-guard from {@literal null}.
63+
* @return the given {@link Iterable} if not {@literal null} or an empty {@link Iterable}.
64+
* @see java.lang.Iterable
65+
*/
66+
@NonNull
67+
public static <T> Iterable<T> nullSafeIterable(@Nullable Iterable<T> it) {
68+
return it != null ? it : Collections::emptyIterator;
69+
}
70+
}

0 commit comments

Comments
 (0)