From eee52f88049cf4e51f213bd26fe90127ef207138 Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Sat, 16 May 2009 15:05:28 +0000 Subject: [PATCH] derby embedded db support initial commit; shutdown use case needs work --- org.springframework.jdbc/.classpath | 1 + org.springframework.jdbc/ivy.xml | 1 + .../DerbyEmbeddedDatabaseConfigurer.java | 97 +++++++++++++++++++ .../EmbeddedDatabaseConfigurerFactory.java | 4 +- .../embedded/EmbeddedDatabaseType.java | 2 +- .../jdbc/config/spring-jdbc-3.0.xsd | 11 ++- .../config/JdbcNamespaceIntegrationTest.java | 4 +- .../EmbeddedDatabaseBuilderTests.java | 16 ++- .../jdbc/config/jdbc-config.xml | 7 +- .../datasource/embedded/db-schema-derby.sql | 1 + .../jdbc/datasource/embedded/db-schema.sql | 0 .../jdbc/datasource/embedded/db-test-data.sql | 0 .../src/test/{java => resources}/schema.sql | 0 .../test/{java => resources}/test-data.sql | 0 14 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DerbyEmbeddedDatabaseConfigurer.java create mode 100644 org.springframework.jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-derby.sql rename org.springframework.jdbc/src/test/{java => resources}/org/springframework/jdbc/datasource/embedded/db-schema.sql (100%) rename org.springframework.jdbc/src/test/{java => resources}/org/springframework/jdbc/datasource/embedded/db-test-data.sql (100%) rename org.springframework.jdbc/src/test/{java => resources}/schema.sql (100%) rename org.springframework.jdbc/src/test/{java => resources}/test-data.sql (100%) diff --git a/org.springframework.jdbc/.classpath b/org.springframework.jdbc/.classpath index d5a8c94a2a4..b9a398df391 100644 --- a/org.springframework.jdbc/.classpath +++ b/org.springframework.jdbc/.classpath @@ -17,5 +17,6 @@ + diff --git a/org.springframework.jdbc/ivy.xml b/org.springframework.jdbc/ivy.xml index f56748154a3..c88ed949e5e 100644 --- a/org.springframework.jdbc/ivy.xml +++ b/org.springframework.jdbc/ivy.xml @@ -32,6 +32,7 @@ + diff --git a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DerbyEmbeddedDatabaseConfigurer.java b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DerbyEmbeddedDatabaseConfigurer.java new file mode 100644 index 00000000000..d3b04b89e2a --- /dev/null +++ b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/DerbyEmbeddedDatabaseConfigurer.java @@ -0,0 +1,97 @@ +/* + * Copyright 2002-2009 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.embedded; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.SQLNonTransientConnectionException; + +import javax.sql.DataSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.derby.jdbc.EmbeddedDriver; +import org.springframework.jdbc.datasource.SimpleDriverDataSource; +import org.springframework.util.ClassUtils; + +/** + * {@link EmbeddedDatabaseConfigurer} for Apache Derby database. + * + * @author Oliver Gierke + */ +public class DerbyEmbeddedDatabaseConfigurer implements EmbeddedDatabaseConfigurer { + + private static final Log logger = LogFactory.getLog(DerbyEmbeddedDatabaseConfigurer.class); + + private static final String URL_TEMPLATE = "jdbc:derby:memory:%s;%s"; + + // Error codes that indicate successful shutdown + private static final String SHUTDOWN_CODE = "08006"; + + private static DerbyEmbeddedDatabaseConfigurer INSTANCE; + + private DerbyEmbeddedDatabaseConfigurer() { + } + + /** + * Get the singleton {@link HsqlEmbeddedDatabaseConfigurer} instance. + * @return the configurer + * @throws ClassNotFoundException if HSQL is not on the classpath + */ + public static synchronized DerbyEmbeddedDatabaseConfigurer getInstance() throws ClassNotFoundException { + if (INSTANCE == null) { + ClassUtils.forName("org.apache.derby.jdbc.EmbeddedDriver", DerbyEmbeddedDatabaseConfigurer.class + .getClassLoader()); + INSTANCE = new DerbyEmbeddedDatabaseConfigurer(); + } + return INSTANCE; + } + + public void configureConnectionProperties(ConnectionProperties properties, String databaseName) { + properties.setDriverClass(org.apache.derby.jdbc.EmbeddedDriver.class); + properties.setUrl(String.format(URL_TEMPLATE, databaseName, "create=true")); + properties.setUsername("sa"); + properties.setPassword(""); + } + + @Override + public void shutdown(DataSource dataSource, String databaseName) { + Connection connection = null; + try { + SimpleDriverDataSource shutdownDataSource = new SimpleDriverDataSource(); + shutdownDataSource.setDriverClass(EmbeddedDriver.class); + shutdownDataSource.setUrl(String.format(URL_TEMPLATE, databaseName, "shutdown=true")); + connection = shutdownDataSource.getConnection(); + } catch (SQLException e) { + if (e instanceof SQLNonTransientConnectionException) { + SQLNonTransientConnectionException ex = (SQLNonTransientConnectionException) e; + if (!SHUTDOWN_CODE.equals(ex.getSQLState())) { + logException(e); + } + } else { + logException(e); + } + } finally { + JdbcUtils.closeConnection(connection); + } + } + + private void logException(SQLException e) { + if (logger.isWarnEnabled()) { + logger.warn("Could not shutdown in-memory Derby database", e); + } + } +} diff --git a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurerFactory.java b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurerFactory.java index 35d01b1540a..685a4ac9e46 100644 --- a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurerFactory.java +++ b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseConfigurerFactory.java @@ -33,6 +33,8 @@ final class EmbeddedDatabaseConfigurerFactory { return HsqlEmbeddedDatabaseConfigurer.getInstance(); case H2: return H2EmbeddedDatabaseConfigurer.getInstance(); + case DERBY: + return DerbyEmbeddedDatabaseConfigurer.getInstance(); default: throw new UnsupportedOperationException("Other embedded database types not yet supported"); } @@ -41,7 +43,7 @@ final class EmbeddedDatabaseConfigurerFactory { + "] are not available in the classpath", e); } } - + private EmbeddedDatabaseConfigurerFactory() { } diff --git a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseType.java b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseType.java index 052e53d722b..138a4a15daa 100644 --- a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseType.java +++ b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseType.java @@ -21,5 +21,5 @@ package org.springframework.jdbc.datasource.embedded; * @author Oliver Gierke */ public enum EmbeddedDatabaseType { - HSQL, H2; + HSQL, H2, DERBY; } diff --git a/org.springframework.jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.0.xsd b/org.springframework.jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.0.xsd index 8b8296f0398..0fcab2cae40 100644 --- a/org.springframework.jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.0.xsd +++ b/org.springframework.jdbc/src/main/resources/org/springframework/jdbc/config/spring-jdbc-3.0.xsd @@ -33,10 +33,10 @@ - + @@ -71,6 +71,13 @@ ]]> + + + + + diff --git a/org.springframework.jdbc/src/test/java/org/springframework/jdbc/config/JdbcNamespaceIntegrationTest.java b/org.springframework.jdbc/src/test/java/org/springframework/jdbc/config/JdbcNamespaceIntegrationTest.java index ee25e3df4fc..47493609f7e 100644 --- a/org.springframework.jdbc/src/test/java/org/springframework/jdbc/config/JdbcNamespaceIntegrationTest.java +++ b/org.springframework.jdbc/src/test/java/org/springframework/jdbc/config/JdbcNamespaceIntegrationTest.java @@ -15,7 +15,9 @@ public class JdbcNamespaceIntegrationTest { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "org/springframework/jdbc/config/jdbc-config.xml"); assertCorrectSetup(context.getBean("dataSource", DataSource.class)); - assertCorrectSetup(context.getBean("h2dataSource", DataSource.class)); + assertCorrectSetup(context.getBean("h2DataSource", DataSource.class)); + assertCorrectSetup(context.getBean("derbyDataSource", DataSource.class)); + context.close(); } private void assertCorrectSetup(DataSource dataSource) { diff --git a/org.springframework.jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilderTests.java b/org.springframework.jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilderTests.java index 11d7e02f3be..108d38e5ea1 100644 --- a/org.springframework.jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilderTests.java +++ b/org.springframework.jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/EmbeddedDatabaseBuilderTests.java @@ -1,8 +1,11 @@ package org.springframework.jdbc.datasource.embedded; -import static org.junit.Assert.*; -import static org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType.DERBY; +import static org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType.H2; +import org.junit.Ignore; import org.junit.Test; import org.springframework.jdbc.core.JdbcTemplate; @@ -28,6 +31,15 @@ public class EmbeddedDatabaseBuilderTests { assertDatabaseCreatedAndShutdown(db); } + @Test + @Ignore + public void testBuildDerby() { + // TODO this fails when the whole suite runs b/c tables are not cleaned up + EmbeddedDatabaseBuilder builder = EmbeddedDatabaseBuilder.relativeTo(getClass()); + EmbeddedDatabase db = builder.type(DERBY).script("db-schema-derby.sql").script("db-test-data.sql").build(); + assertDatabaseCreatedAndShutdown(db); + } + @Test public void testBuildNoSuchScript() { try { diff --git a/org.springframework.jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-config.xml b/org.springframework.jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-config.xml index 3d27bb6d54f..44c66eba6bf 100644 --- a/org.springframework.jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-config.xml +++ b/org.springframework.jdbc/src/test/resources/org/springframework/jdbc/config/jdbc-config.xml @@ -10,9 +10,14 @@ - + + + + + + diff --git a/org.springframework.jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-derby.sql b/org.springframework.jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-derby.sql new file mode 100644 index 00000000000..9b2e14d70d8 --- /dev/null +++ b/org.springframework.jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema-derby.sql @@ -0,0 +1 @@ +create table T_TEST (NAME varchar(50) not null); \ No newline at end of file diff --git a/org.springframework.jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/db-schema.sql b/org.springframework.jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema.sql similarity index 100% rename from org.springframework.jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/db-schema.sql rename to org.springframework.jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-schema.sql diff --git a/org.springframework.jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/db-test-data.sql b/org.springframework.jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-test-data.sql similarity index 100% rename from org.springframework.jdbc/src/test/java/org/springframework/jdbc/datasource/embedded/db-test-data.sql rename to org.springframework.jdbc/src/test/resources/org/springframework/jdbc/datasource/embedded/db-test-data.sql diff --git a/org.springframework.jdbc/src/test/java/schema.sql b/org.springframework.jdbc/src/test/resources/schema.sql similarity index 100% rename from org.springframework.jdbc/src/test/java/schema.sql rename to org.springframework.jdbc/src/test/resources/schema.sql diff --git a/org.springframework.jdbc/src/test/java/test-data.sql b/org.springframework.jdbc/src/test/resources/test-data.sql similarity index 100% rename from org.springframework.jdbc/src/test/java/test-data.sql rename to org.springframework.jdbc/src/test/resources/test-data.sql