spring-projects / spring-projects/spring-boot

Eagerly initialize JdbcTemplate's SQLExceptionTranslator without requiring a DB connection

Open
#28,842 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

type: enhancement
Dominant language
Java
Stars
81.5k
Forks
42.7k
Avg merge
2d 4h
Merged PRs (30d)
65

Description

Currently (as of Spring Boot 2.6), when data source is initialized, by default JDBC exception translator is lazily initialized, meaning, the first time JDBC exception occurs, exception translator will be initialized. However for exception translator initialization, an available JDBC connection is required. This may be problematic in certain scenarios (please see some of them later in the issue description), as this is a 'Chicken and Egg' problem.

As Spring Boot already has the feature to detect JDBC driver from JDBC URL, and as DatabaseDriver class already has database product name, it could be possible to eagerly initialize JDBC exception translator w/o the need for JDBC connection (using database product name obtained from JDBC URL via DatabaseDriver enum).

Some of the scenarios when the current behavior may cause problems:

  1. In the recent versions of Oracle UCP, seems that the UCP pool starts to destroy itself by listening to the shutdown hook, meaning it starts destruction before some Spring Beans that depend on it are destroyed. If no JDBC exceptions happened at all since a Spring Boot app has been started, and an exception occurs the first time during the Spring context destruction, it could not be translated as it is not possible to obtain a database connection.

  2. In general, if database is unavailable at the moment when the first JDBC exception occurs, exception translation would not be possible. For example when network link to the database is broken before any JDBC exception happens, SQL exception with a cause like socket read IO error cannot be translated.

It is possible to make a workaround like:

@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
	var jdbcTemplate = new JdbcTemplate(dataSource);
	jdbcTemplate.setExceptionTranslator(new SQLErrorCodeSQLExceptionTranslator("Oracle"));
	return jdbcTemplate;
}

However, it is required to explicitly put the specific database product name (although Spring Boot can determine it via DatabaseDriver class, database product name is not publicly accessible by the application).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with JdbcTemplate's lazy SQLExceptionTranslator initialization and Spring Boot's DatabaseDriver enum, following the JDBC URL and database product name path described in the issue. Done means the translator is initialized eagerly without requiring a JDBC connection, while the listed unavailable-database and shutdown scenarios still produce translated exceptions.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring-boot
Domain
backend, databases
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.