Skip to content

Commit

Permalink
Support existing database in directory subsubprotocol (GH #15)
Browse files Browse the repository at this point in the history
Added support to skip the create=true attribute in the JDBC URL to
initialize the database.
Fixed / Cleaned up tests and documentation

Resolves #15

Change-Id: Id8bd785c102868a1cd6b27bf284572b1cf5a121b
  • Loading branch information
bindul committed Feb 19, 2016
1 parent 105bbf4 commit ba55e46
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 45 deletions.
22 changes: 22 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!--
Copyright 2016 Development Entropy (deventropy.org) Contributors
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.
-->

# JUnit Helper Changelog

The *Changes Report* is available on each individual module's site.

* [JUnit Helper Changes Report](http://www.deventropy.org/junit-helper/changes-report.html)
* [JUnit Helper :: Derby Changes Report](http://www.deventropy.org/junit-helper/junit-helper-derby/changes-report.html)
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
<!--
Copyright 2016 Development Entropy (deventropy.org) Contributors
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.
-->

# JUnit Helper Utilities / Resources

[![License](https://img.shields.io/github/license/deventropy/junit-helper.svg)](./LICENSE)
Expand Down
3 changes: 3 additions & 0 deletions junit-helper-derby/src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ limitations under the License.
<action dev="bindul" type="add" issue="10" date="2016-02-17">
Support Classpath sub-sub protocol for Apache Derby External Resource
</action>
<action dev="bindul" type="add" issue="15" date="2016-02-18">
Added support for skipping create attribute
</action>
</release>
</body>
</document>
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,14 @@ public class DerbyResourceConfig {
*/
private String jarDatabaseJarFile;

// TODO have combined setters for the sub protocols (with other required values)
/**
* Skip the <code>create=true</code> attribute in the connection URL
*/
private boolean directoryDatabaseSkipCreate = false;

/**
* The database subsubprotocol for the JDBC URL
*/
private JdbcDerbySubSubProtocol subSubProtocol;

// TODO Complete configuring logging
Expand Down Expand Up @@ -112,6 +119,16 @@ public String getDatabasePath () {
return databasePath;
}

/**
* For a database using the {@link JdbcDerbySubSubProtocol#Directory} subsubprotocol, skip the
* <code>create=true</code> attribute.
*
* @return the directoryDatabaseSkipCreate
*/
public boolean isDirectoryDatabaseSkipCreate () {
return directoryDatabaseSkipCreate;
}

/**
* Returns the default database name value, which is a UUID string.
* @return The default database name.
Expand Down Expand Up @@ -162,7 +179,7 @@ public DerbyResourceConfig useDatabaseInDirectory () {
this.databasePath = getDefaultDatabasePathName();
return this;
}

/**
* Use the <code>:directory:</code> Derby sub sub protocol, with the database in the specified
* <code>directorpyDbPath</code>. The path is either relative or absolute as interpreted by the Derby engine.
Expand All @@ -171,11 +188,28 @@ public DerbyResourceConfig useDatabaseInDirectory () {
* @return This instance
*/
public DerbyResourceConfig useDatabaseInDirectory (final String directorpyDbPath) {
return useDatabaseInDirectory(directorpyDbPath, false);
}

/**
* Use the <code>:directory:</code> Derby sub sub protocol, with the database in the specified
* <code>directorpyDbPath</code>. The path is either relative or absolute as interpreted by the Derby engine. If the
* <code>skipCreateAttribute</code> attribute is set to <code>true</code>, the Database will be initialized without
* the <code>create=true</code> attribute.
*
* @param directorpyDbPath The relative or absolute path where the database is created.
* @param skipCreateAttribute Skip the <code>create=true</code> attribute in the connection URL
* @return This instance
*/
public DerbyResourceConfig useDatabaseInDirectory (final String directorpyDbPath,
final boolean skipCreateAttribute) {

ArgumentCheck.notNullOrEmpty(directorpyDbPath, "database path");
resetSubSubProtocolSpecificValues();

this.subSubProtocol = JdbcDerbySubSubProtocol.Directory;
this.databasePath = directorpyDbPath;
this.directoryDatabaseSkipCreate = skipCreateAttribute;
return this;
}

Expand Down Expand Up @@ -249,6 +283,7 @@ public static JdbcDerbySubSubProtocol getDefaultSubSubProtocol () {
private void resetSubSubProtocolSpecificValues () {
this.databasePath = null;
this.jarDatabaseJarFile = null;
this.directoryDatabaseSkipCreate = false;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,15 @@ private void executePostInitScripts (final Connection conn) throws IOException {
}

private String buildCreateJDBCUrl () {
final StringBuilder createDbJdbcUrl = new StringBuilder(jdbcUrl);
final JdbcDerbySubSubProtocol subSubProtocol = config.getSubSubProtocol();
// Only :memory: and :directory: databases need the 'create' flag.
if (JdbcDerbySubSubProtocol.Memory == subSubProtocol
|| (JdbcDerbySubSubProtocol.Directory == subSubProtocol && !config.isDirectoryDatabaseSkipCreate())) {
createDbJdbcUrl.append(URLPROP_DERBY_CREATE);
}
// TODO Will handle things here to restore from a backup, etc.
return new StringBuilder().append(jdbcUrl).append(URLPROP_DERBY_CREATE).toString();
return createDbJdbcUrl.toString();
}

private void setupDerbyProperties () throws IOException {
Expand Down
44 changes: 25 additions & 19 deletions junit-helper-derby/src/site/markdown/manual/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,10 @@ set for any other sub-sub protocol.

### <a name="in-memory"></a>In Memory Database

*Method to enable:* `#useInMemoryDatabase() or #useInMemoryDatabase(String)`
*Enumeration Value:* Memory
*Derby JDBC URL prefix:* jdbc:derby:memory:
*Additional Configurations:* Database Name
*Method to enable:* `#useInMemoryDatabase() or #useInMemoryDatabase(String)`<br />
*Enumeration Value:* Memory<br />
*Derby JDBC URL prefix:* jdbc:derby:memory:<br />
*Additional Configurations:* Database Name<br />

Databases exist only in main memory and are not written to disk.

Expand All @@ -165,10 +165,11 @@ If the database name is not set, an automatic database name is generated using a

### <a name="directory"></a>Database in Directory

*Method to enable:* `#useDatabaseInDirectory() or #useDatabaseInDirectory(String)`
*Enumeration Value:* Directory
*Derby JDBC URL prefix:* jdbc:derby:directory:
*Additional Configurations:* Database Path
*Method to enable:* `#useDatabaseInDirectory() or #useDatabaseInDirectory(String) or #useDatabaseInDirectory(String,
boolean)`<br />
*Enumeration Value:* Directory<br />
*Derby JDBC URL prefix:* jdbc:derby:directory:<br />
*Additional Configurations:* Database Path, Skip create attribute<br />

The database runs in a specified directory, either a relative directory under the `Derby System Directory` or an
absolute directory outside the system directory. See [Connecting to databases](http://db.apache.org/derby/docs/10.12/devguide/cdevdvlp34964.html)
Expand All @@ -181,11 +182,16 @@ is not set, an automatic database path is generated using a `java.util.UUID` obj
is used internally, which generates a new UUID value on every call. This will be a sub directory under the `Derby System
Directory`.

#### Non empty database directory
#### Skip `create` attribute

*This behavior may change with the resolution of [Issue #15](https://github.com/deventropy/junit-helper/issues/15)*
By default, for the `memory` and `directory` databases, the `EmbeddedDerbyResource` starts the Derby instance with the
[create=true attribute](http://db.apache.org/derby/docs/10.12/ref/rrefattrib26867.html). The configuration allows the
user to skip this attribute using the `#useDatabaseInDirectory(String, boolean)` method with the `skipCreateAttribute`
attribute set to `true`.

The `EmbeddedDerbyResource` starts the database with the `;create=true` JDBC URL parameter, and it seems like Derby
#### Existing (non-database) existing directory

When the `EmbeddedDerbyResource` starts the database with the `;create=true` JDBC URL parameter, and it seems like Derby
[likes to create its own directory](http://mail-archives.apache.org/mod_mbox/db-derby-user/200912.mbox/%3C4B3C845A.3050104@gmx.ch%3E).
If the directory (relative or absolute) specified as the `#getDatabasePath()` already exists, the Derby startup will
fail with an error similar to:
Expand All @@ -207,10 +213,10 @@ So, if a directory path is specified in `#useDatabaseInDirectory(String)`, ensur

### <a name="jar"></a>Database in a Jar

*Method to enable:* `#useJarSubSubProtocol(String, String)`
*Enumeration Value:* Jar
*Derby JDBC URL prefix:* jdbc:derby:jar:
*Additional Configurations:* Path to Jar file &amp; Database Path
*Method to enable:* `#useJarSubSubProtocol(String, String)`<br />
*Enumeration Value:* Jar<br />
*Derby JDBC URL prefix:* jdbc:derby:jar:<br />
*Additional Configurations:* Path to Jar file &amp; Database Path<br />

Derby supports creating and using Read Only databases; which may be pre-existing database setup and data that is used
in tests. For instructions on how to create read only database, see the Derby documentation
Expand All @@ -236,10 +242,10 @@ Due to lack of documentation on how to implement this, the tool currently does n

### <a name="classpath"></a>Database from the classpath

*Method to enable:* `#useClasspathSubSubProtocol(String)`
*Enumeration Value:* Classpath
*Derby JDBC URL prefix:* jdbc:derby:classpath:
*Additional Configurations:* Database Path
*Method to enable:* `#useClasspathSubSubProtocol(String)`<br />
*Enumeration Value:* Classpath<br />
*Derby JDBC URL prefix:* jdbc:derby:classpath:<br />
*Additional Configurations:* Database Path<br />

This is another type of Read Only database supported by Derby. The database exists on the classpath, either in a Jar
file or directly in the classpath. The _Database Path_ mentioned above designates the path to the database in the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.sql.SQLException;

import org.deventropy.shared.utils.DirectoryArchiverUtil;
import org.junit.AfterClass;
import org.junit.rules.TemporaryFolder;

/**
Expand Down Expand Up @@ -112,7 +113,7 @@ protected File createAndShutdownDbInDirSimple01 (final TemporaryFolder tempFolde
final EmbeddedDerbyResource embeddedDerbyResource = new EmbeddedDerbyResource(derbyResourceConfig,
derbySystemHomeDir);
embeddedDerbyResource.start();
embeddedDerbyResource.close();
closeEmbeddedDerbyResource(embeddedDerbyResource);

// Shutdown Derby
DerbyUtils.shutdownDerbySystemQuitely(true);
Expand All @@ -129,5 +130,14 @@ protected void closeEmbeddedDerbyResource (final EmbeddedDerbyResource embeddedD
embeddedDerbyResource.close();
}
}

/**
* Cleanup stuff.
*/
@AfterClass
public static void cleanupDerbySystem () {
// Cleanup for next test
DerbyUtils.shutdownDerbySystemQuitely(true);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,20 @@ public void testDirectoryProtocol () {
assertEquals("Sub-sub protocol should be Directory", JdbcDerbySubSubProtocol.Directory,
resourceConfig.getSubSubProtocol());
assertEquals("Database path should be test directory", dbPath, resourceConfig.getDatabasePath());

// Set again with create false
resourceConfig.useDatabaseInDirectory(dbPath, true);
assertEquals("Sub-sub protocol should be Directory", JdbcDerbySubSubProtocol.Directory,
resourceConfig.getSubSubProtocol());
assertEquals("Database path should be test directory", dbPath, resourceConfig.getDatabasePath());
assertTrue("The skip create true", resourceConfig.isDirectoryDatabaseSkipCreate());

// Reset again and make sure it is false
resourceConfig.useDatabaseInDirectory(dbPath);
assertEquals("Sub-sub protocol should be Directory", JdbcDerbySubSubProtocol.Directory,
resourceConfig.getSubSubProtocol());
assertEquals("Database path should be test directory", dbPath, resourceConfig.getDatabasePath());
assertFalse("The skip create true", resourceConfig.isDirectoryDatabaseSkipCreate());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@
import java.sql.SQLException;

import org.apache.commons.io.FileUtils;
import org.deventropy.junithelper.derby.DerbyUtils;
import org.deventropy.junithelper.derby.EmbeddedDerbyResource;
import org.deventropy.shared.utils.ClassUtil;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
Expand Down Expand Up @@ -100,13 +98,4 @@ public void testSimpleClasspathDatabaseFromDir () throws IOException, SQLExcepti
public void cleanupAfterClasspathDbTest () throws Exception {
Thread.currentThread().setContextClassLoader(parentLoader);
}

/**
* Cleanup stuff.
*/
@AfterClass
public static void cleanupDerbySystem () {
// Cleanup for next test
DerbyUtils.shutdownDerbySystemQuitely(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
* @author Bindul Bhowmik
*
*/
public class DatabaseDbCustomDirAllTest extends AbstractEmbeddedDerbyResourceTest {
public class DirectoryDbCustomDirAllTest extends AbstractEmbeddedDerbyResourceTest {

private static final String DB_NAME = "test-database-directory-test01-customdirectory";
private Logger log = LogManager.getFormatterLogger();
Expand Down Expand Up @@ -88,7 +88,7 @@ public void testCustomDirectoryDatabase () throws SQLException {
@After
public void afterTest () {
try {
embeddedDerbyResource.close();
closeEmbeddedDerbyResource(embeddedDerbyResource);
} catch (IOException e) {
log.catching(Level.TRACE, e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2016 Development Entropy (deventropy.org) Contributors
*
* 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.deventropy.junithelper.derby.directory.simple01;

import static org.junit.Assert.*;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;

import org.deventropy.junithelper.derby.AbstractEmbeddedDerbyResourceTest;
import org.deventropy.junithelper.derby.DerbyResourceConfig;
import org.deventropy.junithelper.derby.EmbeddedDerbyResource;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

/**
* @author Bindul Bhowmik
*
*/
public class DirectoryDbExistingDbDirTest extends AbstractEmbeddedDerbyResourceTest {

private static final String DB_NAME = "test-database-dir-test04-custom-existing";

@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();

@Test
public void testStartingDbFromExistingDbDir () throws IOException, SQLException {
final File dbPathFile = createAndShutdownDbInDirSimple01(tempFolder, DB_NAME);
final File derbyHome = tempFolder.newFolder();
final DerbyResourceConfig config = DerbyResourceConfig.buildDefault()
.useDatabaseInDirectory(dbPathFile.getAbsolutePath(), true);
final EmbeddedDerbyResource embeddedDerbyResource = new EmbeddedDerbyResource(config, derbyHome);
embeddedDerbyResource.start();

// Make sure derby loads up
final String jdbcUrl = embeddedDerbyResource.getJdbcUrl();
assertNotNull(jdbcUrl);

simpleDb01Check01(jdbcUrl);

// Done, shut it down
closeEmbeddedDerbyResource(embeddedDerbyResource);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
* @author Bindul Bhowmik
*
*/
public class DatabaseDbTempDirDirTest {
public class DirectoryDbTempDirDirTest {

private static final String DB_NAME = "test-db-dir-simple01-tmpfolder-dirtest-nulllog";

Expand Down

0 comments on commit ba55e46

Please sign in to comment.