Skip to content

Commit 0e699a2

Browse files
mp911dechristophstrobl
authored andcommitted
Polishing.
Align nullness/nullability wording. Use template methods instead of functions to create exceptions. Original Pull Request: #3244
1 parent 2894ff3 commit 0e699a2

File tree

4 files changed

+62
-46
lines changed

4 files changed

+62
-46
lines changed

Diff for: src/main/java/org/springframework/data/projection/ProxyProjectionFactory.java

+8-5
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,16 @@
2424

2525
import org.aopalliance.intercept.MethodInterceptor;
2626
import org.aopalliance.intercept.MethodInvocation;
27+
2728
import org.springframework.aop.framework.Advised;
2829
import org.springframework.aop.framework.ProxyFactory;
2930
import org.springframework.beans.factory.BeanClassLoaderAware;
3031
import org.springframework.core.convert.support.DefaultConversionService;
3132
import org.springframework.core.convert.support.GenericConversionService;
3233
import org.springframework.data.convert.Jsr310Converters;
3334
import org.springframework.data.util.Lazy;
34-
import org.springframework.data.util.NullabilityMethodInvocationValidator;
3535
import org.springframework.data.util.NullableWrapperConverters;
36+
import org.springframework.data.util.NullnessMethodInvocationValidator;
3637
import org.springframework.lang.Nullable;
3738
import org.springframework.util.Assert;
3839
import org.springframework.util.ClassUtils;
@@ -67,8 +68,8 @@ class ProxyProjectionFactory implements ProjectionFactory, BeanClassLoaderAware
6768
private final Lazy<DefaultMethodInvokingMethodInterceptor> defaultMethodInvokingMethodInterceptor = Lazy
6869
.of(DefaultMethodInvokingMethodInterceptor::new);
6970

70-
private final Lazy<NullabilityMethodInvocationValidator> nullabilityValidator = Lazy
71-
.of(NullabilityMethodInvocationValidator::new);
71+
private final Lazy<NullnessMethodInvocationValidator> nullabilityValidator = Lazy
72+
.of(NullnessMethodInvocationValidator::new);
7273

7374
/**
7475
* Creates a new {@link ProxyProjectionFactory}.
@@ -124,7 +125,7 @@ public <T> T createProjection(Class<T> projectionType, Object source) {
124125

125126
factory.addAdvice(new TargetAwareMethodInterceptor(source.getClass()));
126127

127-
if(NullabilityMethodInvocationValidator.supports(projectionType)) {
128+
if (projectionMetadata.definesNullness) {
128129
factory.addAdvice(nullabilityValidator.get());
129130
}
130131

@@ -300,10 +301,12 @@ public boolean supports(Object source, Class<?> targetType) {
300301
*
301302
* @since 3.1.1
302303
*/
303-
record ProjectionMetadata(boolean hasDefaultMethods, ProjectionInformation projectionInformation) {
304+
record ProjectionMetadata(boolean hasDefaultMethods, boolean definesNullness,
305+
ProjectionInformation projectionInformation) {
304306

305307
public static ProjectionMetadata create(Class<?> projectionType, ProjectionInformation projectionInformation) {
306308
return new ProjectionMetadata(DefaultMethodInvokingMethodInterceptor.hasDefaultMethods(projectionType),
309+
NullnessMethodInvocationValidator.supports(projectionType),
307310
projectionInformation);
308311
}
309312
}

Diff for: src/main/java/org/springframework/data/repository/core/support/MethodInvocationValidator.java

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

18+
import java.lang.reflect.Method;
19+
1820
import org.springframework.dao.EmptyResultDataAccessException;
19-
import org.springframework.data.util.NullabilityMethodInvocationValidator;
21+
import org.springframework.data.util.NullnessMethodInvocationValidator;
2022

2123
/**
2224
* Interceptor enforcing required return value and method parameter constraints declared on repository query methods.
@@ -29,12 +31,11 @@
2931
* @see org.springframework.lang.NonNull
3032
* @see org.springframework.data.util.ReflectionUtils#isNullable(org.springframework.core.MethodParameter)
3133
* @see org.springframework.data.util.NullableUtils
32-
* @deprecated use {@link NullabilityMethodInvocationValidator} instead.
3334
*/
34-
@Deprecated // TODO: do we want to remove this with next major
35-
public class MethodInvocationValidator extends NullabilityMethodInvocationValidator {
35+
public class MethodInvocationValidator extends NullnessMethodInvocationValidator {
3636

37-
public MethodInvocationValidator() {
38-
super((invocation) -> new EmptyResultDataAccessException("Result must not be null", 1));
37+
@Override
38+
protected RuntimeException returnValueIsNull(Method method) {
39+
return new EmptyResultDataAccessException("Result must not be null", 1);
3940
}
4041
}

Diff for: src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
import org.springframework.data.repository.util.QueryExecutionConverters;
7474
import org.springframework.data.spel.EvaluationContextProvider;
7575
import org.springframework.data.util.Lazy;
76-
import org.springframework.data.util.NullabilityMethodInvocationValidator;
76+
import org.springframework.data.util.NullnessMethodInvocationValidator;
7777
import org.springframework.data.util.ReflectionUtils;
7878
import org.springframework.expression.ExpressionParser;
7979
import org.springframework.expression.spel.standard.SpelExpressionParser;
@@ -400,7 +400,7 @@ public <T> T getRepository(Class<T> repositoryInterface, RepositoryFragments fra
400400
result.setTarget(target);
401401
result.setInterfaces(repositoryInterface, Repository.class, TransactionalProxy.class);
402402

403-
if (NullabilityMethodInvocationValidator.supports(repositoryInterface)) {
403+
if (NullnessMethodInvocationValidator.supports(repositoryInterface)) {
404404
if (logger.isTraceEnabled()) {
405405
logger.trace(LogMessage.format("Register MethodInvocationValidator for %s…", repositoryInterface.getName()));
406406
}

Diff for: src/main/java/org/springframework/data/util/NullabilityMethodInvocationValidator.java renamed to src/main/java/org/springframework/data/util/NullnessMethodInvocationValidator.java

+45-33
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@
1515
*/
1616
package org.springframework.data.util;
1717

18+
import kotlin.reflect.KFunction;
19+
1820
import java.lang.annotation.ElementType;
1921
import java.lang.reflect.Method;
2022
import java.util.Map;
2123
import java.util.concurrent.ConcurrentHashMap;
22-
import java.util.function.Function;
2324

24-
import kotlin.reflect.KFunction;
2525
import org.aopalliance.intercept.MethodInterceptor;
2626
import org.aopalliance.intercept.MethodInvocation;
27+
2728
import org.springframework.core.DefaultParameterNameDiscoverer;
2829
import org.springframework.core.KotlinDetector;
2930
import org.springframework.core.MethodParameter;
@@ -34,8 +35,8 @@
3435

3536
/**
3637
* Interceptor enforcing required return value and method parameter constraints declared on repository query methods.
37-
* Supports Kotlin nullability markers and JSR-305 Non-null annotations.
38-
* Originally implemented via {@link org.springframework.data.repository.core.support.MethodInvocationValidator}.
38+
* Supports Kotlin nullness markers and JSR-305 Non-null annotations. Originally implemented via
39+
* {@link org.springframework.data.repository.core.support.MethodInvocationValidator}.
3940
*
4041
* @author Mark Paluch
4142
* @author Johannes Englmeier
@@ -44,23 +45,12 @@
4445
* @see org.springframework.lang.NonNull
4546
* @see ReflectionUtils#isNullable(MethodParameter)
4647
* @see NullableUtils
48+
* @link <a href="https://www.thedictionaryofobscuresorrows.com/word/nullness">Nullness</a>
4749
*/
48-
public class NullabilityMethodInvocationValidator implements MethodInterceptor {
50+
public class NullnessMethodInvocationValidator implements MethodInterceptor {
4951

5052
private final ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
51-
private final Map<Method, Nullability> nullabilityCache = new ConcurrentHashMap<>(16);
52-
private final Function<MethodInvocation, RuntimeException> errorFunction;
53-
54-
public NullabilityMethodInvocationValidator() {
55-
this((invocation) -> new NullPointerException("Method marked non nullable used with null value. If this is by design consider providing additional metadata using @Nullable annotations."));
56-
}
57-
58-
/**
59-
* @param errorFunction custom function creating the error in case of failure.
60-
*/
61-
protected NullabilityMethodInvocationValidator(Function<MethodInvocation, RuntimeException> errorFunction) {
62-
this.errorFunction = errorFunction;
63-
}
53+
private final Map<Method, MethodNullness> nullabilityCache = new ConcurrentHashMap<>(16);
6454

6555
/**
6656
* Returns {@literal true} if the {@code type} is supported by this interceptor.
@@ -80,51 +70,73 @@ public static boolean supports(Class<?> type) {
8070
public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
8171

8272
Method method = invocation.getMethod();
83-
Nullability nullability = nullabilityCache.get(method);
73+
MethodNullness nullness = nullabilityCache.get(method);
8474

85-
if (nullability == null) {
75+
if (nullness == null) {
8676

87-
nullability = Nullability.of(method, discoverer);
88-
nullabilityCache.put(method, nullability);
77+
nullness = MethodNullness.of(method, discoverer);
78+
nullabilityCache.put(method, nullness);
8979
}
9080

9181
Object[] arguments = invocation.getArguments();
9282

9383
for (int i = 0; i < method.getParameterCount(); i++) {
9484

95-
if (nullability.isNullableParameter(i)) {
85+
if (nullness.isNullableParameter(i)) {
9686
continue;
9787
}
9888

9989
if ((arguments.length < i) || (arguments[i] == null)) {
100-
throw new IllegalArgumentException(
101-
String.format("Parameter %s in %s.%s must not be null", nullability.getMethodParameterName(i),
102-
ClassUtils.getShortName(method.getDeclaringClass()), method.getName()));
90+
throw argumentIsNull(method, nullness.getMethodParameterName(i));
10391
}
10492
}
10593

10694
Object result = invocation.proceed();
10795

108-
if ((result == null) && !nullability.isNullableReturn()) {
109-
throw errorFunction.apply(invocation);
96+
if ((result == null) && !nullness.isNullableReturn()) {
97+
throw returnValueIsNull(method);
11098
}
11199

112100
return result;
113101
}
114102

115-
static final class Nullability {
103+
/**
104+
* Template method to construct a {@link RuntimeException} indicating failure to provide a non-{@literal null} value
105+
* for a method parameter.
106+
*
107+
* @param method
108+
* @param parameterName
109+
* @return
110+
*/
111+
protected RuntimeException argumentIsNull(Method method, String parameterName) {
112+
return new IllegalArgumentException(String.format("Parameter %s in %s.%s must not be null", parameterName,
113+
ClassUtils.getShortName(method.getDeclaringClass()), method.getName()));
114+
}
115+
116+
/**
117+
* Template method to construct a {@link RuntimeException} indicating failure to return a non-{@literal null} return
118+
* value.
119+
*
120+
* @param method
121+
* @return
122+
*/
123+
protected RuntimeException returnValueIsNull(Method method) {
124+
return new NullPointerException("Return value is null but must not be null");
125+
}
126+
127+
static final class MethodNullness {
116128

117129
private final boolean nullableReturn;
118130
private final boolean[] nullableParameters;
119131
private final MethodParameter[] methodParameters;
120132

121-
private Nullability(boolean nullableReturn, boolean[] nullableParameters, MethodParameter[] methodParameters) {
133+
private MethodNullness(boolean nullableReturn, boolean[] nullableParameters, MethodParameter[] methodParameters) {
122134
this.nullableReturn = nullableReturn;
123135
this.nullableParameters = nullableParameters;
124136
this.methodParameters = methodParameters;
125137
}
126138

127-
static Nullability of(Method method, ParameterNameDiscoverer discoverer) {
139+
static MethodNullness of(Method method, ParameterNameDiscoverer discoverer) {
128140

129141
boolean nullableReturn = isNullableParameter(new MethodParameter(method, -1));
130142
boolean[] nullableParameters = new boolean[method.getParameterCount()];
@@ -138,7 +150,7 @@ static Nullability of(Method method, ParameterNameDiscoverer discoverer) {
138150
methodParameters[i] = parameter;
139151
}
140152

141-
return new Nullability(nullableReturn, nullableParameters, methodParameters);
153+
return new MethodNullness(nullableReturn, nullableParameters, methodParameters);
142154
}
143155

144156
String getMethodParameterName(int index) {
@@ -203,7 +215,7 @@ public boolean equals(@Nullable Object o) {
203215
return true;
204216
}
205217

206-
if (!(o instanceof Nullability that)) {
218+
if (!(o instanceof MethodNullness that)) {
207219
return false;
208220
}
209221

0 commit comments

Comments
 (0)