diff --git a/spring-batch-samples/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java b/archetypes/simple-cli/src/main/java/test/jdbc/datasource/DataSourceInitializer.java similarity index 60% rename from spring-batch-samples/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java rename to archetypes/simple-cli/src/main/java/test/jdbc/datasource/DataSourceInitializer.java index c47eb6c3a..ccfdef88f 100644 --- a/spring-batch-samples/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java +++ b/archetypes/simple-cli/src/main/java/test/jdbc/datasource/DataSourceInitializer.java @@ -22,30 +22,60 @@ import java.util.List; import javax.sql.DataSource; import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanInitializationException; -import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.Resource; import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; -public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { +/** + * Wrapper for a {@link DataSource} that can run scripts on start up and shut + * down. Us as a bean definition

+ * + * Run this class to initialize a database in a running server process. + * Make sure the server is running first by launching the "hsql-server" from the + * hsql.server project. Then you can right click in Eclipse and + * Run As -> Java Application. Do the same any time you want to wipe the + * database and start again. + * + * @author Dave Syer + * + */ +public class DataSourceInitializer implements InitializingBean, DisposableBean { + + private static final Log logger = LogFactory.getLog(DataSourceInitializer.class); private Resource[] initScripts; - private Resource destroyScript; + private Resource[] destroyScripts; private DataSource dataSource; - + private boolean ignoreFailedDrop = true; private static boolean initialized = false; + /** + * Main method as convenient entry point. + * + * @param args + */ + public static void main(String... args) { + new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath(DataSourceInitializer.class, + DataSourceInitializer.class.getSimpleName() + "-context.xml")); + } + /** * @throws Throwable * @see java.lang.Object#finalize() @@ -56,42 +86,40 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { logger.debug("finalize called"); } - protected void destroyInstance(Object instance) throws Exception { - try { - doExecuteScript(destroyScript); - } - catch (Exception e) { - if (logger.isDebugEnabled()) { - logger.warn("Could not execute destroy script [" + destroyScript + "]", e); + public void destroy() { + if (destroyScripts==null) return; + for (int i = 0; i < destroyScripts.length; i++) { + Resource destroyScript = initScripts[i]; + try { + doExecuteScript(destroyScript); } - else { - logger.warn("Could not execute destroy script [" + destroyScript + "]"); + catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.warn("Could not execute destroy script [" + destroyScript + "]", e); + } + else { + logger.warn("Could not execute destroy script [" + destroyScript + "]"); + } } } } public void afterPropertiesSet() throws Exception { Assert.notNull(dataSource); - super.afterPropertiesSet(); + initialize(); } - protected Object createInstance() throws Exception { - Assert.notNull(dataSource); + private void initialize() { if (!initialized) { - try { - doExecuteScript(destroyScript); - } - catch (Exception e) { - logger.debug("Could not execute destroy script [" + destroyScript + "]", e); - } + destroy(); if (initScripts != null) { - for (Resource initScript : initScripts) { + for (int i = 0; i < initScripts.length; i++) { + Resource initScript = initScripts[i]; doExecuteScript(initScript); } } initialized = true; } - return dataSource; } private void doExecuteScript(final Resource scriptResource) { @@ -102,7 +130,7 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { @SuppressWarnings("unchecked") public Object doInTransaction(TransactionStatus status) { - SimpleJdbcTemplate jdbcTemplate = new SimpleJdbcTemplate(dataSource); + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); String[] scripts; try { scripts = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource @@ -111,15 +139,17 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { catch (IOException e) { throw new BeanInitializationException("Cannot load script from [" + scriptResource + "]", e); } - for (String script1 : scripts) { - String script = script1.trim(); + for (int i = 0; i < scripts.length; i++) { + String script = scripts[i].trim(); if (StringUtils.hasText(script)) { try { - jdbcTemplate.getJdbcOperations().execute(script); - } catch (DataAccessException e) { + jdbcTemplate.execute(script); + } + catch (DataAccessException e) { if (ignoreFailedDrop && script.toLowerCase().startsWith("drop")) { logger.debug("DROP script failed (ignoring): " + script); - } else { + } + else { throw e; } } @@ -136,32 +166,24 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { StringBuffer buffer = new StringBuffer(); for (String line : list) { if (!line.startsWith("//") && !line.startsWith("--")) { - buffer.append(line).append("\n"); + buffer.append(line + "\n"); } } return buffer.toString(); } - public Class getObjectType() { - return DataSource.class; - } - - public void setInitScript(Resource initScript) { - this.initScripts = new Resource[] { initScript }; - } - public void setInitScripts(Resource[] initScripts) { this.initScripts = initScripts; } - public void setDestroyScript(Resource destroyScript) { - this.destroyScript = destroyScript; + public void setDestroyScripts(Resource[] destroyScripts) { + this.destroyScripts = destroyScripts; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } - + public void setIgnoreFailedDrop(boolean ignoreFailedDrop) { this.ignoreFailedDrop = ignoreFailedDrop; } diff --git a/archetypes/simple-cli/src/main/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java b/archetypes/simple-cli/src/main/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java deleted file mode 100644 index c4cf618d7..000000000 --- a/archetypes/simple-cli/src/main/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2006-2007 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 test.jdbc.datasource; - -import java.io.IOException; -import java.util.List; - -import javax.sql.DataSource; - -import org.apache.commons.io.IOUtils; -import org.springframework.beans.factory.BeanInitializationException; -import org.springframework.beans.factory.config.AbstractFactoryBean; -import org.springframework.core.io.Resource; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.transaction.TransactionStatus; -import org.springframework.transaction.support.TransactionCallback; -import org.springframework.transaction.support.TransactionTemplate; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { - - private Resource[] initScripts; - - private Resource destroyScript; - - DataSource dataSource; - - private static boolean initialized = false; - - /** - * @throws Throwable - * @see java.lang.Object#finalize() - */ - protected void finalize() throws Throwable { - super.finalize(); - initialized = false; - logger.debug("finalize called"); - } - - protected void destroyInstance(Object instance) throws Exception { - try { - doExecuteScript(destroyScript); - } - catch (Exception e) { - if (logger.isDebugEnabled()) { - logger.warn("Could not execute destroy script [" + destroyScript + "]", e); - } - else { - logger.warn("Could not execute destroy script [" + destroyScript + "]"); - } - } - } - - public void afterPropertiesSet() throws Exception { - Assert.notNull(dataSource); - super.afterPropertiesSet(); - } - - protected Object createInstance() throws Exception { - Assert.notNull(dataSource); - if (!initialized) { - try { - doExecuteScript(destroyScript); - } - catch (Exception e) { - logger.debug("Could not execute destroy script [" + destroyScript + "]", e); - } - if (initScripts != null) { - for (int i = 0; i < initScripts.length; i++) { - Resource initScript = initScripts[i]; - doExecuteScript(initScript); - } - } - initialized = true; - } - return dataSource; - } - - private void doExecuteScript(final Resource scriptResource) { - if (scriptResource == null || !scriptResource.exists()) - return; - TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource)); - transactionTemplate.execute(new TransactionCallback() { - - @SuppressWarnings("unchecked") - public Object doInTransaction(TransactionStatus status) { - JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); - String[] scripts; - try { - scripts = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource - .getInputStream())), ";"); - } - catch (IOException e) { - throw new BeanInitializationException("Cannot load script from [" + scriptResource + "]", e); - } - for (int i = 0; i < scripts.length; i++) { - String script = scripts[i].trim(); - if (StringUtils.hasText(script)) { - jdbcTemplate.execute(scripts[i]); - } - } - return null; - } - - }); - - } - - private String stripComments(List list) { - StringBuffer buffer = new StringBuffer(); - for (String line : list) { - if (!line.startsWith("//") && !line.startsWith("--")) { - buffer.append(line + "\n"); - } - } - return buffer.toString(); - } - - public Class getObjectType() { - return DataSource.class; - } - - public void setInitScripts(Resource[] initScripts) { - this.initScripts = initScripts; - } - - public void setDestroyScript(Resource destroyScript) { - this.destroyScript = destroyScript; - } - - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - } - -} diff --git a/spring-batch-core/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java b/spring-batch-core/src/test/java/test/jdbc/datasource/DataSourceInitializer.java similarity index 58% rename from spring-batch-core/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java rename to spring-batch-core/src/test/java/test/jdbc/datasource/DataSourceInitializer.java index c4cf618d7..ccfdef88f 100644 --- a/spring-batch-core/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java +++ b/spring-batch-core/src/test/java/test/jdbc/datasource/DataSourceInitializer.java @@ -22,27 +22,60 @@ import java.util.List; import javax.sql.DataSource; import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanInitializationException; -import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.Resource; +import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; -public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { +/** + * Wrapper for a {@link DataSource} that can run scripts on start up and shut + * down. Us as a bean definition

+ * + * Run this class to initialize a database in a running server process. + * Make sure the server is running first by launching the "hsql-server" from the + * hsql.server project. Then you can right click in Eclipse and + * Run As -> Java Application. Do the same any time you want to wipe the + * database and start again. + * + * @author Dave Syer + * + */ +public class DataSourceInitializer implements InitializingBean, DisposableBean { + + private static final Log logger = LogFactory.getLog(DataSourceInitializer.class); private Resource[] initScripts; - private Resource destroyScript; + private Resource[] destroyScripts; - DataSource dataSource; + private DataSource dataSource; + + private boolean ignoreFailedDrop = true; private static boolean initialized = false; + /** + * Main method as convenient entry point. + * + * @param args + */ + public static void main(String... args) { + new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath(DataSourceInitializer.class, + DataSourceInitializer.class.getSimpleName() + "-context.xml")); + } + /** * @throws Throwable * @see java.lang.Object#finalize() @@ -53,34 +86,32 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { logger.debug("finalize called"); } - protected void destroyInstance(Object instance) throws Exception { - try { - doExecuteScript(destroyScript); - } - catch (Exception e) { - if (logger.isDebugEnabled()) { - logger.warn("Could not execute destroy script [" + destroyScript + "]", e); + public void destroy() { + if (destroyScripts==null) return; + for (int i = 0; i < destroyScripts.length; i++) { + Resource destroyScript = initScripts[i]; + try { + doExecuteScript(destroyScript); } - else { - logger.warn("Could not execute destroy script [" + destroyScript + "]"); + catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.warn("Could not execute destroy script [" + destroyScript + "]", e); + } + else { + logger.warn("Could not execute destroy script [" + destroyScript + "]"); + } } } } public void afterPropertiesSet() throws Exception { Assert.notNull(dataSource); - super.afterPropertiesSet(); + initialize(); } - protected Object createInstance() throws Exception { - Assert.notNull(dataSource); + private void initialize() { if (!initialized) { - try { - doExecuteScript(destroyScript); - } - catch (Exception e) { - logger.debug("Could not execute destroy script [" + destroyScript + "]", e); - } + destroy(); if (initScripts != null) { for (int i = 0; i < initScripts.length; i++) { Resource initScript = initScripts[i]; @@ -89,7 +120,6 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { } initialized = true; } - return dataSource; } private void doExecuteScript(final Resource scriptResource) { @@ -112,7 +142,17 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { for (int i = 0; i < scripts.length; i++) { String script = scripts[i].trim(); if (StringUtils.hasText(script)) { - jdbcTemplate.execute(scripts[i]); + try { + jdbcTemplate.execute(script); + } + catch (DataAccessException e) { + if (ignoreFailedDrop && script.toLowerCase().startsWith("drop")) { + logger.debug("DROP script failed (ignoring): " + script); + } + else { + throw e; + } + } } } return null; @@ -132,20 +172,20 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { return buffer.toString(); } - public Class getObjectType() { - return DataSource.class; - } - public void setInitScripts(Resource[] initScripts) { this.initScripts = initScripts; } - public void setDestroyScript(Resource destroyScript) { - this.destroyScript = destroyScript; + public void setDestroyScripts(Resource[] destroyScripts) { + this.destroyScripts = destroyScripts; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } + public void setIgnoreFailedDrop(boolean ignoreFailedDrop) { + this.ignoreFailedDrop = ignoreFailedDrop; + } + } diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/data-source-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/data-source-context.xml index 07236f0de..0499aa2c2 100644 --- a/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/data-source-context.xml +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/repository/dao/data-source-context.xml @@ -1,13 +1,8 @@ - - - - - - - + + schema-hsqldb.sql @@ -15,6 +10,10 @@ + + + + diff --git a/spring-batch-infrastructure-tests/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java b/spring-batch-infrastructure-tests/src/test/java/test/jdbc/datasource/DataSourceInitializer.java similarity index 58% rename from spring-batch-infrastructure-tests/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java rename to spring-batch-infrastructure-tests/src/test/java/test/jdbc/datasource/DataSourceInitializer.java index c4cf618d7..ccfdef88f 100644 --- a/spring-batch-infrastructure-tests/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java +++ b/spring-batch-infrastructure-tests/src/test/java/test/jdbc/datasource/DataSourceInitializer.java @@ -22,27 +22,60 @@ import java.util.List; import javax.sql.DataSource; import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanInitializationException; -import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.Resource; +import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; -public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { +/** + * Wrapper for a {@link DataSource} that can run scripts on start up and shut + * down. Us as a bean definition

+ * + * Run this class to initialize a database in a running server process. + * Make sure the server is running first by launching the "hsql-server" from the + * hsql.server project. Then you can right click in Eclipse and + * Run As -> Java Application. Do the same any time you want to wipe the + * database and start again. + * + * @author Dave Syer + * + */ +public class DataSourceInitializer implements InitializingBean, DisposableBean { + + private static final Log logger = LogFactory.getLog(DataSourceInitializer.class); private Resource[] initScripts; - private Resource destroyScript; + private Resource[] destroyScripts; - DataSource dataSource; + private DataSource dataSource; + + private boolean ignoreFailedDrop = true; private static boolean initialized = false; + /** + * Main method as convenient entry point. + * + * @param args + */ + public static void main(String... args) { + new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath(DataSourceInitializer.class, + DataSourceInitializer.class.getSimpleName() + "-context.xml")); + } + /** * @throws Throwable * @see java.lang.Object#finalize() @@ -53,34 +86,32 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { logger.debug("finalize called"); } - protected void destroyInstance(Object instance) throws Exception { - try { - doExecuteScript(destroyScript); - } - catch (Exception e) { - if (logger.isDebugEnabled()) { - logger.warn("Could not execute destroy script [" + destroyScript + "]", e); + public void destroy() { + if (destroyScripts==null) return; + for (int i = 0; i < destroyScripts.length; i++) { + Resource destroyScript = initScripts[i]; + try { + doExecuteScript(destroyScript); } - else { - logger.warn("Could not execute destroy script [" + destroyScript + "]"); + catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.warn("Could not execute destroy script [" + destroyScript + "]", e); + } + else { + logger.warn("Could not execute destroy script [" + destroyScript + "]"); + } } } } public void afterPropertiesSet() throws Exception { Assert.notNull(dataSource); - super.afterPropertiesSet(); + initialize(); } - protected Object createInstance() throws Exception { - Assert.notNull(dataSource); + private void initialize() { if (!initialized) { - try { - doExecuteScript(destroyScript); - } - catch (Exception e) { - logger.debug("Could not execute destroy script [" + destroyScript + "]", e); - } + destroy(); if (initScripts != null) { for (int i = 0; i < initScripts.length; i++) { Resource initScript = initScripts[i]; @@ -89,7 +120,6 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { } initialized = true; } - return dataSource; } private void doExecuteScript(final Resource scriptResource) { @@ -112,7 +142,17 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { for (int i = 0; i < scripts.length; i++) { String script = scripts[i].trim(); if (StringUtils.hasText(script)) { - jdbcTemplate.execute(scripts[i]); + try { + jdbcTemplate.execute(script); + } + catch (DataAccessException e) { + if (ignoreFailedDrop && script.toLowerCase().startsWith("drop")) { + logger.debug("DROP script failed (ignoring): " + script); + } + else { + throw e; + } + } } } return null; @@ -132,20 +172,20 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { return buffer.toString(); } - public Class getObjectType() { - return DataSource.class; - } - public void setInitScripts(Resource[] initScripts) { this.initScripts = initScripts; } - public void setDestroyScript(Resource destroyScript) { - this.destroyScript = destroyScript; + public void setDestroyScripts(Resource[] destroyScripts) { + this.destroyScripts = destroyScripts; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } + public void setIgnoreFailedDrop(boolean ignoreFailedDrop) { + this.ignoreFailedDrop = ignoreFailedDrop; + } + } diff --git a/spring-batch-infrastructure-tests/src/test/resources/data-source.xml b/spring-batch-infrastructure-tests/src/test/resources/data-source.xml index c631924c8..5ce1be588 100644 --- a/spring-batch-infrastructure-tests/src/test/resources/data-source.xml +++ b/spring-batch-infrastructure-tests/src/test/resources/data-source.xml @@ -2,14 +2,13 @@ - - + + - + - + diff --git a/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java b/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DataSourceInitializer.java similarity index 58% rename from spring-batch-infrastructure/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java rename to spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DataSourceInitializer.java index c4cf618d7..ccfdef88f 100644 --- a/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/InitializingDataSourceFactoryBean.java +++ b/spring-batch-infrastructure/src/test/java/test/jdbc/datasource/DataSourceInitializer.java @@ -22,27 +22,60 @@ import java.util.List; import javax.sql.DataSource; import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanInitializationException; -import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.Resource; +import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; -public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { +/** + * Wrapper for a {@link DataSource} that can run scripts on start up and shut + * down. Us as a bean definition

+ * + * Run this class to initialize a database in a running server process. + * Make sure the server is running first by launching the "hsql-server" from the + * hsql.server project. Then you can right click in Eclipse and + * Run As -> Java Application. Do the same any time you want to wipe the + * database and start again. + * + * @author Dave Syer + * + */ +public class DataSourceInitializer implements InitializingBean, DisposableBean { + + private static final Log logger = LogFactory.getLog(DataSourceInitializer.class); private Resource[] initScripts; - private Resource destroyScript; + private Resource[] destroyScripts; - DataSource dataSource; + private DataSource dataSource; + + private boolean ignoreFailedDrop = true; private static boolean initialized = false; + /** + * Main method as convenient entry point. + * + * @param args + */ + public static void main(String... args) { + new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath(DataSourceInitializer.class, + DataSourceInitializer.class.getSimpleName() + "-context.xml")); + } + /** * @throws Throwable * @see java.lang.Object#finalize() @@ -53,34 +86,32 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { logger.debug("finalize called"); } - protected void destroyInstance(Object instance) throws Exception { - try { - doExecuteScript(destroyScript); - } - catch (Exception e) { - if (logger.isDebugEnabled()) { - logger.warn("Could not execute destroy script [" + destroyScript + "]", e); + public void destroy() { + if (destroyScripts==null) return; + for (int i = 0; i < destroyScripts.length; i++) { + Resource destroyScript = initScripts[i]; + try { + doExecuteScript(destroyScript); } - else { - logger.warn("Could not execute destroy script [" + destroyScript + "]"); + catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.warn("Could not execute destroy script [" + destroyScript + "]", e); + } + else { + logger.warn("Could not execute destroy script [" + destroyScript + "]"); + } } } } public void afterPropertiesSet() throws Exception { Assert.notNull(dataSource); - super.afterPropertiesSet(); + initialize(); } - protected Object createInstance() throws Exception { - Assert.notNull(dataSource); + private void initialize() { if (!initialized) { - try { - doExecuteScript(destroyScript); - } - catch (Exception e) { - logger.debug("Could not execute destroy script [" + destroyScript + "]", e); - } + destroy(); if (initScripts != null) { for (int i = 0; i < initScripts.length; i++) { Resource initScript = initScripts[i]; @@ -89,7 +120,6 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { } initialized = true; } - return dataSource; } private void doExecuteScript(final Resource scriptResource) { @@ -112,7 +142,17 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { for (int i = 0; i < scripts.length; i++) { String script = scripts[i].trim(); if (StringUtils.hasText(script)) { - jdbcTemplate.execute(scripts[i]); + try { + jdbcTemplate.execute(script); + } + catch (DataAccessException e) { + if (ignoreFailedDrop && script.toLowerCase().startsWith("drop")) { + logger.debug("DROP script failed (ignoring): " + script); + } + else { + throw e; + } + } } } return null; @@ -132,20 +172,20 @@ public class InitializingDataSourceFactoryBean extends AbstractFactoryBean { return buffer.toString(); } - public Class getObjectType() { - return DataSource.class; - } - public void setInitScripts(Resource[] initScripts) { this.initScripts = initScripts; } - public void setDestroyScript(Resource destroyScript) { - this.destroyScript = destroyScript; + public void setDestroyScripts(Resource[] destroyScripts) { + this.destroyScripts = destroyScripts; } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } + public void setIgnoreFailedDrop(boolean ignoreFailedDrop) { + this.ignoreFailedDrop = ignoreFailedDrop; + } + } diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/JpaPagingItemReaderCommonTests-context.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/JpaPagingItemReaderCommonTests-context.xml index 16560ea04..500260735 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/JpaPagingItemReaderCommonTests-context.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/JpaPagingItemReaderCommonTests-context.xml @@ -4,15 +4,14 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd"> - - - - - - - + + + + + + diff --git a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/data-source-context.xml b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/data-source-context.xml index 29aa4d78e..b6001e632 100644 --- a/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/data-source-context.xml +++ b/spring-batch-infrastructure/src/test/resources/org/springframework/batch/item/database/data-source-context.xml @@ -3,25 +3,20 @@ xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd"> - - - - - - - - + + - + + + + - -
\ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/data-source-context-init.xml b/spring-batch-samples/src/main/resources/data-source-context-init.xml index 5e43a36e4..d6103fd9c 100644 --- a/spring-batch-samples/src/main/resources/data-source-context-init.xml +++ b/spring-batch-samples/src/main/resources/data-source-context-init.xml @@ -3,7 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> - + diff --git a/spring-batch-samples/src/test/java/test/jdbc/datasource/DataSourceInitializer.java b/spring-batch-samples/src/test/java/test/jdbc/datasource/DataSourceInitializer.java new file mode 100644 index 000000000..ccfdef88f --- /dev/null +++ b/spring-batch-samples/src/test/java/test/jdbc/datasource/DataSourceInitializer.java @@ -0,0 +1,191 @@ +/* + * Copyright 2006-2007 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 test.jdbc.datasource; + +import java.io.IOException; +import java.util.List; + +import javax.sql.DataSource; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.BeanInitializationException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.core.io.Resource; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionTemplate; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; + +/** + * Wrapper for a {@link DataSource} that can run scripts on start up and shut + * down. Us as a bean definition

+ * + * Run this class to initialize a database in a running server process. + * Make sure the server is running first by launching the "hsql-server" from the + * hsql.server project. Then you can right click in Eclipse and + * Run As -> Java Application. Do the same any time you want to wipe the + * database and start again. + * + * @author Dave Syer + * + */ +public class DataSourceInitializer implements InitializingBean, DisposableBean { + + private static final Log logger = LogFactory.getLog(DataSourceInitializer.class); + + private Resource[] initScripts; + + private Resource[] destroyScripts; + + private DataSource dataSource; + + private boolean ignoreFailedDrop = true; + + private static boolean initialized = false; + + /** + * Main method as convenient entry point. + * + * @param args + */ + public static void main(String... args) { + new ClassPathXmlApplicationContext(ClassUtils.addResourcePathToPackagePath(DataSourceInitializer.class, + DataSourceInitializer.class.getSimpleName() + "-context.xml")); + } + + /** + * @throws Throwable + * @see java.lang.Object#finalize() + */ + protected void finalize() throws Throwable { + super.finalize(); + initialized = false; + logger.debug("finalize called"); + } + + public void destroy() { + if (destroyScripts==null) return; + for (int i = 0; i < destroyScripts.length; i++) { + Resource destroyScript = initScripts[i]; + try { + doExecuteScript(destroyScript); + } + catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.warn("Could not execute destroy script [" + destroyScript + "]", e); + } + else { + logger.warn("Could not execute destroy script [" + destroyScript + "]"); + } + } + } + } + + public void afterPropertiesSet() throws Exception { + Assert.notNull(dataSource); + initialize(); + } + + private void initialize() { + if (!initialized) { + destroy(); + if (initScripts != null) { + for (int i = 0; i < initScripts.length; i++) { + Resource initScript = initScripts[i]; + doExecuteScript(initScript); + } + } + initialized = true; + } + } + + private void doExecuteScript(final Resource scriptResource) { + if (scriptResource == null || !scriptResource.exists()) + return; + TransactionTemplate transactionTemplate = new TransactionTemplate(new DataSourceTransactionManager(dataSource)); + transactionTemplate.execute(new TransactionCallback() { + + @SuppressWarnings("unchecked") + public Object doInTransaction(TransactionStatus status) { + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + String[] scripts; + try { + scripts = StringUtils.delimitedListToStringArray(stripComments(IOUtils.readLines(scriptResource + .getInputStream())), ";"); + } + catch (IOException e) { + throw new BeanInitializationException("Cannot load script from [" + scriptResource + "]", e); + } + for (int i = 0; i < scripts.length; i++) { + String script = scripts[i].trim(); + if (StringUtils.hasText(script)) { + try { + jdbcTemplate.execute(script); + } + catch (DataAccessException e) { + if (ignoreFailedDrop && script.toLowerCase().startsWith("drop")) { + logger.debug("DROP script failed (ignoring): " + script); + } + else { + throw e; + } + } + } + } + return null; + } + + }); + + } + + private String stripComments(List list) { + StringBuffer buffer = new StringBuffer(); + for (String line : list) { + if (!line.startsWith("//") && !line.startsWith("--")) { + buffer.append(line + "\n"); + } + } + return buffer.toString(); + } + + public void setInitScripts(Resource[] initScripts) { + this.initScripts = initScripts; + } + + public void setDestroyScripts(Resource[] destroyScripts) { + this.destroyScripts = destroyScripts; + } + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + public void setIgnoreFailedDrop(boolean ignoreFailedDrop) { + this.ignoreFailedDrop = ignoreFailedDrop; + } + +}