Specify generic type nullness in spring-context

Also in spring-context-support.

See gh-34140
This commit is contained in:
Sébastien Deleuze 2025-01-13 20:50:56 +01:00
parent 928a3c7184
commit 435cb0c7d6
30 changed files with 112 additions and 103 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@ -16,6 +16,7 @@
package org.springframework.cache.jcache;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.function.Function;
@ -134,7 +135,8 @@ public class JCacheCache extends AbstractValueAdaptingCache {
private static final PutIfAbsentEntryProcessor INSTANCE = new PutIfAbsentEntryProcessor();
@Override
public @Nullable Object process(MutableEntry<Object, Object> entry, Object... arguments) throws EntryProcessorException {
@SuppressWarnings("NullAway") // Overridden method does not define nullness
public @Nullable Object process(MutableEntry<Object, @Nullable Object> entry, @Nullable Object... arguments) throws EntryProcessorException {
Object existingValue = entry.getValue();
if (existingValue == null) {
entry.setValue(arguments[0]);
@ -146,11 +148,11 @@ public class JCacheCache extends AbstractValueAdaptingCache {
private static final class ValueLoaderEntryProcessor implements EntryProcessor<Object, Object, Object> {
private final Function<Object, Object> fromStoreValue;
private final Function<Object, @Nullable Object> fromStoreValue;
private final Function<Object, Object> toStoreValue;
private ValueLoaderEntryProcessor(Function<Object, Object> fromStoreValue,
private ValueLoaderEntryProcessor(Function<Object, @Nullable Object> fromStoreValue,
Function<Object, Object> toStoreValue) {
this.fromStoreValue = fromStoreValue;
@ -158,16 +160,16 @@ public class JCacheCache extends AbstractValueAdaptingCache {
}
@Override
@SuppressWarnings("unchecked")
public @Nullable Object process(MutableEntry<Object, Object> entry, Object... arguments) throws EntryProcessorException {
@SuppressWarnings({"unchecked","NullAway"}) // Overridden method does not define nullness
public @Nullable Object process(MutableEntry<Object, @Nullable Object> entry, @Nullable Object... arguments) throws EntryProcessorException {
Callable<Object> valueLoader = (Callable<Object>) arguments[0];
if (entry.exists()) {
return this.fromStoreValue.apply(entry.getValue());
return this.fromStoreValue.apply(Objects.requireNonNull(entry.getValue()));
}
else {
Object value;
try {
value = valueLoader.call();
value = Objects.requireNonNull(valueLoader).call();
}
catch (Exception ex) {
throw new EntryProcessorException("Value loader '" + valueLoader + "' failed " +

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@ -41,10 +41,11 @@ import org.springframework.context.annotation.Role;
@Configuration(proxyBeanMethods = false)
public abstract class AbstractJCacheConfiguration extends AbstractCachingConfiguration {
protected @Nullable Supplier<CacheResolver> exceptionCacheResolver;
protected @Nullable Supplier<? extends @Nullable CacheResolver> exceptionCacheResolver;
@Override
@SuppressWarnings("NullAway") // https://github.com/uber/NullAway/issues/1126
protected void useCachingConfigurer(CachingConfigurerSupplier cachingConfigurerSupplier) {
super.useCachingConfigurer(cachingConfigurerSupplier);
this.exceptionCacheResolver = cachingConfigurerSupplier.adapt(config -> {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -79,8 +79,8 @@ public class DefaultJCacheOperationSource extends AnnotationJCacheOperationSourc
* @since 5.1
*/
public DefaultJCacheOperationSource(
@Nullable Supplier<CacheManager> cacheManager, @Nullable Supplier<CacheResolver> cacheResolver,
@Nullable Supplier<CacheResolver> exceptionCacheResolver, @Nullable Supplier<KeyGenerator> keyGenerator) {
@Nullable Supplier<? extends @Nullable CacheManager> cacheManager, @Nullable Supplier<? extends @Nullable CacheResolver> cacheResolver,
@Nullable Supplier<? extends @Nullable CacheResolver> exceptionCacheResolver, @Nullable Supplier<? extends @Nullable KeyGenerator> keyGenerator) {
this.cacheManager = SingletonSupplier.ofNullable(cacheManager);
this.cacheResolver = SingletonSupplier.ofNullable(cacheResolver);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2025 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.
@ -96,7 +96,7 @@ public class JCacheAspectSupport extends AbstractCacheInvoker implements Initial
}
protected @Nullable Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {
protected @Nullable Object execute(CacheOperationInvoker invoker, Object target, Method method, @Nullable Object[] args) {
// Check whether aspect is enabled to cope with cases where the AJ is pulled in automatically
if (this.initialized) {
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(target);
@ -113,7 +113,7 @@ public class JCacheAspectSupport extends AbstractCacheInvoker implements Initial
@SuppressWarnings("unchecked")
private CacheOperationInvocationContext<?> createCacheOperationInvocationContext(
Object target, Object[] args, JCacheOperation<?> operation) {
Object target, @Nullable Object[] args, JCacheOperation<?> operation) {
return new DefaultCacheInvocationContext<>(
(JCacheOperation<Annotation>) operation, target, args);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2025 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.
@ -60,7 +60,7 @@ public class JCacheInterceptor extends JCacheAspectSupport implements MethodInte
* applying the default error handler if the supplier is not resolvable
* @since 5.1
*/
public JCacheInterceptor(@Nullable Supplier<CacheErrorHandler> errorHandler) {
public JCacheInterceptor(@Nullable Supplier<? extends @Nullable CacheErrorHandler> errorHandler) {
this.errorHandler = new SingletonSupplier<>(errorHandler, SimpleCacheErrorHandler::new);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2025 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.
@ -50,13 +50,13 @@ public abstract class AbstractCachingConfiguration implements ImportAware {
protected @Nullable AnnotationAttributes enableCaching;
protected @Nullable Supplier<CacheManager> cacheManager;
protected @Nullable Supplier<? extends @Nullable CacheManager> cacheManager;
protected @Nullable Supplier<CacheResolver> cacheResolver;
protected @Nullable Supplier<? extends @Nullable CacheResolver> cacheResolver;
protected @Nullable Supplier<KeyGenerator> keyGenerator;
protected @Nullable Supplier<? extends @Nullable KeyGenerator> keyGenerator;
protected @Nullable Supplier<CacheErrorHandler> errorHandler;
protected @Nullable Supplier<? extends @Nullable CacheErrorHandler> errorHandler;
@Override
@ -70,8 +70,9 @@ public abstract class AbstractCachingConfiguration implements ImportAware {
}
@Autowired
@SuppressWarnings("NullAway") // https://github.com/uber/NullAway/issues/1126
void setConfigurers(ObjectProvider<CachingConfigurer> configurers) {
Supplier<CachingConfigurer> configurer = () -> {
Supplier<? extends @Nullable CachingConfigurer> configurer = () -> {
List<CachingConfigurer> candidates = configurers.stream().toList();
if (CollectionUtils.isEmpty(candidates)) {
return null;
@ -90,6 +91,7 @@ public abstract class AbstractCachingConfiguration implements ImportAware {
/**
* Extract the configuration from the nominated {@link CachingConfigurer}.
*/
@SuppressWarnings("NullAway") // https://github.com/uber/NullAway/issues/1126
protected void useCachingConfigurer(CachingConfigurerSupplier cachingConfigurerSupplier) {
this.cacheManager = cachingConfigurerSupplier.adapt(CachingConfigurer::cacheManager);
this.cacheResolver = cachingConfigurerSupplier.adapt(CachingConfigurer::cacheResolver);
@ -100,10 +102,10 @@ public abstract class AbstractCachingConfiguration implements ImportAware {
protected static class CachingConfigurerSupplier {
private final Supplier<CachingConfigurer> supplier;
private final SingletonSupplier<CachingConfigurer> supplier;
public CachingConfigurerSupplier(Supplier<CachingConfigurer> supplier) {
this.supplier = SingletonSupplier.of(supplier);
public CachingConfigurerSupplier(Supplier<? extends @Nullable CachingConfigurer> supplier) {
this.supplier = SingletonSupplier.ofNullable(supplier);
}
/**
@ -115,7 +117,7 @@ public abstract class AbstractCachingConfiguration implements ImportAware {
* @param <T> the type of the supplier
* @return another supplier mapped by the specified function
*/
public <T> @Nullable Supplier<T> adapt(Function<CachingConfigurer, T> provider) {
public <T> Supplier<@Nullable T> adapt(Function<CachingConfigurer, ? extends @Nullable T> provider) {
return () -> {
CachingConfigurer cachingConfigurer = this.supplier.get();
return (cachingConfigurer != null ? provider.apply(cachingConfigurer) : null);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -154,8 +154,8 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
* @since 5.1
*/
public void configure(
@Nullable Supplier<CacheErrorHandler> errorHandler, @Nullable Supplier<KeyGenerator> keyGenerator,
@Nullable Supplier<CacheResolver> cacheResolver, @Nullable Supplier<CacheManager> cacheManager) {
@Nullable Supplier<? extends @Nullable CacheErrorHandler> errorHandler, @Nullable Supplier<? extends @Nullable KeyGenerator> keyGenerator,
@Nullable Supplier<? extends @Nullable CacheResolver> cacheResolver, @Nullable Supplier<? extends @Nullable CacheManager> cacheManager) {
this.errorHandler = new SingletonSupplier<>(errorHandler, SimpleCacheErrorHandler::new);
this.keyGenerator = new SingletonSupplier<>(keyGenerator, SimpleKeyGenerator::new);
@ -317,7 +317,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
}
protected CacheOperationContext getOperationContext(
CacheOperation operation, Method method, Object[] args, Object target, Class<?> targetClass) {
CacheOperation operation, Method method, @Nullable Object[] args, Object target, Class<?> targetClass) {
CacheOperationMetadata metadata = getCacheOperationMetadata(operation, method, targetClass);
return new CacheOperationContext(metadata, args, target);
@ -391,7 +391,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
this.evaluator.clear();
}
protected @Nullable Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {
protected @Nullable Object execute(CacheOperationInvoker invoker, Object target, Method method, @Nullable Object[] args) {
// Check whether aspect is enabled (to cope with cases where the AJ is pulled in automatically)
if (this.initialized) {
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(target);
@ -726,7 +726,7 @@ public abstract class CacheAspectSupport extends AbstractCacheInvoker
boolean processed;
public CacheOperationContexts(Collection<? extends CacheOperation> operations, Method method,
Object[] args, Object target, Class<?> targetClass) {
@Nullable Object[] args, Object target, Class<?> targetClass) {
this.contexts = new LinkedMultiValueMap<>(operations.size());
for (CacheOperation op : operations) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2025 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.
@ -22,6 +22,7 @@ import org.jspecify.annotations.Nullable;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.lang.Contract;
/**
* A simple {@link CacheResolver} that resolves the {@link Cache} instance(s)
@ -63,6 +64,7 @@ public class SimpleCacheResolver extends AbstractCacheResolver {
* @return the SimpleCacheResolver ({@code null} if the CacheManager was {@code null})
* @since 5.1
*/
@Contract("null -> null; !null -> !null")
static @Nullable SimpleCacheResolver of(@Nullable CacheManager cacheManager) {
return (cacheManager != null ? new SimpleCacheResolver(cacheManager) : null);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -211,7 +211,7 @@ public class AnnotationBeanNameGenerator implements BeanNameGenerator {
* @return whether the annotation qualifies as a stereotype with component name
*/
protected boolean isStereotypeWithNameValue(String annotationType,
Set<String> metaAnnotationTypes, Map<String, Object> attributes) {
Set<String> metaAnnotationTypes, Map<String, @Nullable Object> attributes) {
boolean isStereotype = metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME) ||
annotationType.equals("jakarta.inject.Named");

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -129,7 +129,7 @@ class ConditionEvaluator {
@SuppressWarnings("unchecked")
private List<String[]> getConditionClasses(AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(Conditional.class.getName(), true);
MultiValueMap<String, @Nullable Object> attributes = metadata.getAllAnnotationAttributes(Conditional.class.getName(), true);
Object values = (attributes != null ? attributes.get("value") : null);
return (List<String[]>) (values != null ? values : Collections.emptyList());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -1077,7 +1077,7 @@ class ConfigurationClassParser {
}
public Collection<SourceClass> getAnnotationAttributes(String annType, String attribute) throws IOException {
Map<String, Object> annotationAttributes = this.metadata.getAnnotationAttributes(annType, true);
Map<String, @Nullable Object> annotationAttributes = this.metadata.getAnnotationAttributes(annType, true);
if (annotationAttributes == null || !annotationAttributes.containsKey(attribute)) {
return Collections.emptySet();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -658,9 +658,9 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
private final List<PropertySourceDescriptor> descriptors;
private final Function<String, Resource> resourceResolver;
private final Function<String, @Nullable Resource> resourceResolver;
PropertySourcesAotContribution(List<PropertySourceDescriptor> descriptors, Function<String, Resource> resourceResolver) {
PropertySourcesAotContribution(List<PropertySourceDescriptor> descriptors, Function<String, @Nullable Resource> resourceResolver) {
this.descriptors = descriptors;
this.resourceResolver = resourceResolver;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@ -143,7 +143,7 @@ public abstract class ConfigurationClassUtils {
}
}
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
Map<String, @Nullable Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
@ -208,7 +208,7 @@ public abstract class ConfigurationClassUtils {
* @since 5.0
*/
public static @Nullable Integer getOrder(AnnotationMetadata metadata) {
Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
Map<String, @Nullable Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
return (orderAttributes != null ? ((Integer) orderAttributes.get(AnnotationUtils.VALUE)) : null);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2025 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.
@ -60,7 +60,7 @@ public class MBeanExportConfiguration implements ImportAware, EnvironmentAware,
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
Map<String, Object> map = importMetadata.getAnnotationAttributes(EnableMBeanExport.class.getName());
Map<String, @Nullable Object> map = importMetadata.getAnnotationAttributes(EnableMBeanExport.class.getName());
this.enableMBeanExport = AnnotationAttributes.fromMap(map);
if (this.enableMBeanExport == null) {
throw new IllegalArgumentException(

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2025 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.
@ -76,7 +76,7 @@ abstract class ParserStrategyUtils {
if (constructors.length == 1 && constructors[0].getParameterCount() > 0) {
try {
Constructor<?> constructor = constructors[0];
Object[] args = resolveArgs(constructor.getParameterTypes(),
@Nullable Object[] args = resolveArgs(constructor.getParameterTypes(),
environment, resourceLoader, registry, classLoader);
return BeanUtils.instantiateClass(constructor, args);
}
@ -87,11 +87,11 @@ abstract class ParserStrategyUtils {
return BeanUtils.instantiateClass(clazz);
}
private static Object[] resolveArgs(Class<?>[] parameterTypes,
private static @Nullable Object[] resolveArgs(Class<?>[] parameterTypes,
Environment environment, ResourceLoader resourceLoader,
BeanDefinitionRegistry registry, @Nullable ClassLoader classLoader) {
Object[] parameters = new Object[parameterTypes.length];
@Nullable Object[] parameters = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
parameters[i] = resolveParameter(parameterTypes[i], environment,
resourceLoader, registry, classLoader);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@ -140,7 +140,7 @@ class ApplicationContextInitializationCodeGenerator implements BeanFactoryInitia
this.initializers.add(methodReference);
}
private static class InitializerMethodArgumentCodeGenerator implements Function<TypeName, CodeBlock> {
private static class InitializerMethodArgumentCodeGenerator implements Function<TypeName, @Nullable CodeBlock> {
@Override
public @Nullable CodeBlock apply(TypeName typeName) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@ -88,7 +88,7 @@ public class MethodBasedEvaluationContext extends StandardEvaluationContext {
}
// Expose indexed variables as well as parameter names (if discoverable)
String[] paramNames = this.parameterNameDiscoverer.getParameterNames(this.method);
@Nullable String[] paramNames = this.parameterNameDiscoverer.getParameterNames(this.method);
int paramCount = (paramNames != null ? paramNames.length : this.method.getParameterCount());
int argsCount = this.arguments.length;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -507,7 +507,7 @@ public class MBeanClientInterceptor
* @param args the invocation arguments
* @return the value returned by the method invocation.
*/
private Object invokeOperation(Method method, Object[] args) throws JMException, IOException {
private Object invokeOperation(Method method, @Nullable Object[] args) throws JMException, IOException {
Assert.state(this.serverToUse != null, "No MBeanServerConnection available");
MethodCacheKey key = new MethodCacheKey(method.getName(), method.getParameterTypes());

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@ -172,10 +172,10 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource, BeanFac
}
@SuppressWarnings("unchecked")
private static <T> T[] copyPropertiesToBeanArray(
private static <T> @Nullable T[] copyPropertiesToBeanArray(
List<MergedAnnotation<? extends Annotation>> anns, Class<T> beanClass) {
T[] beans = (T[]) Array.newInstance(beanClass, anns.size());
@Nullable T[] beans = (T[]) Array.newInstance(beanClass, anns.size());
int i = 0;
for (MergedAnnotation<? extends Annotation> ann : anns) {
beans[i++] = copyPropertiesToBean(ann, beanClass);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2025 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.
@ -506,9 +506,10 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
* of the {@code MBeanExporter}
* @return the {@code MBeanParameterInfo} array
*/
@SuppressWarnings("NullAway") // https://github.com/uber/NullAway/issues/1127
protected MBeanParameterInfo[] getOperationParameters(Method method, String beanKey) {
ParameterNameDiscoverer paramNameDiscoverer = getParameterNameDiscoverer();
String[] paramNames = (paramNameDiscoverer != null ? paramNameDiscoverer.getParameterNames(method) : null);
@Nullable String[] paramNames = (paramNameDiscoverer != null ? paramNameDiscoverer.getParameterNames(method) : null);
if (paramNames == null) {
return new MBeanParameterInfo[0];
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2025 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.
@ -48,9 +48,9 @@ public abstract class AbstractAsyncConfiguration implements ImportAware {
protected @Nullable AnnotationAttributes enableAsync;
protected @Nullable Supplier<Executor> executor;
protected @Nullable Supplier<? extends @Nullable Executor> executor;
protected @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler;
protected @Nullable Supplier<? extends @Nullable AsyncUncaughtExceptionHandler> exceptionHandler;
@Override
@ -67,8 +67,9 @@ public abstract class AbstractAsyncConfiguration implements ImportAware {
* Collect any {@link AsyncConfigurer} beans through autowiring.
*/
@Autowired
@SuppressWarnings("NullAway") // https://github.com/uber/NullAway/issues/1126
void setConfigurers(ObjectProvider<AsyncConfigurer> configurers) {
Supplier<AsyncConfigurer> configurer = SingletonSupplier.of(() -> {
SingletonSupplier<AsyncConfigurer> configurer = SingletonSupplier.ofNullable(() -> {
List<AsyncConfigurer> candidates = configurers.stream().toList();
if (CollectionUtils.isEmpty(candidates)) {
return null;
@ -82,7 +83,7 @@ public abstract class AbstractAsyncConfiguration implements ImportAware {
this.exceptionHandler = adapt(configurer, AsyncConfigurer::getAsyncUncaughtExceptionHandler);
}
private <T> Supplier<T> adapt(Supplier<AsyncConfigurer> supplier, Function<AsyncConfigurer, T> provider) {
private <T> Supplier<@Nullable T> adapt(SingletonSupplier<AsyncConfigurer> supplier, Function<AsyncConfigurer, @Nullable T> provider) {
return () -> {
AsyncConfigurer configurer = supplier.get();
return (configurer != null ? provider.apply(configurer) : null);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -64,7 +64,7 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
* Create a new {@code AsyncAnnotationAdvisor} for bean-style configuration.
*/
public AsyncAnnotationAdvisor() {
this((Supplier<Executor>) null, (Supplier<AsyncUncaughtExceptionHandler>) null);
this((Supplier<? extends @Nullable Executor>) null, (Supplier<? extends @Nullable AsyncUncaughtExceptionHandler>) null);
}
/**
@ -92,7 +92,7 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
*/
@SuppressWarnings("unchecked")
public AsyncAnnotationAdvisor(
@Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
@Nullable Supplier<? extends @Nullable Executor> executor, @Nullable Supplier<? extends @Nullable AsyncUncaughtExceptionHandler> exceptionHandler) {
Set<Class<? extends Annotation>> asyncAnnotationTypes = CollectionUtils.newLinkedHashSet(2);
asyncAnnotationTypes.add(Async.class);
@ -157,7 +157,7 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
protected Advice buildAdvice(
@Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
@Nullable Supplier<? extends @Nullable Executor> executor, @Nullable Supplier<? extends @Nullable AsyncUncaughtExceptionHandler> exceptionHandler) {
AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null);
interceptor.configure(executor, exceptionHandler);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -77,9 +77,9 @@ public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAd
protected final Log logger = LogFactory.getLog(getClass());
private @Nullable Supplier<Executor> executor;
private @Nullable Supplier<? extends @Nullable Executor> executor;
private @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler;
private @Nullable Supplier<? extends @Nullable AsyncUncaughtExceptionHandler> exceptionHandler;
private @Nullable Class<? extends Annotation> asyncAnnotationType;
@ -95,8 +95,8 @@ public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAd
* applying the corresponding default if a supplier is not resolvable.
* @since 5.1
*/
public void configure(@Nullable Supplier<Executor> executor,
@Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
public void configure(@Nullable Supplier<? extends @Nullable Executor> executor,
@Nullable Supplier<? extends @Nullable AsyncUncaughtExceptionHandler> exceptionHandler) {
this.executor = executor;
this.exceptionHandler = exceptionHandler;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -908,9 +908,9 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
}
else {
// A single data class constructor -> resolve constructor arguments from request parameters.
String[] paramNames = BeanUtils.getParameterNames(ctor);
@Nullable String[] paramNames = BeanUtils.getParameterNames(ctor);
Class<?>[] paramTypes = ctor.getParameterTypes();
Object[] args = new Object[paramTypes.length];
@Nullable Object[] args = new Object[paramTypes.length];
Set<String> failedParamNames = new HashSet<>(4);
for (int i = 0; i < paramNames.length; i++) {
@ -1067,14 +1067,14 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
}
@SuppressWarnings("unchecked")
private <V> V @Nullable [] createArray(String paramPath, ResolvableType type, ValueResolver valueResolver) {
private <V> @Nullable V @Nullable [] createArray(String paramPath, ResolvableType type, ValueResolver valueResolver) {
ResolvableType elementType = type.getNested(2);
SortedSet<Integer> indexes = getIndexes(paramPath, valueResolver);
if (indexes == null) {
return null;
}
int size = (indexes.last() < this.autoGrowCollectionLimit ? indexes.last() + 1: 0);
V[] array = (V[]) Array.newInstance(elementType.resolve(), size);
@Nullable V[] array = (V[]) Array.newInstance(elementType.resolve(), size);
for (int index : indexes) {
array[index] = (V) createObject(elementType, paramPath + "[" + index + "].", valueResolver);
}
@ -1096,7 +1096,7 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
}
private void validateConstructorArgument(
Class<?> constructorClass, String nestedPath, String name, @Nullable Object value) {
Class<?> constructorClass, String nestedPath, @Nullable String name, @Nullable Object value) {
Object[] hints = null;
if (this.targetType != null && this.targetType.getSource() instanceof MethodParameter parameter) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@ -59,7 +59,7 @@ public interface SmartValidator extends Validator {
* @see jakarta.validation.Validator#validateValue(Class, String, Object, Class[])
*/
default void validateValue(
Class<?> targetType, String fieldName, @Nullable Object value, Errors errors, Object... validationHints) {
Class<?> targetType, @Nullable String fieldName, @Nullable Object value, Errors errors, Object... validationHints) {
throw new IllegalArgumentException("Cannot validate individual value for " + targetType);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@ -242,7 +242,7 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
@Override
@SuppressWarnings({"rawtypes", "unchecked", "NullAway"}) // TODO NullAway bug?
@SuppressWarnings({"rawtypes", "unchecked"})
public void afterPropertiesSet() {
Configuration<?> configuration;
if (this.providerClass != null) {
@ -332,13 +332,13 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
configuration.parameterNameProvider(new ParameterNameProvider() {
@Override
public List<String> getParameterNames(Constructor<?> constructor) {
String[] paramNames = discoverer.getParameterNames(constructor);
@Nullable String[] paramNames = discoverer.getParameterNames(constructor);
return (paramNames != null ? Arrays.asList(paramNames) :
defaultProvider.getParameterNames(constructor));
}
@Override
public List<String> getParameterNames(Method method) {
String[] paramNames = discoverer.getParameterNames(method);
@Nullable String[] paramNames = discoverer.getParameterNames(method);
return (paramNames != null ? Arrays.asList(paramNames) :
defaultProvider.getParameterNames(method));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -236,7 +236,7 @@ public class MethodValidationAdapter implements MethodValidator {
@Override
public final MethodValidationResult validateArguments(
Object target, Method method, MethodParameter @Nullable [] parameters,
Object[] arguments, Class<?>[] groups) {
@Nullable Object[] arguments, Class<?>[] groups) {
Set<ConstraintViolation<Object>> violations =
invokeValidatorForArguments(target, method, arguments, groups);
@ -254,7 +254,7 @@ public class MethodValidationAdapter implements MethodValidator {
* Invoke the validator, and return the resulting violations.
*/
public final Set<ConstraintViolation<Object>> invokeValidatorForArguments(
Object target, Method method, Object[] arguments, Class<?>[] groups) {
Object target, Method method, @Nullable Object[] arguments, Class<?>[] groups) {
ExecutableValidator execVal = this.validator.get().forExecutables();
try {
@ -298,7 +298,7 @@ public class MethodValidationAdapter implements MethodValidator {
private MethodValidationResult adaptViolations(
Object target, Method method, Set<ConstraintViolation<Object>> violations,
Function<Integer, MethodParameter> parameterFunction,
Function<Integer, Object> argumentFunction) {
Function<Integer, @Nullable Object> argumentFunction) {
Map<Path.Node, ParamValidationResultBuilder> paramViolations = new LinkedHashMap<>();
Map<Path.Node, ParamErrorsBuilder> nestedViolations = new LinkedHashMap<>();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -149,7 +149,7 @@ public class MethodValidationInterceptor implements MethodInterceptor {
Object target = getTarget(invocation);
Method method = invocation.getMethod();
Object[] arguments = invocation.getArguments();
@Nullable Object[] arguments = invocation.getArguments();
Class<?>[] groups = determineValidationGroups(invocation);
if (reactorPresent) {
@ -239,9 +239,9 @@ public class MethodValidationInterceptor implements MethodInterceptor {
ReactiveAdapterRegistry.getSharedInstance();
static Object[] insertAsyncValidation(
static @Nullable Object[] insertAsyncValidation(
Supplier<SpringValidatorAdapter> validatorAdapterSupplier, boolean adaptViolations,
Object target, Method method, Object[] arguments) {
Object target, Method method, @Nullable Object[] arguments) {
for (int i = 0; i < method.getParameterCount(); i++) {
if (arguments[i] == null) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 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.
@ -116,7 +116,7 @@ public class SpringValidatorAdapter implements SmartValidator, jakarta.validatio
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public void validateValue(
Class<?> targetType, String fieldName, @Nullable Object value, Errors errors, Object... validationHints) {
Class<?> targetType, @Nullable String fieldName, @Nullable Object value, Errors errors, Object... validationHints) {
if (this.targetValidator != null) {
processConstraintViolations(this.targetValidator.validateValue(

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2025 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.
@ -53,7 +53,7 @@ public interface MethodValidator {
*/
MethodValidationResult validateArguments(
Object target, Method method, MethodParameter @Nullable [] parameters,
Object[] arguments, Class<?>[] groups);
@Nullable Object[] arguments, Class<?>[] groups);
/**
* Delegate to {@link #validateArguments} and handle the validation result,
@ -64,7 +64,7 @@ public interface MethodValidator {
*/
default void applyArgumentValidation(
Object target, Method method, MethodParameter @Nullable [] parameters,
Object[] arguments, Class<?>[] groups) {
@Nullable Object[] arguments, Class<?>[] groups) {
MethodValidationResult result = validateArguments(target, method, parameters, arguments, groups);
if (result.hasErrors()) {