DATACMNS-1114 - Introduced usage of nullable annotations for API validation.
Marked all packages with Spring Frameworks @NonNullApi. Added Spring's @Nullable to methods, parameters and fields that take or produce null values. Adapted using code to make sure the IDE can evaluate the null flow properly. Fixed Javadoc in places where an invalid null handling policy was advertised. Strengthened null requirements for types that expose null-instances. Removed null handling from converters for JodaTime and ThreeTenBP. Introduced factory methods Page.empty() and Page.empty(Pageable). Introduced default methods getRequiredGetter(), …Setter() and …Field() on PersistentProperty to allow non-nullable lookups of members. The same for TypeInformation.getrequiredActualType(), …SuperTypeInformation(). Tweaked PersistentPropertyCreator.addPropertiesForRemainingDescriptors() to filter unsuitable PropertyDescriptors before actually trying to create a Property instance from them as the new stronger nullability requirements would cause exceptions downstream. Lazy.get() now expects a non-null return value. Clients being able to cope with null need to call ….orElse(…). Original pull request: #232.
This commit is contained in:
@@ -44,10 +44,14 @@ public final class Accessor {
|
||||
|
||||
Assert.notNull(method, "Method must not be null!");
|
||||
|
||||
this.descriptor = BeanUtils.findPropertyForMethod(method);
|
||||
this.method = method;
|
||||
PropertyDescriptor descriptor = BeanUtils.findPropertyForMethod(method);
|
||||
|
||||
Assert.notNull(descriptor, () -> String.format("Invoked method %s is no accessor method!", method));
|
||||
if (descriptor == null) {
|
||||
throw new IllegalArgumentException(String.format("Invoked method %s is no accessor method!", method));
|
||||
}
|
||||
|
||||
this.descriptor = descriptor;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,8 @@ import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.aop.ProxyMethodInvocation;
|
||||
@@ -48,8 +50,9 @@ public class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor
|
||||
* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
|
||||
|
||||
Method method = invocation.getMethod();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2017 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.
|
||||
@@ -21,6 +21,8 @@ import lombok.RequiredArgsConstructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -40,8 +42,9 @@ class MapAccessingMethodInterceptor implements MethodInterceptor {
|
||||
* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
|
||||
|
||||
Method method = invocation.getMethod();
|
||||
|
||||
|
||||
@@ -26,12 +26,15 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -54,8 +57,9 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
|
||||
* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
public Object invoke(@SuppressWarnings("null") @Nonnull MethodInvocation invocation) throws Throwable {
|
||||
|
||||
Object result = delegate.invoke(invocation);
|
||||
|
||||
@@ -121,6 +125,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object getProjection(Object result, Class<?> returnType) {
|
||||
return result == null || ClassUtils.isAssignable(returnType, result.getClass()) ? result
|
||||
: factory.createProjection(returnType, result);
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.projection;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* A factory to create projecting instances for other objects usually used to allow easy creation of representation
|
||||
* projections to define which properties of a domain objects shall be exported in which way.
|
||||
@@ -29,11 +31,23 @@ public interface ProjectionFactory {
|
||||
* the implementations.
|
||||
*
|
||||
* @param projectionType the type to create, must not be {@literal null}.
|
||||
* @param source the object to create a projection for, can be {@literal null}
|
||||
* @param source the object to create a projection for, must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
<T> T createProjection(Class<T> projectionType, Object source);
|
||||
|
||||
/**
|
||||
* Creates a projection to the given type for the given nullable source.
|
||||
*
|
||||
* @param projectionType must not be {@literal null}.
|
||||
* @param source can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
default <T> T createNullableProjection(Class<T> projectionType, @Nullable Object source) {
|
||||
return source == null ? null : createProjection(projectionType, source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a projection instance for the given type.
|
||||
*
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.data.util.DirectFieldAccessFallbackBeanWrapper;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
@@ -52,8 +53,9 @@ class PropertyAccessingMethodInterceptor implements MethodInterceptor {
|
||||
* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
|
||||
|
||||
Method method = invocation.getMethod();
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
@@ -48,7 +49,7 @@ class ProxyProjectionFactory implements ProjectionFactory, BeanClassLoaderAware
|
||||
private final List<MethodInterceptorFactory> factories;
|
||||
private final ConversionService conversionService;
|
||||
private final Map<Class<?>, ProjectionInformation> projectionInformationCache = new ConcurrentReferenceHashMap<>();
|
||||
private ClassLoader classLoader;
|
||||
private @Nullable ClassLoader classLoader;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ProxyProjectionFactory}.
|
||||
@@ -94,9 +95,10 @@ class ProxyProjectionFactory implements ProjectionFactory, BeanClassLoaderAware
|
||||
public <T> T createProjection(Class<T> projectionType, Object source) {
|
||||
|
||||
Assert.notNull(projectionType, "Projection type must not be null!");
|
||||
Assert.notNull(source, "Source must not be null!");
|
||||
Assert.isTrue(projectionType.isInterface(), "Projection type must be an interface!");
|
||||
|
||||
if (source == null || projectionType.isInstance(source)) {
|
||||
if (projectionType.isInstance(source)) {
|
||||
return (T) source;
|
||||
}
|
||||
|
||||
@@ -229,8 +231,9 @@ class ProxyProjectionFactory implements ProjectionFactory, BeanClassLoaderAware
|
||||
* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
|
||||
|
||||
if (invocation.getMethod().equals(GET_TARGET_CLASS_METHOD)) {
|
||||
return targetType;
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.data.util.AnnotationDetectionMethodCallback;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
@@ -45,7 +46,7 @@ public class SpelAwareProxyProjectionFactory extends ProxyProjectionFactory impl
|
||||
private final Map<Class<?>, Boolean> typeCache = new HashMap<>();
|
||||
private final SpelExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
private @Nullable BeanFactory beanFactory;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.expression.ParserContext;
|
||||
import org.springframework.expression.common.TemplateParserContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -63,7 +64,7 @@ class SpelEvaluatingMethodInterceptor implements MethodInterceptor {
|
||||
* @param parser must not be {@literal null}.
|
||||
* @param targetInterface must not be {@literal null}.
|
||||
*/
|
||||
public SpelEvaluatingMethodInterceptor(MethodInterceptor delegate, Object target, BeanFactory beanFactory,
|
||||
public SpelEvaluatingMethodInterceptor(MethodInterceptor delegate, Object target, @Nullable BeanFactory beanFactory,
|
||||
SpelExpressionParser parser, Class<?> targetInterface) {
|
||||
|
||||
Assert.notNull(delegate, "Delegate MethodInterceptor must not be null!");
|
||||
@@ -123,8 +124,9 @@ class SpelEvaluatingMethodInterceptor implements MethodInterceptor {
|
||||
* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) throws Throwable {
|
||||
|
||||
Expression expression = expressions.get(invocation.getMethod().hashCode());
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.projection;
|
||||
|
||||
import org.springframework.aop.RawTargetAccess;
|
||||
import org.springframework.core.DecoratingProxy;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
@@ -30,8 +31,9 @@ public interface TargetAware extends org.springframework.aop.TargetClassAware, R
|
||||
/**
|
||||
* Returns the type of the proxy target.
|
||||
*
|
||||
* @return will never be {@literal null}.
|
||||
* @return can be {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
@JsonIgnore
|
||||
Class<?> getTargetClass();
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Projection subsystem.
|
||||
*/
|
||||
@org.springframework.lang.NonNullApi
|
||||
package org.springframework.data.projection;
|
||||
Reference in New Issue
Block a user