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
This commit is contained in:
Sam Brannen 2014-03-17 12:26:32 +01:00
parent f68bd5c8b2
commit fbd25467c4
7 changed files with 83 additions and 24 deletions

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 * {@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 Dave Syer
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen
* @since 3.1 * @since 3.1
*/ */
public class CompositeDatabasePopulator implements DatabasePopulator { public class CompositeDatabasePopulator implements DatabasePopulator {
@ -49,9 +50,11 @@ public class CompositeDatabasePopulator implements DatabasePopulator {
this.populators.addAll(Arrays.asList(populators)); this.populators.addAll(Arrays.asList(populators));
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void populate(Connection connection) throws SQLException { public void populate(Connection connection) throws SQLException, ScriptException {
for (DatabasePopulator populator : this.populators) { for (DatabasePopulator populator : this.populators) {
populator.populate(connection); populator.populate(connection);
} }

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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. * Strategy used to populate a database during initialization.
* *
* @author Keith Donald * @author Keith Donald
* @author Sam Brannen
* @since 3.0 * @since 3.0
* @see ResourceDatabasePopulator * @see ResourceDatabasePopulator
* @see DatabasePopulatorUtils
*/ */
public interface DatabasePopulator { public interface DatabasePopulator {
/** /**
* Populate the database using the JDBC connection provided. * 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 * @param connection the JDBC connection to use to populate the db; already
* @throws SQLException if an unrecoverable data access exception occurs during database population * 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;
} }

View File

@ -21,7 +21,6 @@ import java.sql.Connection;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -39,7 +38,7 @@ public abstract class DatabasePopulatorUtils {
* Execute the given {@link DatabasePopulator} against the given {@link DataSource}. * Execute the given {@link DatabasePopulator} against the given {@link DataSource}.
* @param populator the {@code DatabasePopulator} to execute * @param populator the {@code DatabasePopulator} to execute
* @param dataSource the {@code DataSource} to execute against * @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 { public static void execute(DatabasePopulator populator, DataSource dataSource) throws DataAccessException {
Assert.notNull(populator, "DatabasePopulator must be provided"); Assert.notNull(populator, "DatabasePopulator must be provided");
@ -56,7 +55,11 @@ public abstract class DatabasePopulatorUtils {
} }
} }
catch (Exception ex) { 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);
} }
} }

View File

@ -179,8 +179,11 @@ public class ResourceDatabasePopulator implements DatabasePopulator {
this.ignoreFailedDrops = ignoreFailedDrops; this.ignoreFailedDrops = ignoreFailedDrops;
} }
/**
* {@inheritDoc}
*/
@Override @Override
public void populate(Connection connection) throws SQLException { public void populate(Connection connection) throws SQLException, ScriptException {
for (Resource script : this.scripts) { for (Resource script : this.scripts) {
ScriptUtils.executeSqlScript(connection, encodeScript(script), this.continueOnError, ScriptUtils.executeSqlScript(connection, encodeScript(script), this.continueOnError,
this.ignoreFailedDrops, this.commentPrefix, this.separator, this.blockCommentStartDelimiter, this.ignoreFailedDrops, this.commentPrefix, this.separator, this.blockCommentStartDelimiter,

View File

@ -16,14 +16,17 @@
package org.springframework.jdbc.datasource.init; 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 * @author Sam Brannen
* @since 4.0.3 * @since 4.0.3
*/ */
@SuppressWarnings("serial") @SuppressWarnings("serial")
public abstract class ScriptException extends RuntimeException { public abstract class ScriptException extends DataAccessException {
/** /**
* Constructor for {@code ScriptException}. * Constructor for {@code ScriptException}.

View File

@ -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);
}
}

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.junit.Test;
import org.springframework.core.io.ClassRelativeResourceLoader; import org.springframework.core.io.ClassRelativeResourceLoader;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.init.CannotReadScriptException; import org.springframework.jdbc.datasource.init.CannotReadScriptException;
@ -27,6 +26,7 @@ import static org.junit.Assert.*;
/** /**
* @author Keith Donald * @author Keith Donald
* @author Sam Brannen
*/ */
public class EmbeddedDatabaseBuilderTests { public class EmbeddedDatabaseBuilderTests {
@ -80,15 +80,9 @@ public class EmbeddedDatabaseBuilderTests {
assertDatabaseCreatedAndShutdown(db); assertDatabaseCreatedAndShutdown(db);
} }
@Test @Test(expected = CannotReadScriptException.class)
public void testBuildNoSuchScript() { public void testBuildNoSuchScript() {
try { new EmbeddedDatabaseBuilder().addScript("bogus.sql").build();
new EmbeddedDatabaseBuilder().addScript("bogus.sql").build();
fail("Should have failed");
}
catch (DataAccessResourceFailureException ex) {
assertTrue(ex.getCause() instanceof CannotReadScriptException);
}
} }
private void assertDatabaseCreatedAndShutdown(EmbeddedDatabase db) { private void assertDatabaseCreatedAndShutdown(EmbeddedDatabase db) {