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:
Oliver Gierke
2017-06-27 08:41:16 +02:00
parent d9b16d8a27
commit 049970874d
234 changed files with 2274 additions and 1179 deletions

View File

@@ -0,0 +1,104 @@
/*
* Copyright 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.
* 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.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.xml.XmlReaderContext;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
/**
* Helper class to centralize common functionality that needs to be used in various places of the configuration
* implementation.
*
* @author Oliver Gierke
* @since 2.0
* @soundtrack Richard Spaven - The Self (feat. Jordan Rakei)
*/
public interface ConfigurationUtils {
/**
* Returns the {@link ResourceLoader} from the given {@link XmlReaderContext}.
*
* @param context must not be {@literal null}.
* @return
* @throws IllegalArgumentException if no {@link ResourceLoader} can be obtained from the {@link XmlReaderContext}.
*/
public static ResourceLoader getRequiredResourceLoader(XmlReaderContext context) {
Assert.notNull(context, "XmlReaderContext must not be null!");
ResourceLoader resourceLoader = context.getResourceLoader();
if (resourceLoader == null) {
throw new IllegalArgumentException("Could not obtain ResourceLoader from XmlReaderContext!");
}
return resourceLoader;
}
/**
* Returns the {@link ClassLoader} used by the given {@link XmlReaderContext}.
*
* @param context must not be {@literal null}.
* @return
* @throws IllegalArgumentException if no {@link ClassLoader} can be obtained from the given {@link XmlReaderContext}.
*/
public static ClassLoader getRequiredClassLoader(XmlReaderContext context) {
return getRequiredClassLoader(getRequiredResourceLoader(context));
}
/**
* Returns the {@link ClassLoader} used by the given {@link ResourceLoader}.
*
* @param resourceLoader must not be {@literal null}.
* @return
* @throws IllegalArgumentException if the given {@link ResourceLoader} does not expose a {@link ClassLoader}.
*/
public static ClassLoader getRequiredClassLoader(ResourceLoader resourceLoader) {
Assert.notNull(resourceLoader, "ResourceLoader must not be null!");
ClassLoader classLoader = resourceLoader.getClassLoader();
if (classLoader == null) {
throw new IllegalArgumentException("Could not obtain ClassLoader from ResourceLoader!");
}
return classLoader;
}
/**
* Returns the bean class name of the given {@link BeanDefinition}.
*
* @param beanDefinition must not be {@literal null}.
* @return
* @throws IllegalArgumentException if the given {@link BeanDefinition} does not contain a bean class name.
*/
public static String getRequiredBeanClassName(BeanDefinition beanDefinition) {
Assert.notNull(beanDefinition, "BeanDefinition must not be null!");
String result = beanDefinition.getBeanClassName();
if (result == null) {
throw new IllegalArgumentException(
String.format("Could not obtain required bean class name from BeanDefinition!", beanDefinition));
}
return result;
}
}

View File

@@ -21,6 +21,7 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
@@ -120,7 +121,7 @@ public abstract class ParsingUtils {
* @param source
* @return
*/
public static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, Object source) {
public static AbstractBeanDefinition getSourceBeanDefinition(BeanDefinitionBuilder builder, @Nullable Object source) {
Assert.notNull(builder, "Builder must not be null!");

View File

@@ -30,6 +30,7 @@ import org.springframework.core.type.filter.AspectJTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.RegexPatternTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -55,7 +56,7 @@ public class TypeFilterParser {
* @param readerContext must not be {@literal null}.
*/
public TypeFilterParser(XmlReaderContext readerContext) {
this(readerContext, readerContext.getResourceLoader().getClassLoader());
this(readerContext, ConfigurationUtils.getRequiredClassLoader(readerContext));
}
/**
@@ -92,13 +93,14 @@ public class TypeFilterParser {
Node node = nodeList.item(i);
Element childElement = type.getElement(node);
if (childElement != null) {
if (childElement == null) {
continue;
}
try {
filters.add(createTypeFilter(childElement, classLoader));
} catch (RuntimeException e) {
readerContext.error(e.getMessage(), readerContext.extractSource(element), e.getCause());
}
try {
filters.add(createTypeFilter(childElement, classLoader));
} catch (RuntimeException e) {
readerContext.error(e.getMessage(), readerContext.extractSource(element), e.getCause());
}
}
@@ -224,6 +226,7 @@ public class TypeFilterParser {
* @param node
* @return
*/
@Nullable
Element getElement(Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {

View File

@@ -1,4 +1,5 @@
/**
* Basic support for creating custom Spring namespaces and JavaConfig.
*/
package org.springframework.data.config;
@org.springframework.lang.NonNullApi
package org.springframework.data.config;