Browse Source

Polishing

pull/30915/head
Juergen Hoeller 2 years ago
parent
commit
384246c360
  1. 36
      spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java
  2. 9
      spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java
  3. 25
      spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.java
  4. 36
      spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcTransactionManager.java
  5. 27
      spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java
  6. 6
      spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslator.java
  7. 19
      spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLStateSQLExceptionTranslator.java

36
spring-context/src/test/java/org/springframework/jmx/export/MBeanExporterTests.java

@ -354,7 +354,7 @@ public class MBeanExporterTests extends AbstractMBeanServerTests { @@ -354,7 +354,7 @@ public class MBeanExporterTests extends AbstractMBeanServerTests {
exporter.setBeans(beansToExport);
exporter.setServer(getServer());
exporter.setBeanFactory(factory);
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_NONE);
exporter.setAutodetect(false);
// MBean has a bad ObjectName, so if said MBean is autodetected, an exception will be thrown...
start(exporter);
}
@ -524,18 +524,16 @@ public class MBeanExporterTests extends AbstractMBeanServerTests { @@ -524,18 +524,16 @@ public class MBeanExporterTests extends AbstractMBeanServerTests {
}
@Test
void notRunningInBeanFactoryAndPassedBeanNameToExport() throws Exception {
void notRunningInBeanFactoryAndPassedBeanNameToExport() {
Map<String, Object> beans = Map.of(OBJECT_NAME, "beanName");
exporter.setBeans(beans);
assertThatExceptionOfType(MBeanExportException.class)
.isThrownBy(() -> start(exporter));
assertThatExceptionOfType(MBeanExportException.class).isThrownBy(() -> start(exporter));
}
@Test
void notRunningInBeanFactoryAndAutodetectionIsOn() throws Exception {
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL);
assertThatExceptionOfType(MBeanExportException.class)
.isThrownBy(() -> start(exporter));
void notRunningInBeanFactoryAndAutodetectionIsOn() {
exporter.setAutodetect(true);
assertThatExceptionOfType(MBeanExportException.class).isThrownBy(() -> start(exporter));
}
@Test // SPR-2158
@ -556,7 +554,7 @@ public class MBeanExporterTests extends AbstractMBeanServerTests { @@ -556,7 +554,7 @@ public class MBeanExporterTests extends AbstractMBeanServerTests {
}
@Test // SPR-3302
void beanNameCanBeUsedInNotificationListenersMap() throws Exception {
void beanNameCanBeUsedInNotificationListenersMap() {
String beanName = "charlesDexterWard";
BeanDefinitionBuilder testBean = BeanDefinitionBuilder.rootBeanDefinition(JmxTestBean.class);
@ -576,7 +574,7 @@ public class MBeanExporterTests extends AbstractMBeanServerTests { @@ -576,7 +574,7 @@ public class MBeanExporterTests extends AbstractMBeanServerTests {
}
@Test
void wildcardCanBeUsedInNotificationListenersMap() throws Exception {
void wildcardCanBeUsedInNotificationListenersMap() {
String beanName = "charlesDexterWard";
BeanDefinitionBuilder testBean = BeanDefinitionBuilder.rootBeanDefinition(JmxTestBean.class);
@ -636,24 +634,23 @@ public class MBeanExporterTests extends AbstractMBeanServerTests { @@ -636,24 +634,23 @@ public class MBeanExporterTests extends AbstractMBeanServerTests {
exporter.setServer(getServer());
exporter.setAssembler(new NamedBeanAutodetectCapableMBeanInfoAssemblerStub(firstBeanName, secondBeanName));
exporter.setBeanFactory(factory);
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL);
exporter.setAutodetect(true);
exporter.addExcludedBean(secondBeanName);
start(exporter);
assertIsRegistered("Bean not autodetected in (AUTODETECT_ALL) mode",
ObjectNameManager.getInstance(firstBeanName));
assertIsNotRegistered("Bean should have been excluded",
ObjectNameManager.getInstance(secondBeanName));
assertIsRegistered("Bean not autodetected", ObjectNameManager.getInstance(firstBeanName));
assertIsNotRegistered("Bean should have been excluded", ObjectNameManager.getInstance(secondBeanName));
}
@Test
void registerFactoryBean() throws MalformedObjectNameException {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerBeanDefinition("spring:type=FactoryBean", new RootBeanDefinition(ProperSomethingFactoryBean.class));
factory.registerBeanDefinition("spring:type=FactoryBean",
new RootBeanDefinition(ProperSomethingFactoryBean.class));
exporter.setServer(getServer());
exporter.setBeanFactory(factory);
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL);
exporter.setAutodetect(true);
start(exporter);
assertIsRegistered("Non-null FactoryBean object registered",
@ -663,11 +660,12 @@ public class MBeanExporterTests extends AbstractMBeanServerTests { @@ -663,11 +660,12 @@ public class MBeanExporterTests extends AbstractMBeanServerTests {
@Test
void ignoreNullObjectFromFactoryBean() throws MalformedObjectNameException {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerBeanDefinition("spring:type=FactoryBean", new RootBeanDefinition(NullSomethingFactoryBean.class));
factory.registerBeanDefinition("spring:type=FactoryBean",
new RootBeanDefinition(NullSomethingFactoryBean.class));
exporter.setServer(getServer());
exporter.setBeanFactory(factory);
exporter.setAutodetectMode(MBeanExporter.AUTODETECT_ALL);
exporter.setAutodetect(true);
start(exporter);
assertIsNotRegistered("Null FactoryBean object not registered",

9
spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2023 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.
@ -31,6 +31,8 @@ import org.springframework.util.Assert; @@ -31,6 +31,8 @@ import org.springframework.util.Assert;
*
* @author Juergen Hoeller
* @since 2.5.6
* @see #doTranslate
* @see #setFallbackTranslator
*/
public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExceptionTranslator {
@ -42,8 +44,8 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep @@ -42,8 +44,8 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
/**
* Override the default SQL state fallback translator
* (typically a {@link SQLStateSQLExceptionTranslator}).
* Set the fallback translator to use when this translator cannot find a
* specific match itself.
*/
public void setFallbackTranslator(@Nullable SQLExceptionTranslator fallback) {
this.fallbackTranslator = fallback;
@ -51,6 +53,7 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep @@ -51,6 +53,7 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
/**
* Return the fallback exception translator, if any.
* @see #setFallbackTranslator
*/
@Nullable
public SQLExceptionTranslator getFallbackTranslator() {

25
spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcAccessor.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2023 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.
@ -80,10 +80,11 @@ public abstract class JdbcAccessor implements InitializingBean { @@ -80,10 +80,11 @@ public abstract class JdbcAccessor implements InitializingBean {
}
/**
* Specify the database product name for the DataSource that this accessor uses.
* This allows to initialize an SQLErrorCodeSQLExceptionTranslator without
* obtaining a Connection from the DataSource to get the meta-data.
* Specify the database product name for the {@code DataSource} that this accessor uses.
* This allows for initializing a {@link SQLErrorCodeSQLExceptionTranslator} without
* obtaining a {@code Connection} from the {@code DataSource} to get the meta-data.
* @param dbName the database product name that identifies the error codes entry
* @see #setExceptionTranslator
* @see SQLErrorCodeSQLExceptionTranslator#setDatabaseProductName
* @see java.sql.DatabaseMetaData#getDatabaseProductName()
*/
@ -98,22 +99,20 @@ public abstract class JdbcAccessor implements InitializingBean { @@ -98,22 +99,20 @@ public abstract class JdbcAccessor implements InitializingBean {
/**
* Set the exception translator for this instance.
* <p>If no custom translator is provided, a default
* {@link SQLErrorCodeSQLExceptionTranslator} is used
* which examines the SQLException's vendor-specific error code.
* <p>A {@link SQLErrorCodeSQLExceptionTranslator} used by default if a user-provided
* `sql-error-codes.xml` file has been found in the root of the classpath. Otherwise,
* {@link SQLExceptionSubclassTranslator} serves as the default translator as of 6.0.
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
* @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
* @see org.springframework.jdbc.support.SQLExceptionSubclassTranslator
*/
public void setExceptionTranslator(SQLExceptionTranslator exceptionTranslator) {
this.exceptionTranslator = exceptionTranslator;
}
/**
* Return the exception translator for this instance.
* <p>Creates a default {@link SQLErrorCodeSQLExceptionTranslator}
* for the specified DataSource if none set, or a
* {@link SQLStateSQLExceptionTranslator} in case of no DataSource.
* @see #getDataSource()
* Return the exception translator to use for this instance,
* creating a default if necessary.
* @see #setExceptionTranslator
*/
public SQLExceptionTranslator getExceptionTranslator() {
SQLExceptionTranslator exceptionTranslator = this.exceptionTranslator;

36
spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcTransactionManager.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 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,8 @@ public class JdbcTransactionManager extends DataSourceTransactionManager { @@ -59,8 +59,8 @@ public class JdbcTransactionManager extends DataSourceTransactionManager {
/**
* Create a new JdbcTransactionManager instance.
* A DataSource has to be set to be able to use it.
* Create a new {@code JdbcTransactionManager} instance.
* A {@code DataSource} has to be set to be able to use it.
* @see #setDataSource
*/
public JdbcTransactionManager() {
@ -68,7 +68,7 @@ public class JdbcTransactionManager extends DataSourceTransactionManager { @@ -68,7 +68,7 @@ public class JdbcTransactionManager extends DataSourceTransactionManager {
}
/**
* Create a new JdbcTransactionManager instance.
* Create a new {@code JdbcTransactionManager} instance.
* @param dataSource the JDBC DataSource to manage transactions for
*/
public JdbcTransactionManager(DataSource dataSource) {
@ -79,13 +79,15 @@ public class JdbcTransactionManager extends DataSourceTransactionManager { @@ -79,13 +79,15 @@ public class JdbcTransactionManager extends DataSourceTransactionManager {
/**
* Specify the database product name for the DataSource that this transaction manager
* uses. This allows to initialize an SQLErrorCodeSQLExceptionTranslator without
* obtaining a Connection from the DataSource to get the meta-data.
* Specify the database product name for the {@code DataSource} that this
* transaction manager operates on.
* This allows for initializing a {@link SQLErrorCodeSQLExceptionTranslator} without
* obtaining a {@code Connection} from the {@code DataSource} to get the meta-data.
* @param dbName the database product name that identifies the error codes entry
* @see JdbcAccessor#setDatabaseProductName
* @see #setExceptionTranslator
* @see SQLErrorCodeSQLExceptionTranslator#setDatabaseProductName
* @see java.sql.DatabaseMetaData#getDatabaseProductName()
* @see JdbcAccessor#setDatabaseProductName
*/
public void setDatabaseProductName(String dbName) {
if (SQLErrorCodeSQLExceptionTranslator.hasUserProvidedErrorCodesFile()) {
@ -97,22 +99,22 @@ public class JdbcTransactionManager extends DataSourceTransactionManager { @@ -97,22 +99,22 @@ public class JdbcTransactionManager extends DataSourceTransactionManager {
}
/**
* Set the exception translator for this instance.
* <p>If no custom translator is provided, a default
* {@link SQLErrorCodeSQLExceptionTranslator} is used
* which examines the SQLException's vendor-specific error code.
* @see JdbcAccessor#setExceptionTranslator
* Set the exception translator for this transaction manager.
* <p>A {@link SQLErrorCodeSQLExceptionTranslator} used by default if a user-provided
* `sql-error-codes.xml` file has been found in the root of the classpath. Otherwise,
* {@link SQLExceptionSubclassTranslator} serves as the default translator as of 6.0.
* @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
* @see org.springframework.jdbc.support.SQLExceptionSubclassTranslator
* @see JdbcAccessor#setExceptionTranslator
*/
public void setExceptionTranslator(SQLExceptionTranslator exceptionTranslator) {
this.exceptionTranslator = exceptionTranslator;
}
/**
* Return the exception translator for this instance.
* <p>Creates a default {@link SQLErrorCodeSQLExceptionTranslator}
* for the specified DataSource if none set.
* @see #getDataSource()
* Return the exception translator to use for this instance,
* creating a default if necessary.
* @see #setExceptionTranslator
*/
public SQLExceptionTranslator getExceptionTranslator() {
SQLExceptionTranslator exceptionTranslator = this.exceptionTranslator;

27
spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodeSQLExceptionTranslator.java

@ -60,6 +60,11 @@ import org.springframework.util.function.SupplierUtils; @@ -60,6 +60,11 @@ import org.springframework.util.function.SupplierUtils;
* of the class path (e.g. in the "/WEB-INF/classes" directory), as long as the
* Spring JDBC package is loaded from the same ClassLoader.
*
* <p>This translator is commonly used by default if a user-provided `sql-error-codes.xml`
* file has been found in the root of the classpath, as a signal to use this strategy.
* Otherwise, {@link SQLExceptionSubclassTranslator} serves as the default translator
* as of 6.0.
*
* @author Rod Johnson
* @author Thomas Risberg
* @author Juergen Hoeller
@ -75,11 +80,10 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep @@ -75,11 +80,10 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
private static final int MESSAGE_SQL_THROWABLE_CONSTRUCTOR = 4;
private static final int MESSAGE_SQL_SQLEX_CONSTRUCTOR = 5;
private static final boolean USER_PROVIDED_ERROR_CODES_FILE_PRESENT =
new ClassPathResource(SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH, SQLErrorCodesFactory.class.getClassLoader()).exists();
private static final boolean userProvidedErrorCodesFilePresent =
new ClassPathResource(SQLErrorCodesFactory.SQL_ERROR_CODE_OVERRIDE_PATH,
SQLErrorCodesFactory.class.getClassLoader()).exists();
/** Error codes used by this translator. */
@Nullable
private SingletonSupplier<SQLErrorCodes> sqlErrorCodes;
@ -198,9 +202,9 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep @@ -198,9 +202,9 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
if (sqlErrorCodes != null) {
SQLExceptionTranslator customTranslator = sqlErrorCodes.getCustomSqlExceptionTranslator();
if (customTranslator != null) {
DataAccessException customDex = customTranslator.translate(task, sql, sqlEx);
if (customDex != null) {
return customDex;
dae = customTranslator.translate(task, sql, sqlEx);
if (dae != null) {
return dae;
}
}
}
@ -228,11 +232,10 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep @@ -228,11 +232,10 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
for (CustomSQLErrorCodesTranslation customTranslation : customTranslations) {
if (Arrays.binarySearch(customTranslation.getErrorCodes(), errorCode) >= 0 &&
customTranslation.getExceptionClass() != null) {
DataAccessException customException = createCustomException(
task, sql, sqlEx, customTranslation.getExceptionClass());
if (customException != null) {
dae = createCustomException(task, sql, sqlEx, customTranslation.getExceptionClass());
if (dae != null) {
logTranslation(task, sql, sqlEx, true);
return customException;
return dae;
}
}
}
@ -426,7 +429,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep @@ -426,7 +429,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
* in the root of the classpath.
*/
static boolean hasUserProvidedErrorCodesFile() {
return USER_PROVIDED_ERROR_CODES_FILE_PRESENT;
return userProvidedErrorCodesFilePresent;
}
}

6
spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLExceptionSubclassTranslator.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 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.
@ -51,6 +51,8 @@ import org.springframework.lang.Nullable; @@ -51,6 +51,8 @@ import org.springframework.lang.Nullable;
* <p>Falls back to a standard {@link SQLStateSQLExceptionTranslator} if the JDBC
* driver does not actually expose JDBC 4 compliant {@code SQLException} subclasses.
*
* <p>This translator serves as the default translator as of 6.0.
*
* @author Thomas Risberg
* @author Juergen Hoeller
* @since 2.5
@ -72,7 +74,7 @@ public class SQLExceptionSubclassTranslator extends AbstractFallbackSQLException @@ -72,7 +74,7 @@ public class SQLExceptionSubclassTranslator extends AbstractFallbackSQLException
return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex);
}
if (ex instanceof SQLTransactionRollbackException) {
if ("40001".equals(ex.getSQLState())) {
if (SQLStateSQLExceptionTranslator.indicatesCannotAcquireLock(ex.getSQLState())) {
return new CannotAcquireLockException(buildMessage(task, sql, ex), ex);
}
return new PessimisticLockingFailureException(buildMessage(task, sql, ex), ex);

19
spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLStateSQLExceptionTranslator.java

@ -39,11 +39,16 @@ import org.springframework.lang.Nullable; @@ -39,11 +39,16 @@ import org.springframework.lang.Nullable;
* does not require special initialization (no database vendor detection, etc.).
* For more precise translation, consider {@link SQLErrorCodeSQLExceptionTranslator}.
*
* <p>This translator is commonly used as a {@link #setFallbackTranslator fallback}
* behind a primary translator such as {@link SQLErrorCodeSQLExceptionTranslator} or
* {@link SQLExceptionSubclassTranslator}.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Thomas Risberg
* @see java.sql.SQLException#getSQLState()
* @see SQLErrorCodeSQLExceptionTranslator
* @see SQLExceptionSubclassTranslator
*/
public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLExceptionTranslator {
@ -111,7 +116,7 @@ public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLException @@ -111,7 +116,7 @@ public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLException
return new TransientDataAccessResourceException(buildMessage(task, sql, ex), ex);
}
else if (PESSIMISTIC_LOCKING_FAILURE_CODES.contains(classCode)) {
if ("40001".equals(sqlState)) {
if (indicatesCannotAcquireLock(sqlState)) {
return new CannotAcquireLockException(buildMessage(task, sql, ex), ex);
}
return new PessimisticLockingFailureException(buildMessage(task, sql, ex), ex);
@ -148,9 +153,10 @@ public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLException @@ -148,9 +153,10 @@ public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLException
return sqlState;
}
/**
* Check whether the given SQL state (and the associated error code in case
* of a generic SQL state value) indicate a duplicate key exception:
* of a generic SQL state value) indicate a {@link DuplicateKeyException}:
* either SQL state 23505 as a specific indication, or the generic SQL state
* 23000 with well-known vendor codes (1 for Oracle, 1062 for MySQL/MariaDB,
* 2601/2627 for MS SQL Server).
@ -163,4 +169,13 @@ public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLException @@ -163,4 +169,13 @@ public class SQLStateSQLExceptionTranslator extends AbstractFallbackSQLException
(errorCode == 1 || errorCode == 1062 || errorCode == 2601 || errorCode == 2627)));
}
/**
* Check whether the given SQL state indicates a {@link CannotAcquireLockException},
* with SQL state 40001 as a specific indication.
* @param sqlState the SQL state value
*/
static boolean indicatesCannotAcquireLock(@Nullable String sqlState) {
return "40001".equals(sqlState);
}
}

Loading…
Cancel
Save