Consistent use of @Nullable across the codebase (even for internals)

Beyond just formally declaring the current behavior, this revision actually enforces non-null behavior in selected signatures now, not tolerating null values anymore when not explicitly documented. It also changes some utility methods with historic null-in/null-out tolerance towards enforced non-null return values, making them a proper citizen in non-null assignments.

Some issues are left as to-do: in particular a thorough revision of spring-test, and a few tests with unclear failures (ignored as "TODO: NULLABLE") to be sorted out in a follow-up commit.

Issue: SPR-15540
This commit is contained in:
Juergen Hoeller
2017-06-07 14:17:48 +02:00
parent ffc3f6d87d
commit f813712f5b
1493 changed files with 10670 additions and 9172 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -16,6 +16,8 @@
package org.springframework.dao;
import org.springframework.lang.Nullable;
/**
* Exception thrown on concurrency failure.
*
@@ -45,7 +47,7 @@ public class ConcurrencyFailureException extends TransientDataAccessException {
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public ConcurrencyFailureException(String msg, Throwable cause) {
public ConcurrencyFailureException(String msg, @Nullable Throwable cause) {
super(msg, cause);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -17,6 +17,7 @@
package org.springframework.dao;
import org.springframework.core.NestedRuntimeException;
import org.springframework.lang.Nullable;
/**
* Root of the hierarchy of data access exceptions discussed in
@@ -52,7 +53,7 @@ public abstract class DataAccessException extends NestedRuntimeException {
* @param cause the root cause (usually from using a underlying
* data access API such as JDBC)
*/
public DataAccessException(String msg, Throwable cause) {
public DataAccessException(@Nullable String msg, @Nullable Throwable cause) {
super(msg, cause);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -16,6 +16,8 @@
package org.springframework.dao;
import org.springframework.lang.Nullable;
/**
* Data access exception thrown when a resource fails completely:
* for example, if we can't connect to a database using JDBC.
@@ -39,7 +41,7 @@ public class DataAccessResourceFailureException extends NonTransientDataAccessRe
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public DataAccessResourceFailureException(String msg, Throwable cause) {
public DataAccessResourceFailureException(String msg, @Nullable Throwable cause) {
super(msg, cause);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -16,6 +16,8 @@
package org.springframework.dao;
import org.springframework.lang.Nullable;
/**
* Exception thrown if certain expected data could not be retrieved, e.g.
* when looking up specific data via a known identifier. This exception
@@ -40,7 +42,7 @@ public class DataRetrievalFailureException extends NonTransientDataAccessExcepti
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public DataRetrievalFailureException(String msg, Throwable cause) {
public DataRetrievalFailureException(String msg, @Nullable Throwable cause) {
super(msg, cause);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -16,6 +16,8 @@
package org.springframework.dao;
import org.springframework.lang.Nullable;
/**
* Root of the hierarchy of data access exceptions that are considered non-transient -
* where a retry of the same operation would fail unless the cause of the Exception
@@ -42,7 +44,7 @@ public abstract class NonTransientDataAccessException extends DataAccessExceptio
* @param cause the root cause (usually from using a underlying
* data access API such as JDBC)
*/
public NonTransientDataAccessException(String msg, Throwable cause) {
public NonTransientDataAccessException(@Nullable String msg, @Nullable Throwable cause) {
super(msg, cause);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -16,6 +16,8 @@
package org.springframework.dao;
import org.springframework.lang.Nullable;
/**
* Data access exception thrown when a resource fails completely and the failure is permanent.
*
@@ -39,7 +41,7 @@ public class NonTransientDataAccessResourceException extends NonTransientDataAcc
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public NonTransientDataAccessResourceException(String msg, Throwable cause) {
public NonTransientDataAccessResourceException(String msg, @Nullable Throwable cause) {
super(msg, cause);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -16,6 +16,8 @@
package org.springframework.dao;
import org.springframework.lang.Nullable;
/**
* Exception thrown on an optimistic locking violation.
*
@@ -42,7 +44,7 @@ public class OptimisticLockingFailureException extends ConcurrencyFailureExcepti
* @param msg the detail message
* @param cause the root cause from the data access API in use
*/
public OptimisticLockingFailureException(String msg, Throwable cause) {
public OptimisticLockingFailureException(String msg, @Nullable Throwable cause) {
super(msg, cause);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -16,6 +16,8 @@
package org.springframework.dao;
import org.springframework.lang.Nullable;
/**
* Root of the hierarchy of data access exceptions that are considered transient -
* where a previously failed operation might be able to succeed when the operation
@@ -42,7 +44,7 @@ public abstract class TransientDataAccessException extends DataAccessException {
* @param cause the root cause (usually from using a underlying
* data access API such as JDBC)
*/
public TransientDataAccessException(String msg, Throwable cause) {
public TransientDataAccessException(String msg, @Nullable Throwable cause) {
super(msg, cause);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -16,6 +16,8 @@
package org.springframework.dao;
import org.springframework.lang.Nullable;
/**
* Normal superclass when we can't distinguish anything more specific
* than "something went wrong with the underlying resource": for example,
@@ -31,7 +33,7 @@ public abstract class UncategorizedDataAccessException extends NonTransientDataA
* @param msg the detail message
* @param cause the exception thrown by underlying data access API
*/
public UncategorizedDataAccessException(String msg, Throwable cause) {
public UncategorizedDataAccessException(@Nullable String msg, @Nullable Throwable cause) {
super(msg, cause);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -46,7 +46,7 @@ public abstract class DataAccessUtils {
* element has been found in the given Collection
*/
@Nullable
public static <T> T singleResult(Collection<T> results) throws IncorrectResultSizeDataAccessException {
public static <T> T singleResult(@Nullable Collection<T> results) throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
return null;
@@ -137,7 +137,7 @@ public abstract class DataAccessUtils {
* not match the specified required type
*/
@SuppressWarnings("unchecked")
public static <T> T objectResult(@Nullable Collection<?> results, Class<T> requiredType)
public static <T> T objectResult(@Nullable Collection<?> results, @Nullable Class<T> requiredType)
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException {
Object result = requiredUniqueResult(results);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -32,6 +32,7 @@ import org.springframework.transaction.support.AbstractPlatformTransactionManage
import org.springframework.transaction.support.DefaultTransactionStatus;
import org.springframework.transaction.support.ResourceTransactionManager;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
/**
* {@link org.springframework.transaction.PlatformTransactionManager} implementation
@@ -106,10 +107,17 @@ public class CciLocalTransactionManager extends AbstractPlatformTransactionManag
* Return the CCI ConnectionFactory that this instance manages local
* transactions for.
*/
@Nullable
public ConnectionFactory getConnectionFactory() {
return this.connectionFactory;
}
private ConnectionFactory obtainConnectionFactory() {
ConnectionFactory connectionFactory = getConnectionFactory();
Assert.state(connectionFactory != null, "No ConnectionFactory set");
return connectionFactory;
}
@Override
public void afterPropertiesSet() {
if (getConnectionFactory() == null) {
@@ -120,14 +128,14 @@ public class CciLocalTransactionManager extends AbstractPlatformTransactionManag
@Override
public Object getResourceFactory() {
return getConnectionFactory();
return obtainConnectionFactory();
}
@Override
protected Object doGetTransaction() {
CciLocalTransactionObject txObject = new CciLocalTransactionObject();
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(getConnectionFactory());
(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainConnectionFactory());
txObject.setConnectionHolder(conHolder);
return txObject;
}
@@ -136,40 +144,43 @@ public class CciLocalTransactionManager extends AbstractPlatformTransactionManag
protected boolean isExistingTransaction(Object transaction) {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
// Consider a pre-bound connection as transaction.
return (txObject.getConnectionHolder() != null);
return txObject.hasConnectionHolder();
}
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
ConnectionFactory connectionFactory = obtainConnectionFactory();
Connection con = null;
try {
con = getConnectionFactory().getConnection();
con = connectionFactory.getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + con + "] for local CCI transaction");
}
txObject.setConnectionHolder(new ConnectionHolder(con));
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
ConnectionHolder connectionHolder = new ConnectionHolder(con);
connectionHolder.setSynchronizedWithTransaction(true);
con.getLocalTransaction().begin();
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
connectionHolder.setTimeoutInSeconds(timeout);
}
TransactionSynchronizationManager.bindResource(getConnectionFactory(), txObject.getConnectionHolder());
txObject.setConnectionHolder(connectionHolder);
TransactionSynchronizationManager.bindResource(connectionFactory, connectionHolder);
}
catch (NotSupportedException ex) {
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory());
ConnectionFactoryUtils.releaseConnection(con, connectionFactory);
throw new CannotCreateTransactionException("CCI Connection does not support local transactions", ex);
}
catch (LocalTransactionException ex) {
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory());
ConnectionFactoryUtils.releaseConnection(con, connectionFactory);
throw new CannotCreateTransactionException("Could not begin local CCI transaction", ex);
}
catch (Throwable ex) {
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory());
ConnectionFactoryUtils.releaseConnection(con, connectionFactory);
throw new TransactionSystemException("Unexpected failure on begin of CCI local transaction", ex);
}
}
@@ -178,13 +189,13 @@ public class CciLocalTransactionManager extends AbstractPlatformTransactionManag
protected Object doSuspend(Object transaction) {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
txObject.setConnectionHolder(null);
return TransactionSynchronizationManager.unbindResource(getConnectionFactory());
return TransactionSynchronizationManager.unbindResource(obtainConnectionFactory());
}
@Override
protected void doResume(Object transaction, Object suspendedResources) {
protected void doResume(@Nullable Object transaction, Object suspendedResources) {
ConnectionHolder conHolder = (ConnectionHolder) suspendedResources;
TransactionSynchronizationManager.bindResource(getConnectionFactory(), conHolder);
TransactionSynchronizationManager.bindResource(obtainConnectionFactory(), conHolder);
}
protected boolean isRollbackOnly(Object transaction) throws TransactionException {
@@ -241,16 +252,17 @@ public class CciLocalTransactionManager extends AbstractPlatformTransactionManag
@Override
protected void doCleanupAfterCompletion(Object transaction) {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
ConnectionFactory connectionFactory = obtainConnectionFactory();
// Remove the connection holder from the thread.
TransactionSynchronizationManager.unbindResource(getConnectionFactory());
TransactionSynchronizationManager.unbindResource(connectionFactory);
txObject.getConnectionHolder().clear();
Connection con = txObject.getConnectionHolder().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Releasing CCI Connection [" + con + "] after transaction");
}
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory());
ConnectionFactoryUtils.releaseConnection(con, connectionFactory);
}
@@ -268,8 +280,13 @@ public class CciLocalTransactionManager extends AbstractPlatformTransactionManag
}
public ConnectionHolder getConnectionHolder() {
Assert.state(this.connectionHolder != null, "No ConnectionHolder available");
return this.connectionHolder;
}
public boolean hasConnectionHolder() {
return (this.connectionHolder != null);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -163,7 +163,7 @@ public abstract class ConnectionFactoryUtils {
* (can be {@code null})
* @see #getConnection
*/
public static void releaseConnection(Connection con, @Nullable ConnectionFactory cf) {
public static void releaseConnection(@Nullable Connection con, @Nullable ConnectionFactory cf) {
try {
doReleaseConnection(con, cf);
}
@@ -187,7 +187,9 @@ public abstract class ConnectionFactoryUtils {
* @throws ResourceException if thrown by JCA CCI methods
* @see #doGetConnection
*/
public static void doReleaseConnection(Connection con, @Nullable ConnectionFactory cf) throws ResourceException {
public static void doReleaseConnection(@Nullable Connection con, @Nullable ConnectionFactory cf)
throws ResourceException {
if (con == null || isConnectionTransactional(con, cf)) {
return;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -18,9 +18,12 @@ package org.springframework.jca.cci.connection;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.ConnectionSpec;
import org.springframework.core.NamedThreadLocal;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* An adapter for a target CCI {@link javax.resource.cci.ConnectionFactory},
@@ -128,16 +131,10 @@ public class ConnectionSpecConnectionFactoryAdapter extends DelegatingConnection
* @see javax.resource.cci.ConnectionFactory#getConnection(javax.resource.cci.ConnectionSpec)
* @see javax.resource.cci.ConnectionFactory#getConnection()
*/
protected Connection doGetConnection(ConnectionSpec spec) throws ResourceException {
if (getTargetConnectionFactory() == null) {
throw new IllegalStateException("targetConnectionFactory is required");
}
if (spec != null) {
return getTargetConnectionFactory().getConnection(spec);
}
else {
return getTargetConnectionFactory().getConnection();
}
protected Connection doGetConnection(@Nullable ConnectionSpec spec) throws ResourceException {
ConnectionFactory connectionFactory = getTargetConnectionFactory();
Assert.state(connectionFactory != null, "No 'targetConnectionFactory' set");
return (spec != null ? connectionFactory.getConnection(spec) : connectionFactory.getConnection());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -26,6 +26,8 @@ import javax.resource.cci.RecordFactory;
import javax.resource.cci.ResourceAdapterMetaData;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* CCI {@link ConnectionFactory} implementation that delegates all calls
@@ -55,10 +57,21 @@ public class DelegatingConnectionFactory implements ConnectionFactory, Initializ
/**
* Return the target ConnectionFactory that this ConnectionFactory should delegate to.
*/
@Nullable
public ConnectionFactory getTargetConnectionFactory() {
return this.targetConnectionFactory;
}
/**
* Obtain the target {@code ConnectionFactory} for actual use (never {@code null}).
* @since 5.0
*/
protected ConnectionFactory obtainTargetConnectionFactory() {
ConnectionFactory connectionFactory = getTargetConnectionFactory();
Assert.state(connectionFactory != null, "No 'targetConnectionFactory' set");
return connectionFactory;
}
@Override
public void afterPropertiesSet() {
@@ -70,32 +83,32 @@ public class DelegatingConnectionFactory implements ConnectionFactory, Initializ
@Override
public Connection getConnection() throws ResourceException {
return getTargetConnectionFactory().getConnection();
return obtainTargetConnectionFactory().getConnection();
}
@Override
public Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException {
return getTargetConnectionFactory().getConnection(connectionSpec);
return obtainTargetConnectionFactory().getConnection(connectionSpec);
}
@Override
public RecordFactory getRecordFactory() throws ResourceException {
return getTargetConnectionFactory().getRecordFactory();
return obtainTargetConnectionFactory().getRecordFactory();
}
@Override
public ResourceAdapterMetaData getMetaData() throws ResourceException {
return getTargetConnectionFactory().getMetaData();
return obtainTargetConnectionFactory().getMetaData();
}
@Override
public Reference getReference() throws NamingException {
return getTargetConnectionFactory().getReference();
return obtainTargetConnectionFactory().getReference();
}
@Override
public void setReference(Reference reference) {
getTargetConnectionFactory().setReference(reference);
obtainTargetConnectionFactory().setReference(reference);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -30,6 +30,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@@ -177,7 +178,9 @@ public class SingleConnectionFactory extends DelegatingConnectionFactory impleme
* @throws javax.resource.ResourceException if thrown by CCI API methods
*/
protected Connection doCreateConnection() throws ResourceException {
return getTargetConnectionFactory().getConnection();
ConnectionFactory connectionFactory = getTargetConnectionFactory();
Assert.state(connectionFactory != null, "No 'targetConnectionFactory' set");
return connectionFactory.getConnection();
}
/**
@@ -229,6 +232,7 @@ public class SingleConnectionFactory extends DelegatingConnectionFactory impleme
}
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -24,6 +24,8 @@ import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import org.springframework.lang.Nullable;
/**
* Proxy for a target CCI {@link javax.resource.cci.ConnectionFactory}, adding
* awareness of Spring-managed transactions. Similar to a transactional JNDI
@@ -91,8 +93,9 @@ public class TransactionAwareConnectionFactoryProxy extends DelegatingConnection
*/
@Override
public Connection getConnection() throws ResourceException {
Connection con = ConnectionFactoryUtils.doGetConnection(getTargetConnectionFactory());
return getTransactionAwareConnectionProxy(con, getTargetConnectionFactory());
ConnectionFactory targetConnectionFactory = obtainTargetConnectionFactory();
Connection con = ConnectionFactoryUtils.doGetConnection(targetConnectionFactory);
return getTransactionAwareConnectionProxy(con, targetConnectionFactory);
}
/**
@@ -128,6 +131,7 @@ public class TransactionAwareConnectionFactoryProxy extends DelegatingConnection
}
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on Connection interface coming in...

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-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.
@@ -75,6 +75,7 @@ public interface CciOperations {
* @return the output record
* @throws DataAccessException if there is any problem
*/
@Nullable
Record execute(InteractionSpec spec, Record inputRecord) throws DataAccessException;
/**
@@ -106,6 +107,7 @@ public interface CciOperations {
* @return the output data extracted with the RecordExtractor object
* @throws DataAccessException if there is any problem
*/
@Nullable
<T> T execute(InteractionSpec spec, Record inputRecord, RecordExtractor<T> outputExtractor)
throws DataAccessException;
@@ -118,6 +120,7 @@ public interface CciOperations {
* @return the output data extracted with the RecordExtractor object
* @throws DataAccessException if there is any problem
*/
@Nullable
<T> T execute(InteractionSpec spec, RecordCreator inputCreator, RecordExtractor<T> outputExtractor)
throws DataAccessException;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -17,7 +17,6 @@
package org.springframework.jca.cci.core;
import java.sql.SQLException;
import javax.resource.NotSupportedException;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
@@ -115,22 +114,29 @@ public class CciTemplate implements CciOperations {
/**
* Set the CCI ConnectionFactory to obtain Connections from.
*/
public void setConnectionFactory(ConnectionFactory connectionFactory) {
public void setConnectionFactory(@Nullable ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
/**
* Return the CCI ConnectionFactory used by this template.
*/
@Nullable
public ConnectionFactory getConnectionFactory() {
return this.connectionFactory;
}
private ConnectionFactory obtainConnectionFactory() {
ConnectionFactory connectionFactory = getConnectionFactory();
Assert.state(connectionFactory != null, "No ConnectionFactory set");
return connectionFactory;
}
/**
* Set the CCI ConnectionSpec that this template instance is
* supposed to obtain Connections for.
*/
public void setConnectionSpec(ConnectionSpec connectionSpec) {
public void setConnectionSpec(@Nullable ConnectionSpec connectionSpec) {
this.connectionSpec = connectionSpec;
}
@@ -154,7 +160,7 @@ public class CciTemplate implements CciOperations {
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record)
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record, Record)
*/
public void setOutputRecordCreator(RecordCreator creator) {
public void setOutputRecordCreator(@Nullable RecordCreator creator) {
this.outputRecordCreator = creator;
}
@@ -194,9 +200,10 @@ public class CciTemplate implements CciOperations {
@Override
public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = ConnectionFactoryUtils.getConnection(getConnectionFactory(), getConnectionSpec());
ConnectionFactory connectionFactory = obtainConnectionFactory();
Connection con = ConnectionFactoryUtils.getConnection(connectionFactory, getConnectionSpec());
try {
return action.doInConnection(con, getConnectionFactory());
return action.doInConnection(con, connectionFactory);
}
catch (NotSupportedException ex) {
throw new CciOperationNotSupportedException("CCI operation not supported by connector", ex);
@@ -242,7 +249,9 @@ public class CciTemplate implements CciOperations {
@Override
public Record execute(InteractionSpec spec, RecordCreator inputCreator) throws DataAccessException {
return doExecute(spec, createRecord(inputCreator), null, new SimpleRecordExtractor());
Record output = doExecute(spec, createRecord(inputCreator), null, new SimpleRecordExtractor());
Assert.state(output != null, "Invalid output record");
return output;
}
@Override
@@ -270,33 +279,30 @@ public class CciTemplate implements CciOperations {
* @return the output data extracted with the RecordExtractor object
* @throws DataAccessException if there is any problem
*/
@Nullable
protected <T> T doExecute(
final InteractionSpec spec, final Record inputRecord, @Nullable final Record outputRecord,
@Nullable final RecordExtractor<T> outputExtractor) throws DataAccessException {
return execute(new InteractionCallback<T>() {
@Override
public T doInInteraction(Interaction interaction, ConnectionFactory connectionFactory)
throws ResourceException, SQLException, DataAccessException {
Record outputRecordToUse = outputRecord;
try {
if (outputRecord != null || getOutputRecordCreator() != null) {
// Use the CCI execute method with output record as parameter.
if (outputRecord == null) {
RecordFactory recordFactory = getRecordFactory(connectionFactory);
outputRecordToUse = getOutputRecordCreator().createRecord(recordFactory);
}
interaction.execute(spec, inputRecord, outputRecordToUse);
return execute((InteractionCallback<T>) (interaction, connectionFactory) -> {
Record outputRecordToUse = outputRecord;
try {
if (outputRecord != null || getOutputRecordCreator() != null) {
// Use the CCI execute method with output record as parameter.
if (outputRecord == null) {
RecordFactory recordFactory = getRecordFactory(connectionFactory);
outputRecordToUse = getOutputRecordCreator().createRecord(recordFactory);
}
else {
outputRecordToUse = interaction.execute(spec, inputRecord);
}
return (outputExtractor != null ? outputExtractor.extractData(outputRecordToUse) : null);
interaction.execute(spec, inputRecord, outputRecordToUse);
}
finally {
if (outputRecordToUse instanceof ResultSet) {
closeResultSet((ResultSet) outputRecordToUse);
}
else {
outputRecordToUse = interaction.execute(spec, inputRecord);
}
return (outputExtractor != null ? outputExtractor.extractData(outputRecordToUse) : null);
}
finally {
if (outputRecordToUse instanceof ResultSet) {
closeResultSet((ResultSet) outputRecordToUse);
}
}
});
@@ -313,7 +319,7 @@ public class CciTemplate implements CciOperations {
*/
public IndexedRecord createIndexedRecord(String name) throws DataAccessException {
try {
RecordFactory recordFactory = getRecordFactory(getConnectionFactory());
RecordFactory recordFactory = getRecordFactory(obtainConnectionFactory());
return recordFactory.createIndexedRecord(name);
}
catch (NotSupportedException ex) {
@@ -334,7 +340,7 @@ public class CciTemplate implements CciOperations {
*/
public MappedRecord createMappedRecord(String name) throws DataAccessException {
try {
RecordFactory recordFactory = getRecordFactory(getConnectionFactory());
RecordFactory recordFactory = getRecordFactory(obtainConnectionFactory());
return recordFactory.createMappedRecord(name);
}
catch (NotSupportedException ex) {
@@ -356,7 +362,7 @@ public class CciTemplate implements CciOperations {
*/
protected Record createRecord(RecordCreator recordCreator) throws DataAccessException {
try {
RecordFactory recordFactory = getRecordFactory(getConnectionFactory());
RecordFactory recordFactory = getRecordFactory(obtainConnectionFactory());
return recordCreator.createRecord(recordFactory);
}
catch (NotSupportedException ex) {
@@ -395,7 +401,7 @@ public class CciTemplate implements CciOperations {
* @param interaction the CCI Interaction to close
* @see javax.resource.cci.Interaction#close()
*/
private void closeInteraction(Interaction interaction) {
private void closeInteraction(@Nullable Interaction interaction) {
if (interaction != null) {
try {
interaction.close();
@@ -416,7 +422,7 @@ public class CciTemplate implements CciOperations {
* @param resultSet the CCI ResultSet to close
* @see javax.resource.cci.ResultSet#close()
*/
private void closeResultSet(ResultSet resultSet) {
private void closeResultSet(@Nullable ResultSet resultSet) {
if (resultSet != null) {
try {
resultSet.close();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -24,6 +24,8 @@ import org.springframework.dao.support.DaoSupport;
import org.springframework.jca.cci.CannotGetCciConnectionException;
import org.springframework.jca.cci.connection.ConnectionFactoryUtils;
import org.springframework.jca.cci.core.CciTemplate;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Convenient super class for CCI-based data access objects.
@@ -73,6 +75,7 @@ public abstract class CciDaoSupport extends DaoSupport {
/**
* Return the ConnectionFactory used by this DAO.
*/
@Nullable
public final ConnectionFactory getConnectionFactory() {
return this.cciTemplate.getConnectionFactory();
}
@@ -122,7 +125,9 @@ public abstract class CciDaoSupport extends DaoSupport {
* @see org.springframework.jca.cci.connection.ConnectionFactoryUtils#getConnection(javax.resource.cci.ConnectionFactory)
*/
protected final Connection getConnection() throws CannotGetCciConnectionException {
return ConnectionFactoryUtils.getConnection(getConnectionFactory());
ConnectionFactory connectionFactory = getConnectionFactory();
Assert.state(connectionFactory != null, "No ConnectionFactory set");
return ConnectionFactoryUtils.getConnection(connectionFactory);
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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,7 @@ import javax.resource.cci.InteractionSpec;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jca.cci.core.CciTemplate;
import org.springframework.util.Assert;
/**
* Base class for EIS operation objects that work with the CCI API.
@@ -47,9 +48,7 @@ public abstract class EisOperation implements InitializingBean {
* @see #setConnectionFactory
*/
public void setCciTemplate(CciTemplate cciTemplate) {
if (cciTemplate == null) {
throw new IllegalArgumentException("cciTemplate must not be null");
}
Assert.notNull(cciTemplate, "CciTemplate must not be null");
this.cciTemplate = cciTemplate;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -26,6 +26,7 @@ import javax.resource.cci.RecordFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jca.cci.core.RecordCreator;
import org.springframework.jca.cci.core.RecordExtractor;
import org.springframework.lang.Nullable;
/**
* EIS operation object that expects mapped input and output objects,
@@ -85,6 +86,7 @@ public abstract class MappingRecordOperation extends EisOperation {
* @see #createInputRecord
* @see #extractOutputData
*/
@Nullable
public Object execute(Object inputObject) throws DataAccessException {
return getCciTemplate().execute(
getInteractionSpec(), new RecordCreatorImpl(inputObject), new RecordExtractorImpl());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -20,6 +20,7 @@ import javax.resource.spi.BootstrapContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;
/**
* {@link org.springframework.beans.factory.config.BeanPostProcessor}
@@ -41,7 +42,7 @@ class BootstrapContextAwareProcessor implements BeanPostProcessor {
/**
* Create a new BootstrapContextAwareProcessor for the given context.
*/
public BootstrapContextAwareProcessor(BootstrapContext bootstrapContext) {
public BootstrapContextAwareProcessor(@Nullable BootstrapContext bootstrapContext) {
this.bootstrapContext = bootstrapContext;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -177,15 +177,17 @@ public class SpringContextResourceAdapter implements ResourceAdapter {
protected ConfigurableApplicationContext createApplicationContext(BootstrapContext bootstrapContext) {
ResourceAdapterApplicationContext applicationContext =
new ResourceAdapterApplicationContext(bootstrapContext);
// Set ResourceAdapter's ClassLoader as bean class loader.
applicationContext.setClassLoader(getClass().getClassLoader());
// Extract individual config locations.
String[] configLocations =
StringUtils.tokenizeToStringArray(getContextConfigLocation(), CONFIG_LOCATION_DELIMITERS);
if (configLocations != null) {
loadBeanDefinitions(applicationContext, configLocations);
}
loadBeanDefinitions(applicationContext, configLocations);
applicationContext.refresh();
return applicationContext;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -311,7 +311,7 @@ public abstract class AbstractMessageEndpointFactory implements MessageEndpointF
private boolean rollbackOnly;
public TransactionDelegate(XAResource xaResource) {
public TransactionDelegate(@Nullable XAResource xaResource) {
if (xaResource == null) {
if (transactionFactory != null && !transactionFactory.supportsResourceAdapterManagedTransactions()) {
throw new IllegalStateException("ResourceAdapter-provided XAResource is required for " +

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -24,6 +24,8 @@ import javax.resource.spi.endpoint.MessageEndpointFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.SmartLifecycle;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Generic bean that manages JCA 1.7 message endpoints within a Spring
@@ -171,6 +173,7 @@ public class GenericMessageEndpointManager implements SmartLifecycle, Initializi
/**
* Return the JCA ResourceAdapter to manage endpoints for.
*/
@Nullable
public ResourceAdapter getResourceAdapter() {
return this.resourceAdapter;
}
@@ -190,6 +193,7 @@ public class GenericMessageEndpointManager implements SmartLifecycle, Initializi
/**
* Return the JCA MessageEndpointFactory to activate.
*/
@Nullable
public MessageEndpointFactory getMessageEndpointFactory() {
return this.messageEndpointFactory;
}
@@ -206,6 +210,7 @@ public class GenericMessageEndpointManager implements SmartLifecycle, Initializi
/**
* Return the JCA ActivationSpec to use for activating the endpoint.
*/
@Nullable
public ActivationSpec getActivationSpec() {
return this.activationSpec;
}
@@ -281,8 +286,10 @@ public class GenericMessageEndpointManager implements SmartLifecycle, Initializi
public void start() {
synchronized (this.lifecycleMonitor) {
if (!this.running) {
ResourceAdapter resourceAdapter = getResourceAdapter();
Assert.state(resourceAdapter != null, "No ResourceAdapter set");
try {
getResourceAdapter().endpointActivation(getMessageEndpointFactory(), getActivationSpec());
resourceAdapter.endpointActivation(getMessageEndpointFactory(), getActivationSpec());
}
catch (ResourceException ex) {
throw new IllegalStateException("Could not activate message endpoint", ex);
@@ -299,7 +306,9 @@ public class GenericMessageEndpointManager implements SmartLifecycle, Initializi
public void stop() {
synchronized (this.lifecycleMonitor) {
if (this.running) {
getResourceAdapter().endpointDeactivation(getMessageEndpointFactory(), getActivationSpec());
ResourceAdapter resourceAdapter = getResourceAdapter();
Assert.state(resourceAdapter != null, "No ResourceAdapter set");
resourceAdapter.endpointDeactivation(getMessageEndpointFactory(), getActivationSpec());
this.running = false;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -141,9 +141,8 @@ public class SimpleTaskWorkManager implements WorkManager {
* (or -1 if not applicable or not known)
* @throws WorkException if the TaskExecutor did not accept the Work
*/
protected long executeWork(TaskExecutor taskExecutor, Work work, long startTimeout,
boolean blockUntilStarted, ExecutionContext executionContext, WorkListener workListener)
throws WorkException {
protected long executeWork(TaskExecutor taskExecutor, Work work, long startTimeout, boolean blockUntilStarted,
@Nullable ExecutionContext executionContext, @Nullable WorkListener workListener) throws WorkException {
if (executionContext != null && executionContext.getXid() != null) {
throw new WorkException("SimpleTaskWorkManager does not supported imported XIDs: " + executionContext.getXid());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -86,7 +86,7 @@ public class TransactionSystemException extends TransactionException {
}
@Override
public boolean contains(Class<?> exType) {
public boolean contains(@Nullable Class<?> exType) {
return super.contains(exType) || (exType != null && exType.isInstance(this.applicationException));
}

View File

@@ -141,14 +141,14 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
* @see #getTransactionAttribute
*/
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// Ignore CGLIB subclasses - introspect the actual user class.
Class<?> userClass = ClassUtils.getUserClass(targetClass);
Class<?> userClass = (targetClass != null ? ClassUtils.getUserClass(targetClass) : null);
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-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.
@@ -54,7 +54,7 @@ public class MatchAlwaysTransactionAttributeSource implements TransactionAttribu
@Override
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
return (method == null || ClassUtils.isUserLevelMethod(method) ? this.transactionAttribute : null);
return (ClassUtils.isUserLevelMethod(method) ? this.transactionAttribute : null);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -59,8 +59,7 @@ public class MethodMapTransactionAttributeSource
private boolean initialized = false;
/** Map from Method to TransactionAttribute */
private final Map<Method, TransactionAttribute> transactionAttributeMap =
new HashMap<>();
private final Map<Method, TransactionAttribute> transactionAttributeMap = new HashMap<>();
/** Map from Method to name pattern used for registration */
private final Map<Method, String> methodNameMap = new HashMap<>();
@@ -83,7 +82,7 @@ public class MethodMapTransactionAttributeSource
}
@Override
public void setBeanClassLoader(@Nullable ClassLoader beanClassLoader) {
public void setBeanClassLoader(ClassLoader beanClassLoader) {
this.beanClassLoader = beanClassLoader;
}
@@ -105,7 +104,7 @@ public class MethodMapTransactionAttributeSource
* @param methodMap Map from method names to {@code TransactionAttribute} instances
* @see #setMethodMap
*/
protected void initMethodMap(Map<String, TransactionAttribute> methodMap) {
protected void initMethodMap(@Nullable Map<String, TransactionAttribute> methodMap) {
if (methodMap != null) {
for (Map.Entry<String, TransactionAttribute> entry : methodMap.entrySet()) {
addTransactionalMethod(entry.getKey(), entry.getValue());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -35,6 +35,7 @@ import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.StringUtils;
@@ -200,7 +201,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* @see NameMatchTransactionAttributeSource
* @see org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
*/
public void setTransactionAttributeSources(TransactionAttributeSource[] transactionAttributeSources) {
public void setTransactionAttributeSources(TransactionAttributeSource... transactionAttributeSources) {
this.transactionAttributeSource = new CompositeTransactionAttributeSource(transactionAttributeSources);
}
@@ -220,6 +221,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
/**
* Return the transaction attribute source.
*/
@Nullable
public TransactionAttributeSource getTransactionAttributeSource() {
return this.transactionAttributeSource;
}
@@ -268,11 +270,12 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* @throws Throwable propagated from the target invocation
*/
@Nullable
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable {
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
@@ -354,11 +357,13 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
/**
* Determine the specific transaction manager to use for the given transaction.
*/
protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) {
@Nullable
protected PlatformTransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
// Do not attempt to lookup tx manager if no tx attributes are set
if (txAttr == null || this.beanFactory == null) {
return getTransactionManager();
}
String qualifier = txAttr.getQualifier();
if (StringUtils.hasText(qualifier)) {
return determineQualifiedTransactionManager(qualifier);
@@ -390,7 +395,9 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
return txManager;
}
private String methodIdentification(Method method, Class<?> targetClass, TransactionAttribute txAttr) {
private String methodIdentification(Method method, @Nullable Class<?> targetClass,
@Nullable TransactionAttribute txAttr) {
String methodIdentification = methodIdentification(method, targetClass);
if (methodIdentification == null) {
if (txAttr instanceof DefaultTransactionAttribute) {
@@ -416,7 +423,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* @see org.springframework.util.ClassUtils#getQualifiedMethodName
*/
@Nullable
protected String methodIdentification(Method method, Class<?> targetClass) {
protected String methodIdentification(Method method, @Nullable Class<?> targetClass) {
return null;
}
@@ -433,8 +440,8 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* @see #getTransactionAttributeSource()
*/
@SuppressWarnings("serial")
protected TransactionInfo createTransactionIfNecessary(
PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// If no name specified, apply method identification as transaction name.
if (txAttr != null && txAttr.getName() == null) {
@@ -469,8 +476,9 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* @param status the TransactionStatus for the current transaction
* @return the prepared TransactionInfo object
*/
protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, String joinpointIdentification,
@Nullable TransactionStatus status) {
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
if (txAttr != null) {
@@ -501,7 +509,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* Do nothing if we didn't create a transaction.
* @param txInfo information about the current transaction
*/
protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.hasTransaction()) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
@@ -516,13 +524,13 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* @param txInfo information about the current transaction
* @param ex throwable encountered
*/
protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.hasTransaction()) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
"] after exception: " + ex);
}
if (txInfo.transactionAttribute.rollbackOn(ex)) {
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
try {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
@@ -591,8 +599,8 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
private TransactionInfo oldTransactionInfo;
public TransactionInfo(PlatformTransactionManager transactionManager,
TransactionAttribute transactionAttribute, String joinpointIdentification) {
public TransactionInfo(@Nullable PlatformTransactionManager transactionManager,
@Nullable TransactionAttribute transactionAttribute, String joinpointIdentification) {
this.transactionManager = transactionManager;
this.transactionAttribute = transactionAttribute;
@@ -600,9 +608,11 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
}
public PlatformTransactionManager getTransactionManager() {
Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
return this.transactionManager;
}
@Nullable
public TransactionAttribute getTransactionAttribute() {
return this.transactionAttribute;
}
@@ -615,7 +625,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
return this.joinpointIdentification;
}
public void newTransactionStatus(TransactionStatus status) {
public void newTransactionStatus(@Nullable TransactionStatus status) {
this.transactionStatus = status;
}
@@ -646,7 +656,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
@Override
public String toString() {
return this.transactionAttribute.toString();
return (this.transactionAttribute != null ? this.transactionAttribute.toString() : "No transaction");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -38,8 +38,8 @@ public interface TransactionAttributeSource {
* Return the transaction attribute for the given method,
* or {@code null} if the method is non-transactional.
* @param method the method to introspect
* @param targetClass the target class. May be {@code null},
* in which case the declaring class of the method must be used.
* @param targetClass the target class (may be {@code null},
* in which case the declaring class of the method must be used)
* @return TransactionAttribute the matching transaction attribute,
* or {@code null} if none found
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-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.
@@ -35,7 +35,7 @@ abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPoi
@Override
public boolean matches(Method method, @Nullable Class<?> targetClass) {
if (TransactionalProxy.class.isAssignableFrom(targetClass)) {
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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,7 +21,6 @@ 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;
@@ -251,6 +250,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
/**
* Return the JNDI environment to use for JNDI lookups.
*/
@Nullable
public Properties getJndiEnvironment() {
return this.jndiTemplate.getEnvironment();
}
@@ -270,6 +270,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
/**
* Return the JTA UserTransaction that this transaction manager uses.
*/
@Nullable
public UserTransaction getUserTransaction() {
return this.userTransaction;
}
@@ -958,7 +959,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
}
@Override
protected void doResume(Object transaction, Object suspendedResources) {
protected void doResume(@Nullable Object transaction, Object suspendedResources) {
JtaTransactionObject txObject = (JtaTransactionObject) transaction;
try {
doJtaResume(txObject, suspendedResources);
@@ -984,7 +985,7 @@ public class JtaTransactionManager extends AbstractPlatformTransactionManager
* @see #getTransactionManager()
* @see javax.transaction.TransactionManager#resume(javax.transaction.Transaction)
*/
protected void doJtaResume(JtaTransactionObject txObject, Object suspendedTransaction)
protected void doJtaResume(@Nullable JtaTransactionObject txObject, Object suspendedTransaction)
throws InvalidTransactionException, SystemException {
if (getTransactionManager() == null) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -64,9 +64,6 @@ public class JtaTransactionObject implements SmartTransactionObject {
*/
@Override
public boolean isRollbackOnly() {
if (this.userTransaction == null) {
return false;
}
try {
int jtaStatus = this.userTransaction.getStatus();
return (jtaStatus == Status.STATUS_MARKED_ROLLBACK || jtaStatus == Status.STATUS_ROLLEDBACK);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -24,6 +24,7 @@ import javax.transaction.UserTransaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.lang.Nullable;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
@@ -76,8 +77,8 @@ public class SpringJtaSynchronizationAdapter implements Synchronization {
* (can be omitted if the JTA provider itself marks the transaction rollback-only
* in such a scenario, which is required by the JTA specification as of JTA 1.1).
*/
public SpringJtaSynchronizationAdapter(
TransactionSynchronization springSynchronization, UserTransaction jtaUserTransaction) {
public SpringJtaSynchronizationAdapter(TransactionSynchronization springSynchronization,
@Nullable UserTransaction jtaUserTransaction) {
this(springSynchronization);
if (jtaUserTransaction != null && !jtaUserTransaction.getClass().getName().startsWith("weblogic.")) {
@@ -99,7 +100,7 @@ public class SpringJtaSynchronizationAdapter implements Synchronization {
* in such a scenario, which is required by the JTA specification as of JTA 1.1)
*/
public SpringJtaSynchronizationAdapter(
TransactionSynchronization springSynchronization, TransactionManager jtaTransactionManager) {
TransactionSynchronization springSynchronization, @Nullable TransactionManager jtaTransactionManager) {
this(springSynchronization);
if (jtaTransactionManager != null && !jtaTransactionManager.getClass().getName().startsWith("weblogic.")) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-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.
@@ -29,6 +29,7 @@ import javax.transaction.UserTransaction;
import org.springframework.lang.Nullable;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.util.Assert;
/**
* Special {@link JtaTransactionManager} variant for BEA WebLogic (9.0 and higher).
@@ -198,6 +199,12 @@ public class WebLogicJtaTransactionManager extends JtaTransactionManager {
}
}
private TransactionManager obtainTransactionManager() {
TransactionManager tm = getTransactionManager();
Assert.state(tm != null, "No TransactionManager set");
return tm;
}
@Override
protected void doJtaBegin(JtaTransactionObject txObject, TransactionDefinition definition)
@@ -243,7 +250,7 @@ public class WebLogicJtaTransactionManager extends JtaTransactionManager {
if (this.weblogicTransactionManagerAvailable) {
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
try {
Transaction tx = getTransactionManager().getTransaction();
Transaction tx = obtainTransactionManager().getTransaction();
Integer isolationLevel = definition.getIsolationLevel();
/*
weblogic.transaction.Transaction wtx = (weblogic.transaction.Transaction) tx;
@@ -271,7 +278,7 @@ public class WebLogicJtaTransactionManager extends JtaTransactionManager {
throws InvalidTransactionException, SystemException {
try {
getTransactionManager().resume((Transaction) suspendedTransaction);
obtainTransactionManager().resume((Transaction) suspendedTransaction);
}
catch (InvalidTransactionException ex) {
if (!this.weblogicTransactionManagerAvailable) {
@@ -330,7 +337,7 @@ public class WebLogicJtaTransactionManager extends JtaTransactionManager {
catch (Exception ex) {
throw new SystemException("Could not invoke WebLogic's UserTransaction.begin() method: " + ex);
}
return new ManagedTransactionAdapter(getTransactionManager());
return new ManagedTransactionAdapter(obtainTransactionManager());
}
else {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -26,6 +26,7 @@ import com.ibm.wsspi.uow.UOWException;
import com.ibm.wsspi.uow.UOWManager;
import com.ibm.wsspi.uow.UOWManagerFactory;
import org.springframework.lang.Nullable;
import org.springframework.transaction.IllegalTransactionStateException;
import org.springframework.transaction.InvalidTimeoutException;
import org.springframework.transaction.NestedTransactionNotSupportedException;
@@ -219,7 +220,9 @@ public class WebSphereUowTransactionManager extends JtaTransactionManager
@Override
public <T> T execute(TransactionDefinition definition, TransactionCallback<T> callback) throws TransactionException {
public <T> T execute(@Nullable TransactionDefinition definition, TransactionCallback<T> callback)
throws TransactionException {
if (definition == null) {
// Use defaults if no transaction definition given.
definition = new DefaultTransactionDefinition();

View File

@@ -511,7 +511,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
* Create a TransactionStatus instance for the given arguments.
*/
protected DefaultTransactionStatus newTransactionStatus(
TransactionDefinition definition, Object transaction, boolean newTransaction,
TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
boolean actualNewSynchronization = newSynchronization &&
@@ -633,7 +633,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
* Resume outer transaction after inner transaction begin failed.
*/
private void resumeAfterBeginException(
Object transaction, SuspendedResourcesHolder suspendedResources, Throwable beginEx) {
Object transaction, @Nullable SuspendedResourcesHolder suspendedResources, Throwable beginEx) {
String exMessage = "Inner transaction begin exception overridden by outer transaction resume exception";
try {
@@ -1006,7 +1006,8 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
if (status.isDebug()) {
logger.debug("Resuming suspended transaction after completion of inner transaction");
}
resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources());
Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
}
}
@@ -1129,7 +1130,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
* @throws TransactionException in case of system errors
* @see #doSuspend
*/
protected void doResume(Object transaction, Object suspendedResources) throws TransactionException {
protected void doResume(@Nullable Object transaction, Object suspendedResources) throws TransactionException {
throw new TransactionSuspensionNotSupportedException(
"Transaction manager [" + getClass().getName() + "] does not support transaction suspension");
}
@@ -1287,8 +1288,9 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
}
private SuspendedResourcesHolder(
Object suspendedResources, List<TransactionSynchronization> suspendedSynchronizations,
String name, boolean readOnly, Integer isolationLevel, boolean wasActive) {
@Nullable Object suspendedResources, List<TransactionSynchronization> suspendedSynchronizations,
@Nullable String name, boolean readOnly, @Nullable Integer isolationLevel, boolean wasActive) {
this.suspendedResources = suspendedResources;
this.suspendedSynchronizations = suspendedSynchronizations;
this.name = name;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-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.
@@ -151,12 +151,13 @@ public abstract class AbstractTransactionStatus implements TransactionStatus {
* and release the savepoint right afterwards.
*/
public void rollbackToHeldSavepoint() throws TransactionException {
if (!hasSavepoint()) {
Object savepoint = getSavepoint();
if (savepoint == null) {
throw new TransactionUsageException(
"Cannot roll back to savepoint - no savepoint associated with current transaction");
}
getSavepointManager().rollbackToSavepoint(getSavepoint());
getSavepointManager().releaseSavepoint(getSavepoint());
getSavepointManager().rollbackToSavepoint(savepoint);
getSavepointManager().releaseSavepoint(savepoint);
setSavepoint(null);
}
@@ -164,11 +165,12 @@ public abstract class AbstractTransactionStatus implements TransactionStatus {
* Release the savepoint that is held for the transaction.
*/
public void releaseHeldSavepoint() throws TransactionException {
if (!hasSavepoint()) {
Object savepoint = getSavepoint();
if (savepoint == null) {
throw new TransactionUsageException(
"Cannot release savepoint - no savepoint associated with current transaction");
}
getSavepointManager().releaseSavepoint(getSavepoint());
getSavepointManager().releaseSavepoint(savepoint);
setSavepoint(null);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -55,7 +55,7 @@ public interface CallbackPreferringPlatformTransactionManager extends PlatformTr
* @throws RuntimeException if thrown by the TransactionCallback
*/
@Nullable
<T> T execute(TransactionDefinition definition, TransactionCallback<T> callback)
<T> T execute(@Nullable TransactionDefinition definition, TransactionCallback<T> callback)
throws TransactionException;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -114,7 +114,7 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri
* @see #PROPAGATION_REQUIRED
*/
public final void setPropagationBehaviorName(String constantName) throws IllegalArgumentException {
if (constantName == null || !constantName.startsWith(PREFIX_PROPAGATION)) {
if (!constantName.startsWith(PREFIX_PROPAGATION)) {
throw new IllegalArgumentException("Only propagation constants allowed");
}
setPropagationBehavior(constants.asNumber(constantName).intValue());
@@ -149,7 +149,7 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri
* @see #ISOLATION_DEFAULT
*/
public final void setIsolationLevelName(String constantName) throws IllegalArgumentException {
if (constantName == null || !constantName.startsWith(PREFIX_ISOLATION)) {
if (!constantName.startsWith(PREFIX_ISOLATION)) {
throw new IllegalArgumentException("Only isolation constants allowed");
}
setIsolationLevel(constants.asNumber(constantName).intValue());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -19,6 +19,7 @@ package org.springframework.transaction.support;
import org.springframework.lang.Nullable;
import org.springframework.transaction.NestedTransactionNotSupportedException;
import org.springframework.transaction.SavepointManager;
import org.springframework.util.Assert;
/**
* Default implementation of the {@link org.springframework.transaction.TransactionStatus}
@@ -78,7 +79,7 @@ public class DefaultTransactionStatus extends AbstractTransactionStatus {
* for this transaction, if any
*/
public DefaultTransactionStatus(
Object transaction, boolean newTransaction, boolean newSynchronization,
@Nullable Object transaction, boolean newTransaction, boolean newSynchronization,
boolean readOnly, boolean debug, @Nullable Object suspendedResources) {
this.transaction = transaction;
@@ -92,8 +93,10 @@ public class DefaultTransactionStatus extends AbstractTransactionStatus {
/**
* Return the underlying transaction object.
* @throws IllegalStateException if no transaction is active
*/
public Object getTransaction() {
Assert.state(this.transaction != null, "No transaction active");
return this.transaction;
}
@@ -177,11 +180,12 @@ public class DefaultTransactionStatus extends AbstractTransactionStatus {
*/
@Override
protected SavepointManager getSavepointManager() {
if (!isTransactionSavepointManager()) {
Object transaction = this.transaction;
if (!(transaction instanceof SavepointManager)) {
throw new NestedTransactionNotSupportedException(
"Transaction object [" + getTransaction() + "] does not support savepoints");
"Transaction object [" + this.transaction + "] does not support savepoints");
}
return (SavepointManager) getTransaction();
return (SavepointManager) transaction;
}
/**
@@ -191,7 +195,7 @@ public class DefaultTransactionStatus extends AbstractTransactionStatus {
* @see org.springframework.transaction.SavepointManager
*/
public boolean isTransactionSavepointManager() {
return (getTransaction() instanceof SavepointManager);
return (this.transaction instanceof SavepointManager);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-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.
@@ -22,6 +22,7 @@ import java.util.Map;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.util.Assert;
/**
* A simple transaction-backed {@link Scope} implementation, delegating to
@@ -52,6 +53,7 @@ public class SimpleTransactionScope implements Scope {
Object scopedObject = scopedObjects.scopedInstances.get(name);
if (scopedObject == null) {
scopedObject = objectFactory.getObject();
Assert.state(scopedObject != null, "Scoped object resolved to null");
scopedObjects.scopedInstances.put(name, scopedObject);
}
return scopedObject;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-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.
@@ -23,6 +23,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.aop.scope.ScopedObject;
import org.springframework.core.InfrastructureProxy;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -127,7 +128,7 @@ public abstract class TransactionSynchronizationUtils {
* @param synchronizations List of TransactionSynchronization objects
* @see TransactionSynchronization#afterCommit()
*/
public static void invokeAfterCommit(List<TransactionSynchronization> synchronizations) {
public static void invokeAfterCommit(@Nullable List<TransactionSynchronization> synchronizations) {
if (synchronizations != null) {
for (TransactionSynchronization synchronization : synchronizations) {
synchronization.afterCommit();
@@ -161,7 +162,9 @@ public abstract class TransactionSynchronizationUtils {
* @see TransactionSynchronization#STATUS_ROLLED_BACK
* @see TransactionSynchronization#STATUS_UNKNOWN
*/
public static void invokeAfterCompletion(List<TransactionSynchronization> synchronizations, int completionStatus) {
public static void invokeAfterCompletion(@Nullable List<TransactionSynchronization> synchronizations,
int completionStatus) {
if (synchronizations != null) {
for (TransactionSynchronization synchronization : synchronizations) {
try {