From fbd25467c47fcda1e4d500e1cc3ede3d8ca7f61e Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Mon, 17 Mar 2014 12:26:32 +0100 Subject: [PATCH] Introduce SQL script exception hierarchy This commit continues the work began in SPR-9531 as follows. - ScriptException now extends DataAccessException. - DatabasePopulator.populate() now explicitly throws ScriptException. - Introduced UncategorizedScriptException. - DatabasePopulatorUtils.execute() now throws an UncategorizedScriptException instead of a DataAccessResourceFailureException. Issue: SPR-11564 --- .../init/CompositeDatabasePopulator.java | 11 +++-- .../datasource/init/DatabasePopulator.java | 14 ++++-- .../init/DatabasePopulatorUtils.java | 9 ++-- .../init/ResourceDatabasePopulator.java | 5 +- .../jdbc/datasource/init/ScriptException.java | 7 ++- .../init/UncategorizedScriptException.java | 47 +++++++++++++++++++ .../EmbeddedDatabaseBuilderTests.java | 14 ++---- 7 files changed, 83 insertions(+), 24 deletions(-) create mode 100644 spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/UncategorizedScriptException.java diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulator.java index 4920ada8f7..8b570c2b10 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/CompositeDatabasePopulator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 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,10 +23,11 @@ import java.util.List; /** * {@link DatabasePopulator} implementation that delegates to a list of other - * DatabasePopulator implementations, executing all scripts. + * {@code DatabasePopulator} implementations, executing all scripts. * * @author Dave Syer * @author Juergen Hoeller + * @author Sam Brannen * @since 3.1 */ public class CompositeDatabasePopulator implements DatabasePopulator { @@ -49,9 +50,11 @@ public class CompositeDatabasePopulator implements DatabasePopulator { this.populators.addAll(Arrays.asList(populators)); } - + /** + * {@inheritDoc} + */ @Override - public void populate(Connection connection) throws SQLException { + public void populate(Connection connection) throws SQLException, ScriptException { for (DatabasePopulator populator : this.populators) { populator.populate(connection); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulator.java index 52cdd43016..1e30251a42 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 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,16 +23,22 @@ import java.sql.SQLException; * Strategy used to populate a database during initialization. * * @author Keith Donald + * @author Sam Brannen * @since 3.0 * @see ResourceDatabasePopulator + * @see DatabasePopulatorUtils */ public interface DatabasePopulator { /** * Populate the database using the JDBC connection provided. - * @param connection the JDBC connection to use to populate the db; already configured and ready to use - * @throws SQLException if an unrecoverable data access exception occurs during database population + * @param connection the JDBC connection to use to populate the db; already + * configured and ready to use + * @throws SQLException if an unrecoverable data access exception occurs + * during database population + * @throws ScriptException in all other error cases + * @see DatabasePopulatorUtils#execute */ - void populate(Connection connection) throws SQLException; + void populate(Connection connection) throws SQLException, ScriptException; } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java index 6125ae9fd9..898c6a394a 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java @@ -21,7 +21,6 @@ import java.sql.Connection; import javax.sql.DataSource; import org.springframework.dao.DataAccessException; -import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.util.Assert; @@ -39,7 +38,7 @@ public abstract class DatabasePopulatorUtils { * Execute the given {@link DatabasePopulator} against the given {@link DataSource}. * @param populator the {@code DatabasePopulator} to execute * @param dataSource the {@code DataSource} to execute against - * @throws DataAccessException if an error occurs + * @throws DataAccessException if an error occurs, specifically a {@link ScriptException} */ public static void execute(DatabasePopulator populator, DataSource dataSource) throws DataAccessException { Assert.notNull(populator, "DatabasePopulator must be provided"); @@ -56,7 +55,11 @@ public abstract class DatabasePopulatorUtils { } } catch (Exception ex) { - throw new DataAccessResourceFailureException("Failed to execute database script", ex); + if (ex instanceof ScriptException) { + throw (ScriptException) ex; + } + + throw new UncategorizedScriptException("Failed to execute database script", ex); } } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java index de1202d8ba..8f4189a421 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ResourceDatabasePopulator.java @@ -179,8 +179,11 @@ public class ResourceDatabasePopulator implements DatabasePopulator { this.ignoreFailedDrops = ignoreFailedDrops; } + /** + * {@inheritDoc} + */ @Override - public void populate(Connection connection) throws SQLException { + public void populate(Connection connection) throws SQLException, ScriptException { for (Resource script : this.scripts) { ScriptUtils.executeSqlScript(connection, encodeScript(script), this.continueOnError, this.ignoreFailedDrops, this.commentPrefix, this.separator, this.blockCommentStartDelimiter, diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java index 31c8a9618d..198284d1ba 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/ScriptException.java @@ -16,14 +16,17 @@ package org.springframework.jdbc.datasource.init; +import org.springframework.dao.DataAccessException; + /** - * Root of the hierarchy of SQL script exceptions. + * Root of the hierarchy of data access exceptions that are related to processing + * of SQL scripts. * * @author Sam Brannen * @since 4.0.3 */ @SuppressWarnings("serial") -public abstract class ScriptException extends RuntimeException { +public abstract class ScriptException extends DataAccessException { /** * Constructor for {@code ScriptException}. diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/UncategorizedScriptException.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/UncategorizedScriptException.java new file mode 100644 index 0000000000..bf50befb5e --- /dev/null +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/UncategorizedScriptException.java @@ -0,0 +1,47 @@ +/* + * Copyright 2002-2014 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.datasource.init; + +/** + * Thrown when we cannot determine anything more specific than "something went + * wrong while processing an SQL script": for example, a {@link java.sql.SQLException} + * from JDBC that we cannot pinpoint more precisely. + * + * @author Sam Brannen + * @since 4.0.3 + */ +@SuppressWarnings("serial") +public class UncategorizedScriptException extends ScriptException { + + /** + * Construct a new {@code UncategorizedScriptException}. + * @param message detailed message + */ + public UncategorizedScriptException(String message) { + super(message); + } + + /** + * Construct a new {@code UncategorizedScriptException}. + * @param message detailed message + * @param cause the root cause + */ + public UncategorizedScriptException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilderTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilderTests.java index a3983c2583..32fedb2321 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilderTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 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,7 +19,6 @@ package org.springframework.jdbc.datasource.embedded; import org.junit.Test; import org.springframework.core.io.ClassRelativeResourceLoader; -import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.init.CannotReadScriptException; @@ -27,6 +26,7 @@ import static org.junit.Assert.*; /** * @author Keith Donald + * @author Sam Brannen */ public class EmbeddedDatabaseBuilderTests { @@ -80,15 +80,9 @@ public class EmbeddedDatabaseBuilderTests { assertDatabaseCreatedAndShutdown(db); } - @Test + @Test(expected = CannotReadScriptException.class) public void testBuildNoSuchScript() { - try { - new EmbeddedDatabaseBuilder().addScript("bogus.sql").build(); - fail("Should have failed"); - } - catch (DataAccessResourceFailureException ex) { - assertTrue(ex.getCause() instanceof CannotReadScriptException); - } + new EmbeddedDatabaseBuilder().addScript("bogus.sql").build(); } private void assertDatabaseCreatedAndShutdown(EmbeddedDatabase db) {