Introduce null-safety of Spring Framework API

This commit introduces 2 new @Nullable and @NonNullApi
annotations that leverage JSR 305 (dormant but available via
Findbugs jsr305 dependency and already used by libraries
like OkHttp) meta-annotations to specify explicitly
null-safety of Spring Framework parameters and return values.

In order to avoid adding too much annotations, the
default is set at package level with @NonNullApi and
@Nullable annotations are added when needed at parameter or
return value level. These annotations are intended to be used
on Spring Framework itself but also by other Spring projects.

@Nullable annotations have been introduced based on Javadoc
and search of patterns like "return null;". It is expected that
nullability of Spring Framework API will be polished with
complementary commits.

In practice, this will make the whole Spring Framework API
null-safe for Kotlin projects (when KT-10942 will be fixed)
since Kotlin will be able to leverage these annotations to
know if a parameter or a return value is nullable or not. But
this is also useful for Java developers as well since IntelliJ
IDEA, for example, also understands these annotations to
generate warnings when unsafe nullable usages are detected.

Issue: SPR-15540
This commit is contained in:
Sebastien Deleuze
2017-05-27 08:14:59 +02:00
parent 2d37c966b2
commit 87598f48e4
1315 changed files with 4831 additions and 963 deletions

View File

@@ -2,4 +2,7 @@
* Annotation support for DAOs. Contains a bean post-processor for translating
* persistence exceptions based on a repository stereotype annotation.
*/
@NonNullApi
package org.springframework.dao.annotation;
import org.springframework.lang.NonNullApi;

View File

@@ -13,4 +13,7 @@
* <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0764543857/">Expert One-On-One J2EE Design and Development</a>
* by Rod Johnson (Wrox, 2002).
*/
@NonNullApi
package org.springframework.dao;
import org.springframework.lang.NonNullApi;

View File

@@ -22,6 +22,7 @@ import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.dao.TypeMismatchDataAccessException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.NumberUtils;
@@ -44,6 +45,7 @@ public abstract class DataAccessUtils {
* @throws IncorrectResultSizeDataAccessException if more than one
* element has been found in the given Collection
*/
@Nullable
public static <T> T singleResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
@@ -65,7 +67,7 @@ public abstract class DataAccessUtils {
* @throws EmptyResultDataAccessException if no element at all
* has been found in the given Collection
*/
public static <T> T requiredSingleResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
public static <T> T requiredSingleResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
throw new EmptyResultDataAccessException(1);
@@ -86,7 +88,8 @@ public abstract class DataAccessUtils {
* result object has been found in the given Collection
* @see org.springframework.util.CollectionUtils#hasUniqueObject
*/
public static <T> T uniqueResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
@Nullable
public static <T> T uniqueResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
return null;
@@ -108,7 +111,7 @@ public abstract class DataAccessUtils {
* has been found in the given Collection
* @see org.springframework.util.CollectionUtils#hasUniqueObject
*/
public static <T> T requiredUniqueResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
public static <T> T requiredUniqueResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
throw new EmptyResultDataAccessException(1);
@@ -134,7 +137,7 @@ public abstract class DataAccessUtils {
* not match the specified required type
*/
@SuppressWarnings("unchecked")
public static <T> T objectResult(Collection<?> results, Class<T> requiredType)
public static <T> T objectResult(@Nullable Collection<?> results, Class<T> requiredType)
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException {
Object result = requiredUniqueResult(results);
@@ -172,7 +175,7 @@ public abstract class DataAccessUtils {
* @throws TypeMismatchDataAccessException if the unique object
* in the collection is not convertible to an int
*/
public static int intResult(Collection<?> results)
public static int intResult(@Nullable Collection<?> results)
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException {
return objectResult(results, Number.class).intValue();
@@ -191,7 +194,7 @@ public abstract class DataAccessUtils {
* @throws TypeMismatchDataAccessException if the unique object
* in the collection is not convertible to a long
*/
public static long longResult(Collection<?> results)
public static long longResult(@Nullable Collection<?> results)
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException {
return objectResult(results, Number.class).longValue();

View File

@@ -17,6 +17,7 @@
package org.springframework.dao.support;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
/**
* Interface implemented by Spring integrations with data access technologies
@@ -51,6 +52,7 @@ public interface PersistenceExceptionTranslator {
* @see org.springframework.dao.DataIntegrityViolationException
* @see org.springframework.jdbc.support.SQLExceptionTranslator
*/
@Nullable
DataAccessException translateExceptionIfPossible(RuntimeException ex);
}

View File

@@ -2,4 +2,7 @@
* Support classes for DAO implementations,
* providing miscellaneous utility methods.
*/
@NonNullApi
package org.springframework.dao.support;
import org.springframework.lang.NonNullApi;

View File

@@ -25,6 +25,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jca.cci.CannotGetCciConnectionException;
import org.springframework.lang.Nullable;
import org.springframework.transaction.support.ResourceHolderSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
@@ -87,7 +88,7 @@ public abstract class ConnectionFactoryUtils {
* if the attempt to get a Connection failed
* @see #releaseConnection
*/
public static Connection getConnection(ConnectionFactory cf, ConnectionSpec spec)
public static Connection getConnection(ConnectionFactory cf, @Nullable ConnectionSpec spec)
throws CannotGetCciConnectionException {
try {
if (spec != null) {
@@ -145,7 +146,7 @@ public abstract class ConnectionFactoryUtils {
* (may be {@code null})
* @return whether the Connection is transactional
*/
public static boolean isConnectionTransactional(Connection con, ConnectionFactory cf) {
public static boolean isConnectionTransactional(Connection con, @Nullable ConnectionFactory cf) {
if (cf == null) {
return false;
}
@@ -162,7 +163,7 @@ public abstract class ConnectionFactoryUtils {
* (can be {@code null})
* @see #getConnection
*/
public static void releaseConnection(Connection con, ConnectionFactory cf) {
public static void releaseConnection(Connection con, @Nullable ConnectionFactory cf) {
try {
doReleaseConnection(con, cf);
}
@@ -186,7 +187,7 @@ public abstract class ConnectionFactoryUtils {
* @throws ResourceException if thrown by JCA CCI methods
* @see #doGetConnection
*/
public static void doReleaseConnection(Connection con, ConnectionFactory cf) throws ResourceException {
public static void doReleaseConnection(Connection con, @Nullable ConnectionFactory cf) throws ResourceException {
if (con == null || isConnectionTransactional(con, cf)) {
return;
}

View File

@@ -3,4 +3,7 @@
* a PlatformTransactionManager for local CCI transactions,
* and various simple ConnectionFactory proxies/adapters.
*/
@NonNullApi
package org.springframework.jca.cci.connection;
import org.springframework.lang.NonNullApi;

View File

@@ -20,6 +20,7 @@ import javax.resource.cci.InteractionSpec;
import javax.resource.cci.Record;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
/**
* Interface that specifies a basic set of CCI operations on an EIS.
@@ -47,6 +48,7 @@ public interface CciOperations {
* @return the result object returned by the action, if any
* @throws DataAccessException if there is any problem
*/
@Nullable
<T> T execute(ConnectionCallback<T> action) throws DataAccessException;
/**
@@ -62,6 +64,7 @@ public interface CciOperations {
* @return the result object returned by the action, if any
* @throws DataAccessException if there is any problem
*/
@Nullable
<T> T execute(InteractionCallback<T> action) throws DataAccessException;
/**

View File

@@ -17,6 +17,7 @@
package org.springframework.jca.cci.core;
import java.sql.SQLException;
import javax.resource.NotSupportedException;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
@@ -41,6 +42,7 @@ import org.springframework.jca.cci.InvalidResultSetAccessException;
import org.springframework.jca.cci.RecordTypeNotSupportedException;
import org.springframework.jca.cci.connection.ConnectionFactoryUtils;
import org.springframework.jca.cci.connection.NotSupportedRecordFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -103,7 +105,7 @@ public class CciTemplate implements CciOperations {
* @param connectionSpec the CCI ConnectionSpec to obtain Connections for
* (may be {@code null})
*/
public CciTemplate(ConnectionFactory connectionFactory, ConnectionSpec connectionSpec) {
public CciTemplate(ConnectionFactory connectionFactory, @Nullable ConnectionSpec connectionSpec) {
setConnectionFactory(connectionFactory);
setConnectionSpec(connectionSpec);
afterPropertiesSet();
@@ -135,6 +137,7 @@ public class CciTemplate implements CciOperations {
/**
* Return the CCI ConnectionSpec used by this template, if any.
*/
@Nullable
public ConnectionSpec getConnectionSpec() {
return this.connectionSpec;
}
@@ -158,6 +161,7 @@ public class CciTemplate implements CciOperations {
/**
* Return a RecordCreator that should be used for creating default output Records.
*/
@Nullable
public RecordCreator getOutputRecordCreator() {
return this.outputRecordCreator;
}
@@ -267,7 +271,7 @@ public class CciTemplate implements CciOperations {
* @throws DataAccessException if there is any problem
*/
protected <T> T doExecute(
final InteractionSpec spec, final Record inputRecord, final Record outputRecord,
final InteractionSpec spec, final Record inputRecord, @Nullable final Record outputRecord,
final RecordExtractor<T> outputExtractor) throws DataAccessException {
return execute(new InteractionCallback<T>() {

View File

@@ -17,11 +17,13 @@
package org.springframework.jca.cci.core;
import java.sql.SQLException;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
/**
* Generic callback interface for code that operates on a CCI Connection.
@@ -70,6 +72,7 @@ public interface ConnectionCallback<T> {
* @see javax.resource.cci.ConnectionFactory#getMetaData()
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
*/
@Nullable
T doInConnection(Connection connection, ConnectionFactory connectionFactory)
throws ResourceException, SQLException, DataAccessException;

View File

@@ -17,11 +17,13 @@
package org.springframework.jca.cci.core;
import java.sql.SQLException;
import javax.resource.ResourceException;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.Interaction;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
/**
* Generic callback interface for code that operates on a CCI Interaction.
@@ -71,6 +73,7 @@ public interface InteractionCallback<T> {
* @see javax.resource.cci.ConnectionFactory#getMetaData()
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor)
*/
@Nullable
T doInInteraction(Interaction interaction, ConnectionFactory connectionFactory)
throws ResourceException, SQLException, DataAccessException;

View File

@@ -17,10 +17,12 @@
package org.springframework.jca.cci.core;
import java.sql.SQLException;
import javax.resource.ResourceException;
import javax.resource.cci.Record;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
/**
* Callback interface for extracting a result object from a CCI Record instance.
@@ -58,6 +60,7 @@ public interface RecordExtractor<T> {
* @throws DataAccessException in case of custom exceptions
* @see javax.resource.cci.ResultSet
*/
@Nullable
T extractData(Record record) throws ResourceException, SQLException, DataAccessException;
}

View File

@@ -2,4 +2,7 @@
* Provides the core JCA CCI support, based on CciTemplate
* and its associated callback interfaces.
*/
@NonNullApi
package org.springframework.jca.cci.core;
import org.springframework.lang.NonNullApi;

View File

@@ -2,4 +2,7 @@
* Classes supporting the {@code org.springframework.jca.cci.core} package.
* Contains a DAO base class for CciTemplate usage.
*/
@NonNullApi
package org.springframework.jca.cci.core.support;
import org.springframework.lang.NonNullApi;

View File

@@ -5,4 +5,7 @@
* Exceptions thrown are as in the {@code org.springframework.dao} package,
* meaning that code using this package does not need to worry about error handling.
*/
@NonNullApi
package org.springframework.jca.cci.object;
import org.springframework.lang.NonNullApi;

View File

@@ -4,4 +4,7 @@
* to the {@code org.springframework.jdbc} package, providing the same
* levels of data access abstraction.
*/
@NonNullApi
package org.springframework.jca.cci;
import org.springframework.lang.NonNullApi;

View File

@@ -33,6 +33,7 @@ import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@@ -230,6 +231,7 @@ public class SpringContextResourceAdapter implements ResourceAdapter {
* This implementation always returns {@code null}.
*/
@Override
@Nullable
public XAResource[] getXAResources(ActivationSpec[] activationSpecs) throws ResourceException {
return null;
}

View File

@@ -2,4 +2,7 @@
* Integration package that allows for deploying a Spring application context
* as a JCA 1.7 compliant RAR file.
*/
@NonNullApi
package org.springframework.jca.context;
import org.springframework.lang.NonNullApi;

View File

@@ -30,6 +30,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.lang.Nullable;
import org.springframework.transaction.jta.SimpleTransactionFactory;
import org.springframework.transaction.jta.TransactionFactory;
@@ -135,6 +136,7 @@ public abstract class AbstractMessageEndpointFactory implements MessageEndpointF
* @see #setBeanName
*/
@Override
@Nullable
public String getActivationName() {
return this.beanName;
}
@@ -144,6 +146,7 @@ public abstract class AbstractMessageEndpointFactory implements MessageEndpointF
* returning {@code} null in order to indicate a synthetic endpoint type.
*/
@Override
@Nullable
public Class<?> getEndpointClass() {
return null;
}

View File

@@ -1,4 +1,7 @@
/**
* This package provides a facility for generic JCA message endpoint management.
*/
@NonNullApi
package org.springframework.jca.endpoint;
import org.springframework.lang.NonNullApi;

View File

@@ -17,6 +17,7 @@
package org.springframework.jca.support;
import java.util.Timer;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.UnavailableException;
import javax.resource.spi.XATerminator;
@@ -24,6 +25,8 @@ import javax.resource.spi.work.WorkContext;
import javax.resource.spi.work.WorkManager;
import javax.transaction.TransactionSynchronizationRegistry;
import org.springframework.lang.Nullable;
/**
* Simple implementation of the JCA 1.7 {@link javax.resource.spi.BootstrapContext}
* interface, used for bootstrapping a JCA ResourceAdapter in a local environment.
@@ -50,7 +53,7 @@ public class SimpleBootstrapContext implements BootstrapContext {
* with no XATerminator available.
* @param workManager the JCA WorkManager to use (may be {@code null})
*/
public SimpleBootstrapContext(WorkManager workManager) {
public SimpleBootstrapContext(@Nullable WorkManager workManager) {
this.workManager = workManager;
}
@@ -59,7 +62,7 @@ public class SimpleBootstrapContext implements BootstrapContext {
* @param workManager the JCA WorkManager to use (may be {@code null})
* @param xaTerminator the JCA XATerminator to use (may be {@code null})
*/
public SimpleBootstrapContext(WorkManager workManager, XATerminator xaTerminator) {
public SimpleBootstrapContext(@Nullable WorkManager workManager, @Nullable XATerminator xaTerminator) {
this.workManager = workManager;
this.xaTerminator = xaTerminator;
}
@@ -73,8 +76,8 @@ public class SimpleBootstrapContext implements BootstrapContext {
* to use (may be {@code null})
* @since 5.0
*/
public SimpleBootstrapContext(WorkManager workManager, XATerminator xaTerminator,
TransactionSynchronizationRegistry transactionSynchronizationRegistry) {
public SimpleBootstrapContext(@Nullable WorkManager workManager, @Nullable XATerminator xaTerminator,
@Nullable TransactionSynchronizationRegistry transactionSynchronizationRegistry) {
this.workManager = workManager;
this.xaTerminator = xaTerminator;

View File

@@ -2,4 +2,7 @@
* Provides generic support classes for JCA usage within Spring,
* mainly for local setup of a JCA ResourceAdapter and/or ConnectionFactory.
*/
@NonNullApi
package org.springframework.jca.support;
import org.springframework.lang.NonNullApi;

View File

@@ -35,6 +35,7 @@ import org.springframework.core.task.TaskRejectedException;
import org.springframework.core.task.TaskTimeoutException;
import org.springframework.jca.context.BootstrapContextAware;
import org.springframework.jndi.JndiLocatorSupport;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.SchedulingException;
import org.springframework.scheduling.SchedulingTaskExecutor;
import org.springframework.util.Assert;
@@ -157,7 +158,7 @@ public class WorkManagerTaskExecutor extends JndiLocatorSupport
* <p>This shared WorkListener instance will be passed on to the
* WorkManager by all {@link #execute} calls on this TaskExecutor.
*/
public void setWorkListener(WorkListener workListener) {
public void setWorkListener(@Nullable WorkListener workListener) {
this.workListener = workListener;
}

View File

@@ -2,4 +2,7 @@
* Convenience classes for scheduling based on the JCA WorkManager facility,
* as supported within ResourceAdapters.
*/
@NonNullApi
package org.springframework.jca.work;
import org.springframework.lang.NonNullApi;

View File

@@ -16,6 +16,8 @@
package org.springframework.transaction;
import org.springframework.lang.Nullable;
/**
* This is the central interface in Spring's transaction infrastructure.
* Applications can use this directly, but it is not primarily meant as API:
@@ -66,7 +68,7 @@ public interface PlatformTransactionManager {
* @see TransactionDefinition#getTimeout
* @see TransactionDefinition#isReadOnly
*/
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
/**
* Commit the given transaction, with regard to its status. If the transaction

View File

@@ -18,6 +18,8 @@ package org.springframework.transaction;
import java.sql.Connection;
import org.springframework.lang.Nullable;
/**
* Interface that defines Spring-compliant transaction properties.
* Based on the propagation behavior definitions analogous to EJB CMT attributes.
@@ -253,6 +255,7 @@ public interface TransactionDefinition {
* @see org.springframework.transaction.interceptor.TransactionAspectSupport
* @see org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionName()
*/
@Nullable
String getName();
}

View File

@@ -16,6 +16,7 @@
package org.springframework.transaction;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -69,6 +70,7 @@ public class TransactionSystemException extends TransactionException {
* if any.
* @return the application exception, or {@code null} if none set
*/
@Nullable
public final Throwable getApplicationException() {
return this.applicationException;
}
@@ -78,6 +80,7 @@ public class TransactionSystemException extends TransactionException {
* i.e. the application exception, if any, or the TransactionSystemException's own cause.
* @return the original exception, or {@code null} if there was none
*/
@Nullable
public Throwable getOriginalException() {
return (this.applicationException != null ? this.applicationException : getCause());
}

View File

@@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.util.Assert;
@@ -149,6 +150,7 @@ public class AnnotationTransactionAttributeSource extends AbstractFallbackTransa
* @return TransactionAttribute the configured transaction attribute,
* or {@code null} if none was found
*/
@Nullable
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);

View File

@@ -18,6 +18,7 @@ package org.springframework.transaction.annotation;
import java.lang.reflect.AnnotatedElement;
import org.springframework.lang.Nullable;
import org.springframework.transaction.interceptor.TransactionAttribute;
/**
@@ -47,6 +48,7 @@ public interface TransactionAnnotationParser {
* or {@code null} if none was found
* @see AnnotationTransactionAttributeSource#determineTransactionAttribute
*/
@Nullable
TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae);
}

View File

@@ -3,4 +3,7 @@
* Hooked into Spring's transaction interception infrastructure
* via a special TransactionAttributeSource implementation.
*/
@NonNullApi
package org.springframework.transaction.annotation;
import org.springframework.lang.NonNullApi;

View File

@@ -2,4 +2,7 @@
* Support package for declarative transaction configuration,
* with XML schema being the primary configuration format.
*/
@NonNullApi
package org.springframework.transaction.config;
import org.springframework.lang.NonNullApi;

View File

@@ -1,4 +1,7 @@
/**
* Spring's support for listening to transaction events.
*/
@NonNullApi
package org.springframework.transaction.event;
import org.springframework.lang.NonNullApi;

View File

@@ -26,6 +26,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.core.MethodClassKey;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
@@ -81,7 +82,7 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
* is not transactional
*/
@Override
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
@@ -128,7 +129,7 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
* @param targetClass the target class (may be {@code null})
* @return the cache key (never {@code null})
*/
protected Object getCacheKey(Method method, Class<?> targetClass) {
protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) {
return new MethodClassKey(method, targetClass);
}
@@ -139,6 +140,7 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
* @since 4.1.8
* @see #getTransactionAttribute
*/
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
@@ -189,6 +191,7 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
* @return all transaction attribute associated with this method
* (or {@code null} if none)
*/
@Nullable
protected abstract TransactionAttribute findTransactionAttribute(Method method);
/**
@@ -198,6 +201,7 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
* @return all transaction attribute associated with this class
* (or {@code null} if none)
*/
@Nullable
protected abstract TransactionAttribute findTransactionAttribute(Class<?> clazz);

View File

@@ -16,6 +16,7 @@
package org.springframework.transaction.interceptor;
import org.springframework.lang.Nullable;
import org.springframework.transaction.support.DefaultTransactionDefinition;
/**
@@ -106,6 +107,7 @@ public class DefaultTransactionAttribute extends DefaultTransactionDefinition im
* or {@code null} if none.
* @since 4.3.4
*/
@Nullable
public String getDescriptor() {
return this.descriptor;
}

View File

@@ -28,6 +28,7 @@ import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
import org.springframework.core.NamedThreadLocal;
import org.springframework.lang.Nullable;
import org.springframework.transaction.NoTransactionException;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
@@ -105,6 +106,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* @see org.springframework.transaction.support.TransactionSynchronizationManager#isSynchronizationActive()
* @see org.springframework.transaction.support.TransactionSynchronizationManager#isActualTransactionActive()
*/
@Nullable
protected static TransactionInfo currentTransactionInfo() throws NoTransactionException {
return transactionInfoHolder.get();
}
@@ -167,6 +169,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
/**
* Return the default transaction manager, or {@code null} if unknown.
*/
@Nullable
public PlatformTransactionManager getTransactionManager() {
return this.transactionManager;
}
@@ -264,6 +267,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* @return the return value of the method, if any
* @throws Throwable propagated from the target invocation
*/
@Nullable
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable {
@@ -411,6 +415,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* @return a String representation identifying this method
* @see org.springframework.util.ClassUtils#getQualifiedMethodName
*/
@Nullable
protected String methodIdentification(Method method, Class<?> targetClass) {
return null;
}
@@ -429,7 +434,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
*/
@SuppressWarnings("serial")
protected TransactionInfo createTransactionIfNecessary(
PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {
PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// If no name specified, apply method identification as transaction name.
if (txAttr != null && txAttr.getName() == null) {
@@ -465,7 +470,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* @return the prepared TransactionInfo object
*/
protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,
TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {
@Nullable TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
if (txAttr != null) {
@@ -563,7 +568,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* <p>Call this in all cases: exception or normal return!
* @param txInfo information about the current transaction (may be {@code null})
*/
protected void cleanupTransactionInfo(TransactionInfo txInfo) {
protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) {
if (txInfo != null) {
txInfo.restoreThreadLocalStatus();
}

View File

@@ -18,6 +18,8 @@ package org.springframework.transaction.interceptor;
import java.lang.reflect.Method;
import org.springframework.lang.Nullable;
/**
* Strategy interface used by {@link TransactionInterceptor} for metadata retrieval.
*
@@ -41,6 +43,7 @@ public interface TransactionAttributeSource {
* @return TransactionAttribute the matching transaction attribute,
* or {@code null} if none found
*/
TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass);
@Nullable
TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass);
}

View File

@@ -20,6 +20,7 @@ import java.io.Serializable;
import java.lang.reflect.Method;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
/**
@@ -68,6 +69,7 @@ abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPoi
* Obtain the underlying TransactionAttributeSource (may be {@code null}).
* To be implemented by subclasses.
*/
@Nullable
protected abstract TransactionAttributeSource getTransactionAttributeSource();
}

View File

@@ -11,4 +11,7 @@
* This allows declarative transaction management in any environment,
* even without JTA if an application uses only a single database.
*/
@NonNullApi
package org.springframework.transaction.interceptor;
import org.springframework.lang.NonNullApi;

View File

@@ -21,6 +21,7 @@ import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.List;
import java.util.Properties;
import javax.naming.NamingException;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
@@ -36,6 +37,7 @@ import javax.transaction.UserTransaction;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jndi.JndiTemplate;
import org.springframework.lang.Nullable;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.HeuristicCompletionException;
import org.springframework.transaction.IllegalTransactionStateException;
@@ -331,6 +333,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
/**
* Return the JTA TransactionManager that this transaction manager uses, if any.
*/
@Nullable
public TransactionManager getTransactionManager() {
return this.transactionManager;
}
@@ -383,6 +386,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
/**
* Return the JTA 1.1 TransactionSynchronizationRegistry that this transaction manager uses, if any.
*/
@Nullable
public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() {
return this.transactionSynchronizationRegistry;
}
@@ -632,6 +636,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
* @see #setUserTransaction
* @see #setUserTransactionName
*/
@Nullable
protected UserTransaction retrieveUserTransaction() throws TransactionSystemException {
return null;
}
@@ -645,6 +650,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
* @see #setTransactionManager
* @see #setTransactionManagerName
*/
@Nullable
protected TransactionManager retrieveTransactionManager() throws TransactionSystemException {
return null;
}
@@ -657,6 +663,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
* or {@code null} if none found
* @throws TransactionSystemException in case of errors
*/
@Nullable
protected TransactionSynchronizationRegistry retrieveTransactionSynchronizationRegistry() throws TransactionSystemException {
return null;
}
@@ -667,6 +674,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
* @return the JTA UserTransaction reference, or {@code null} if not found
* @see #DEFAULT_USER_TRANSACTION_NAME
*/
@Nullable
protected UserTransaction findUserTransaction() {
String jndiName = DEFAULT_USER_TRANSACTION_NAME;
try {
@@ -693,6 +701,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
* @return the JTA TransactionManager reference, or {@code null} if not found
* @see #FALLBACK_TRANSACTION_MANAGER_NAMES
*/
@Nullable
protected TransactionManager findTransactionManager(UserTransaction ut) {
if (ut instanceof TransactionManager) {
if (logger.isDebugEnabled()) {
@@ -732,6 +741,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
* or {@code null} if none found
* @throws TransactionSystemException in case of errors
*/
@Nullable
protected TransactionSynchronizationRegistry findTransactionSynchronizationRegistry(UserTransaction ut, TransactionManager tm)
throws TransactionSystemException {

View File

@@ -20,6 +20,8 @@ import javax.transaction.NotSupportedException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import org.springframework.lang.Nullable;
/**
* Strategy interface for creating JTA {@link javax.transaction.Transaction}
* objects based on specified transactional characteristics.
@@ -47,7 +49,7 @@ public interface TransactionFactory {
* @throws SystemException if the transaction manager failed to create the
* transaction
*/
Transaction createTransaction(String name, int timeout) throws NotSupportedException, SystemException;
Transaction createTransaction(@Nullable String name, int timeout) throws NotSupportedException, SystemException;
/**
* Determine whether the underlying transaction manager supports XA transactions

View File

@@ -1,4 +1,7 @@
/**
* Transaction SPI implementation for JTA.
*/
@NonNullApi
package org.springframework.transaction.jta;
import org.springframework.lang.NonNullApi;

View File

@@ -3,4 +3,7 @@
* independent of any specific transaction management system.
* Contains transaction manager, definition, and status interfaces.
*/
@NonNullApi
package org.springframework.transaction;
import org.springframework.lang.NonNullApi;

View File

@@ -25,6 +25,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.Constants;
import org.springframework.lang.Nullable;
import org.springframework.transaction.IllegalTransactionStateException;
import org.springframework.transaction.InvalidTimeoutException;
import org.springframework.transaction.NestedTransactionNotSupportedException;
@@ -562,7 +563,8 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
* @see #doSuspend
* @see #resume
*/
protected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException {
@Nullable
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
try {
@@ -608,7 +610,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
* @see #doResume
* @see #suspend
*/
protected final void resume(Object transaction, SuspendedResourcesHolder resourcesHolder)
protected final void resume(Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
throws TransactionException {
if (resourcesHolder != null) {

View File

@@ -16,6 +16,7 @@
package org.springframework.transaction.support;
import org.springframework.lang.Nullable;
import org.springframework.transaction.NestedTransactionNotSupportedException;
import org.springframework.transaction.SavepointManager;
import org.springframework.transaction.TransactionException;
@@ -126,6 +127,7 @@ public abstract class AbstractTransactionStatus implements TransactionStatus {
/**
* Get the savepoint for this transaction, if any.
*/
@Nullable
protected Object getSavepoint() {
return this.savepoint;
}

View File

@@ -16,6 +16,7 @@
package org.springframework.transaction.support;
import org.springframework.lang.Nullable;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
@@ -53,6 +54,7 @@ public interface CallbackPreferringPlatformTransactionManager extends PlatformTr
* @throws TransactionException in case of initialization, rollback, or system errors
* @throws RuntimeException if thrown by the TransactionCallback
*/
@Nullable
<T> T execute(TransactionDefinition definition, TransactionCallback<T> callback)
throws TransactionException;

View File

@@ -16,6 +16,7 @@
package org.springframework.transaction.support;
import org.springframework.lang.Nullable;
import org.springframework.transaction.NestedTransactionNotSupportedException;
import org.springframework.transaction.SavepointManager;
@@ -78,7 +79,7 @@ public class DefaultTransactionStatus extends AbstractTransactionStatus {
*/
public DefaultTransactionStatus(
Object transaction, boolean newTransaction, boolean newSynchronization,
boolean readOnly, boolean debug, Object suspendedResources) {
boolean readOnly, boolean debug, @Nullable Object suspendedResources) {
this.transaction = transaction;
this.newTransaction = newTransaction;
@@ -136,6 +137,7 @@ public class DefaultTransactionStatus extends AbstractTransactionStatus {
* Return the holder for resources that have been suspended for this transaction,
* if any.
*/
@Nullable
public Object getSuspendedResources() {
return this.suspendedResources;
}

View File

@@ -16,6 +16,7 @@
package org.springframework.transaction.support;
import org.springframework.lang.Nullable;
import org.springframework.transaction.TransactionStatus;
/**
@@ -50,6 +51,7 @@ public interface TransactionCallback<T> {
* @see TransactionTemplate#execute
* @see CallbackPreferringPlatformTransactionManager#execute
*/
@Nullable
T doInTransaction(TransactionStatus status);
}

View File

@@ -16,6 +16,7 @@
package org.springframework.transaction.support;
import org.springframework.lang.Nullable;
import org.springframework.transaction.TransactionException;
/**
@@ -40,6 +41,7 @@ public interface TransactionOperations {
* @throws TransactionException in case of initialization, rollback, or system errors
* @throws RuntimeException if thrown by the TransactionCallback
*/
@Nullable
<T> T execute(TransactionCallback<T> action) throws TransactionException;
}

View File

@@ -29,6 +29,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.core.NamedThreadLocal;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -133,6 +134,7 @@ public abstract class TransactionSynchronizationManager {
* resource object), or {@code null} if none
* @see ResourceTransactionManager#getResourceFactory()
*/
@Nullable
public static Object getResource(Object key) {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Object value = doGetResource(actualKey);
@@ -146,6 +148,7 @@ public abstract class TransactionSynchronizationManager {
/**
* Actually check the value of the resource that is bound for the given key.
*/
@Nullable
private static Object doGetResource(Object actualKey) {
Map<Object, Object> map = resources.get();
if (map == null) {
@@ -217,6 +220,7 @@ public abstract class TransactionSynchronizationManager {
* @param key the key to unbind (usually the resource factory)
* @return the previously bound value, or {@code null} if none bound
*/
@Nullable
public static Object unbindResourceIfPossible(Object key) {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
return doUnbindResource(actualKey);
@@ -225,6 +229,7 @@ public abstract class TransactionSynchronizationManager {
/**
* Actually remove the value of the resource that is bound for the given key.
*/
@Nullable
private static Object doUnbindResource(Object actualKey) {
Map<Object, Object> map = resources.get();
if (map == null) {
@@ -343,7 +348,7 @@ public abstract class TransactionSynchronizationManager {
* @param name the name of the transaction, or {@code null} to reset it
* @see org.springframework.transaction.TransactionDefinition#getName()
*/
public static void setCurrentTransactionName(String name) {
public static void setCurrentTransactionName(@Nullable String name) {
currentTransactionName.set(name);
}
@@ -353,6 +358,7 @@ public abstract class TransactionSynchronizationManager {
* for example to optimize fetch strategies for specific named transactions.
* @see org.springframework.transaction.TransactionDefinition#getName()
*/
@Nullable
public static String getCurrentTransactionName() {
return currentTransactionName.get();
}
@@ -400,7 +406,7 @@ public abstract class TransactionSynchronizationManager {
* @see org.springframework.transaction.TransactionDefinition#ISOLATION_SERIALIZABLE
* @see org.springframework.transaction.TransactionDefinition#getIsolationLevel()
*/
public static void setCurrentTransactionIsolationLevel(Integer isolationLevel) {
public static void setCurrentTransactionIsolationLevel(@Nullable Integer isolationLevel) {
currentTransactionIsolationLevel.set(isolationLevel);
}
@@ -421,6 +427,7 @@ public abstract class TransactionSynchronizationManager {
* @see org.springframework.transaction.TransactionDefinition#ISOLATION_SERIALIZABLE
* @see org.springframework.transaction.TransactionDefinition#getIsolationLevel()
*/
@Nullable
public static Integer getCurrentTransactionIsolationLevel() {
return currentTransactionIsolationLevel.get();
}

View File

@@ -3,4 +3,7 @@
* Provides an abstract base class for transaction manager implementations,
* and a template plus callback for transaction demarcation.
*/
@NonNullApi
package org.springframework.transaction.support;
import org.springframework.lang.NonNullApi;