]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-1580,CSPACE-1627: Updates to ID Generator records are now temporarily row...
authorAron Roberts <aron@socrates.berkeley.edu>
Wed, 28 Apr 2010 20:26:54 +0000 (20:26 +0000)
committerAron Roberts <aron@socrates.berkeley.edu>
Wed, 28 Apr 2010 20:26:54 +0000 (20:26 +0000)
services/id/service/src/main/java/org/collectionspace/services/id/IDServiceJdbcImpl.java

index 2211960caac30947825b297dd7858c1a72d5706a..8c4cf522254d1f9f6243d9b77a3d48ff679f4e11 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 // *IMPORTANT*
 // @TODO Revise exception handling to return custom Exceptions,
 // perhaps mirroring the subset of HTTP status codes returned.
 //
 // We're currently overloading existing core and extension Java Exceptions
 // in ways that are not consistent with their original semantic meaning.
-
 // @TODO Get the JDBC driver classname and database URL from configuration;
 // better yet, substitute JPA or Hibernate for JDBC for accessing
 // database-managed persistence.
-
 // @TODO Remove any hard-coded dependencies on MySQL.
-
 // @TODO Determine how to restrict access to ID-related tables by role.
-
 // @TODO Retrieve IDGenerators from the database (via JDBC or
 // Hibernate) at initialization and refresh time.
-
 // @TODO Handle both CollectionSpace IDs and URIs as identifiers
 // for ID generators, replacing simple integer IDs.
 //
@@ -48,7 +42,6 @@
 // To uniquely identify ID generators in production, we'll need to handle
 // both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
 // other form of identifier to be determined, such as URLs or URNs.
-
 // @TODO Handle concurrency.
 //
 // Right now, with each new request we're simply instantiating
 //
 // At that point, we'll also need to add code to handle concurrent
 // requests to modify that state.
-
 // @TODO Verify access (public, protected, or private) to service methods.
-
 // @TODO As long as we're using JDBC, use PreparedStatements, not Statements,
 // throughout the code below.
-
 // @TODO Re-consider beginnings of method names:
 // - "store/get" versus:
 // - "store/retrieve"
@@ -74,7 +64,6 @@
 // - "persist/find" (used by JPA)
 // - or?
 // For now have used CRUD-like names, consistent with other classes.
-
 package org.collectionspace.services.id;
 
 import java.sql.Connection;
@@ -105,560 +94,609 @@ import org.slf4j.LoggerFactory;
  */
 public class IDServiceJdbcImpl implements IDService {
 
-       final Logger logger = LoggerFactory.getLogger(IDServiceJdbcImpl.class);
-       
-       final String JDBC_DRIVER_CLASSNAME = "com.mysql.jdbc.Driver";
-       final String DATABASE_NAME = "cspace";
-       final String DATABASE_URL = "jdbc:mysql://localhost:3306/" + DATABASE_NAME;
-       final String DATABASE_USERNAME = "test";
-       final String DATABASE_PASSWORD = "test";
-       final String TABLE_NAME = "id_generator";
-       
-       boolean hasPreconditions = true;
-
-       //////////////////////////////////////////////////////////////////////
-       /**
-       * Constructor (no-argument).
-       */ 
-       public void IDServiceJdbcImpl() throws IllegalStateException {
-       
-               // @TODO Decide when and how to fail at startup, or else to correct
-               // failure conditions automatically, when preconditions are not met.
-               //
-               // Currently, errors at initialization are merely informative and
-               // result in exceptions that can be persistently logged.
-       
-               try {
-                       init();
-               } catch (IllegalStateException e) {
-                       throw e;
-               }
-       
-       }
-       
-       // @TODO init() is currently UNTESTED as of 2009-08-11T13:00-0700.
-       
+    final Logger logger = LoggerFactory.getLogger(IDServiceJdbcImpl.class);
+    final String JDBC_DRIVER_CLASSNAME = "com.mysql.jdbc.Driver";
+    final String DATABASE_NAME = "cspace";
+    final String DATABASE_URL = "jdbc:mysql://localhost:3306/" + DATABASE_NAME;
+    final String DATABASE_USERNAME = "test";
+    final String DATABASE_PASSWORD = "test";
+    final String TABLE_NAME = "id_generator";
+    boolean jdbcDriverInstantiated = false;
+    boolean hasPreconditions = true;
+
     //////////////////////////////////////////////////////////////////////
-   /**
-       * Initializes the service.
-       *
-       * @throws  IllegalStateException if one or more of the required preconditions
-       *          for the service is not present, or is not in its required state.
-       */
-       public void init() throws IllegalStateException {
-       
-               logger.debug("> in init");
-       
-               try {
-                       instantiateJdbcDriver(JDBC_DRIVER_CLASSNAME);
-               } catch (IllegalStateException e) {
-                       throw e;
-               }
-               
-               try {
-                       boolean hasTable = hasTable(TABLE_NAME);
-                       if (! hasTable) {
-                       String msg =
-                               "Required table " +
-                               "\'" + TABLE_NAME + "\'" +
-                               " could not be found in the database.";
-                               logger.warn(msg);
-                       throw new IllegalStateException(msg);
-                 }
-               } catch (IllegalStateException e) {
-                       throw e;
-               }
-       
-       }
-
-       // -----------------
+    /**
+     * Constructor (no-argument).
+     */
+    public void IDServiceJdbcImpl() throws IllegalStateException {
+
+        // @TODO Decide when and how to fail at startup, or else to correct
+        // failure conditions automatically, when preconditions are not met.
+        //
+        // Currently, errors at initialization are merely informative and
+        // result in exceptions that can be persistently logged.
+
+        try {
+            init();
+        } catch (IllegalStateException e) {
+            throw e;
+        }
+
+    }
+
+    // @TODO init() is currently UNTESTED as of 2009-08-11T13:00-0700.
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Initializes the service.
+     *
+     * @throws  IllegalStateException if one or more of the required preconditions
+     *          for the service is not present, or is not in its required state.
+     */
+    public void init() throws IllegalStateException {
+
+        logger.debug("> in init");
+
+        try {
+            instantiateJdbcDriver(JDBC_DRIVER_CLASSNAME);
+        } catch (IllegalStateException e) {
+            throw e;
+        }
+
+        try {
+            boolean hasTable = hasTable(TABLE_NAME);
+            if (!hasTable) {
+                String msg =
+                        "Required table "
+                        + "\'" + TABLE_NAME + "\'"
+                        + " could not be found in the database.";
+                logger.warn(msg);
+                throw new IllegalStateException(msg);
+            }
+        } catch (IllegalStateException e) {
+            throw e;
+        }
+
+    }
+
+    // -----------------
     // Operations on IDs
     // -----------------
-       
-       //////////////////////////////////////////////////////////////////////
-   /**
-       * Generates and returns a new ID associated with a specified ID generator.
-       *
-       * This method has an intentional side-effect: it sets the
-       * current ID of that ID generator to the just-generated ID.
-       *
-       * @param  csid  An identifier for an ID generator.
-       *
-       * @return  A new ID associated with the specified ID generator.
-       *
-       * @throws  IllegalArgumentException if the provided csid is null or empty,
-       *          or if the specified ID generator can't be found.
-       *
-       * @throws  IllegalStateException if a storage-related error occurred.
-       */
-       @Override
-       public String createID(String csid) throws DocumentNotFoundException,
-               BadRequestException, IllegalArgumentException, IllegalStateException {
-               
-               logger.debug("> in createID");
-               
-               // @TODO Where relevant, implement logic to check for ID availability,
-               // after generating a candidate ID.
-               
-               // @TODO: Add checks for authorization to perform this operation.
-               
-               String newId = "";
-               String lastId = "";
-               
-               if (csid == null || csid.equals("")) {
-                       throw new DocumentNotFoundException(
-                               "Identifier for ID generator must not be null or empty.");
-               }
-               
-               String serializedGenerator = "";
-               try {
-                       serializedGenerator = readIDGenerator(csid).getGeneratorState();
-               } catch (DocumentNotFoundException e ) {
-                       throw e;
-               } catch (IllegalArgumentException e ) {
-                       throw e;
-               } catch (IllegalStateException e ) {
-                       throw e;
-               }
-               
-               // Guard code - should not be needed.
-               if (serializedGenerator == null || serializedGenerator.equals("")) {
-                       throw new BadRequestException(
-                               "ID generator " + "\'" + csid + "\'" + " could not be found.");
-               }
-               
-               SettableIDGenerator generator;
-               try {
-                       generator = IDGeneratorSerializer.deserialize(serializedGenerator);
-               } catch (IllegalArgumentException e) {
-                       throw e;
-               }
-               
-               try {
-               
-                       // Retrieve the last ID associated with this generator
-                       // from persistent storage.
-                       lastId = readLastID(csid);
-                       
-                       // If there was no last generated ID associated with this generator,
-                       // get a new ID.
-                       if (lastId == null || lastId.equals("")) {
-                               newId = generator.newID();
-                       
-                       // Otherwise, generate a new ID, potentially based on the last ID.
-                       // (This also sets the current ID of the ID generator's state
-                       // to this just-generated 'new' ID.)
-                       } else {
-                               newId = generator.newID(lastId);
-                       }
-                       
-                       // Store the 'new' ID as the last-generated ID for this generator.
-                       updateLastID(csid, newId);
-                       
-                       // Store the new state of this ID generator, reflecting that
-                       // one of its parts may possibly have had its value updated as
-                       // a result of the generation of this 'new' ID.
-                       updateIDGenerator(csid, generator);
-                 
-               } catch (IllegalArgumentException e ) {
-                   throw e;
-               } catch (IllegalStateException e ) {
-                       throw e;
-               }
-               
-               return newId;
-       
-       }
-
-       //////////////////////////////////////////////////////////////////////
-   /**
-       * Stores the last-generated ID, corresponding to a specified ID generator,
-       * into persistent storage.
-       *
-       * @param  csid     An identifier for an ID generator.
-       *
-       * @param  generator  An ID generator, including the values of its constituent parts.
-       *
-       * @param  lastId  The value of the last-generated ID associated with that ID generator.
-       *
-       * @throws  IllegalArgumentException if the requested ID generator could not be found.
-       *
-       * @throws  IllegalStateException if a storage-related error occurred.
-       */
-       public void updateLastID(String csid, String lastId)
-         throws IllegalArgumentException, IllegalStateException {
-       
-               logger.debug("> in updateLastID");
-               
-               // @TODO Where relevant, implement logic to check for ID availability,
-               // after generating a candidate ID.
-               
-               // @TODO: Add checks for authorization to perform this operation.
-               
-               Connection conn = null;
-               try {
-               
-                       conn = getJdbcConnection();
-                       Statement stmt = conn.createStatement();
-                       
-                       int rowsUpdated = stmt.executeUpdate(
-                         "UPDATE id_generators SET last_generated_id='" + lastId +
-                         "' WHERE csid='" + csid + "'");
-                         
-                       if (rowsUpdated != 1) {
-                               throw new IllegalStateException(
-                                       "Error updating last-generated ID in the database " +
-                                       "for ID generator '" + csid + "'");
-                       }
-               
-                 logger.debug("> successfully updated last-generated ID: " + lastId);
-               
-               } catch (SQLException e) {
-                       throw new IllegalStateException("Error updating last-generated " +
-                           "ID in the database: " + e.getMessage());
-               } finally {
-                       try {
-                               if (conn != null) {
-                                       conn.close();
-                               }
-                       } catch(SQLException e) {
-                               // Do nothing here
-                       }
-               }
-       
-       }
-       
-       //////////////////////////////////////////////////////////////////////
-   /**
-       * Returns the last-generated ID, corresponding to a specified ID generator,
-       * from persistent storage.
-       *
-       * @param  csid  An identifier for an ID generator.
-       *
-       * @return  The last ID generated that corresponds to the requested ID generator.
-       *
-       * @throws  DocumentNotFoundException if the requested ID generator
-    *          could not be found.
-       *
-       * @throws  IllegalStateException if a storage-related error occurred.
-       */
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Generates and returns a new ID associated with a specified ID generator.
+     *
+     * This method has an intentional side-effect: it sets the
+     * current ID of that ID generator to the just-generated ID.
+     *
+     * @param  csid  An identifier for an ID generator.
+     *
+     * @return  A new ID associated with the specified ID generator.
+     *
+     * @throws  IllegalArgumentException if the provided csid is null or empty,
+     *          or if the specified ID generator can't be found.
+     *
+     * @throws  IllegalStateException if a storage-related error occurred.
+     */
+    @Override
+    public String createID(String csid) throws DocumentNotFoundException,
+            BadRequestException, IllegalArgumentException, IllegalStateException {
+
+        logger.debug("> in createID");
+
+        // @TODO Where relevant, implement logic to check for ID availability,
+        // after generating a candidate ID.
+
+        // @TODO: Add checks for authorization to perform this operation.
+
+        String newId = "";
+        String lastId = "";
+
+        if (csid == null || csid.equals("")) {
+            throw new DocumentNotFoundException(
+                    "Identifier for ID generator must not be null or empty.");
+        }
+
+        String serializedGenerator = "";
+        try {
+            IDGeneratorInstance generator = readIDGenerator(csid);
+            serializedGenerator = generator.getGeneratorState();
+            // serializedGenerator = readIDGenerator(csid).getGeneratorState();
+        } catch (DocumentNotFoundException e) {
+            throw e;
+        } catch (IllegalArgumentException e) {
+            throw e;
+        } catch (IllegalStateException e) {
+            throw e;
+        }
+
+        // Guard code - should not be needed.
+        if (serializedGenerator == null || serializedGenerator.equals("")) {
+            throw new BadRequestException(
+                    "ID generator " + "\'" + csid + "\'" + " could not be found.");
+        }
+
+        SettableIDGenerator generator;
+        try {
+            generator = IDGeneratorSerializer.deserialize(serializedGenerator);
+        } catch (IllegalArgumentException e) {
+            throw e;
+        }
+
+        try {
+
+            // Retrieve the last ID associated with this generator
+            // from persistent storage.
+            lastId = readLastID(csid);
+
+            // If there was no last generated ID associated with this generator,
+            // get a new ID.
+            if (lastId == null || lastId.equals("")) {
+                newId = generator.newID();
+
+                // Otherwise, generate a new ID, potentially based on the last ID.
+                // (This also sets the current ID of the ID generator's state
+                // to this just-generated 'new' ID.)
+            } else {
+                newId = generator.newID(lastId);
+            }
+
+            // Store the 'new' ID as the last-generated ID for this generator.
+            updateLastID(csid, newId);
+
+            // Store the new state of this ID generator, reflecting that
+            // one of its parts may possibly have had its value updated as
+            // a result of the generation of this 'new' ID.
+            updateIDGenerator(csid, generator);
+
+        } catch (DocumentNotFoundException e) {
+            throw e;
+        } catch (IllegalArgumentException e) {
+            throw e;
+        } catch (IllegalStateException e) {
+            throw e;
+        }
+
+        return newId;
+
+    }
+
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Stores the last-generated ID, corresponding to a specified ID generator,
+     * into persistent storage.
+     *
+     * @param  csid     An identifier for an ID generator.
+     *
+     * @param  generator  An ID generator, including the values of its constituent parts.
+     *
+     * @param  lastId  The value of the last-generated ID associated with that ID generator.
+     *
+     * @throws  IllegalStateException if a storage-related error occurred.
+     *      *
+     * @throws  DocumentNotFoundException if the requested ID generator could not be found.
+     */
+    public void updateLastID(String csid, String lastId)
+            throws IllegalStateException, DocumentNotFoundException {
+
+        logger.debug("> in updateLastID");
+
+        // @TODO Where relevant, implement logic to check for ID availability,
+        // after generating a candidate ID.
+
+        // @TODO: Add checks for authorization to perform this operation.
+
+        Connection conn = null;
+        try {
+
+            conn = getJdbcConnection();
+            conn.setAutoCommit(false);
+            Statement stmt = conn.createStatement();
+
+            // Test whether this ID generator already exists in the database.
+            // Using a 'SELECT ... FOR UPDATE' statement will temporarily
+            // lock this row for updates from any other connection, until
+            // the UPDATE is committed, below.
+            ResultSet rs = stmt.executeQuery(
+                    "SELECT csid "
+                    + "FROM id_generators "
+                    + "WHERE csid='"
+                    + csid
+                    + "' FOR UPDATE");
+
+            boolean moreRows = rs.next();
+
+            boolean idGeneratorFound = true;
+            if (!moreRows) {
+                idGeneratorFound = false;
+            }
+
+            // If this ID generator was not found in the
+            // database, an update can't be performed.
+            // Close the connection and throw an exception.
+            if (!idGeneratorFound) {
+                conn.close();
+                throw new DocumentNotFoundException(
+                        "Error updating ID generator '" + csid
+                        + "': generator could not be found in the database.");
+            }
+
+            // Otherwise, if this ID generator exists in the database,
+            // update its Last ID value.
+            final String SQL_STATEMENT_STRING =
+                    "UPDATE id_generators SET "
+                    + "last_generated_id = ? "
+                    + "WHERE csid = ?";
+
+            PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
+            ps.setString(1, lastId);
+            ps.setString(2, csid);
+
+            int rowsUpdated = ps.executeUpdate();
+
+            if (rowsUpdated != 1) {
+                throw new IllegalStateException(
+                        "Error updating last-generated ID in the database "
+                        + "for ID generator '" + csid + "'");
+            }
+
+            conn.commit();
+            conn.close();
+
+            logger.debug("Successfully updated last-generated ID: " + lastId);
+
+        } catch (IllegalStateException ise) {
+            throw ise;
+        } catch (SQLException e) {
+            throw new IllegalStateException("Error updating last-generated "
+                    + "ID in the database: " + e.getMessage());
+        } finally {
+            try {
+                if (conn != null) {
+                    conn.close();
+                }
+            } catch (SQLException e) {
+                // Do nothing here
+            }
+        }
+
+    }
+
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Returns the last-generated ID, corresponding to a specified ID generator,
+     * from persistent storage.
+     *
+     * @param  csid  An identifier for an ID generator.
+     *
+     * @return  The last ID generated that corresponds to the requested ID generator.
+     *
+     * @throws  DocumentNotFoundException if the requested ID generator
+     *          could not be found.
+     *
+     * @throws  IllegalStateException if a storage-related error occurred.
+     */
     @Override
-       public String readLastID(String csid) throws DocumentNotFoundException,
-               IllegalStateException {
-       
-               logger.debug("> in readLastID");
-               
-               // @TODO Where relevant, implement logic to check for ID availability,
-               // after generating a candidate ID.
-               
-               // @TODO: Add checks for authorization to perform this operation.
-               
-               String lastId = null;
-               Connection conn = null;
-               try {
-               
-                       conn = getJdbcConnection();
-                       Statement stmt = conn.createStatement();
-                       
-                       ResultSet rs = stmt.executeQuery(
-                         "SELECT last_generated_id FROM id_generators " + 
-                         "WHERE csid='" + csid + "'");
-                         
-                       boolean moreRows = rs.next();
-                       if (! moreRows) {
-                       throw new DocumentNotFoundException(
-                               "ID generator " + "\'" + csid + "\'" + " could not be found.");
-                       }
-               
-                       lastId = rs.getString(1);
-                       logger.debug("> retrieved ID: " + lastId);
-               
-                       rs.close();
-               
-               } catch (SQLException e) {
-                       throw new IllegalStateException("Error retrieving last ID " + 
-                           "from the database: " + e.getMessage());
-               } finally {
-                       try {
-                               if (conn != null) {
-                                 conn.close();
-                               }
-                       } catch(SQLException e) {
-                               // Do nothing here
-                       }
-               }
-               
-               logger.debug("> returning ID: " + lastId);
-               
-               return lastId;
-       
-       }
-
-       // ---------------------------
+    public String readLastID(String csid) throws DocumentNotFoundException,
+            IllegalStateException {
+
+        logger.debug("> in readLastID");
+
+        // @TODO Where relevant, implement logic to check for ID availability,
+        // after generating a candidate ID.
+
+        // @TODO: Add checks for authorization to perform this operation.
+
+        String lastId = null;
+        Connection conn = null;
+        try {
+
+            conn = getJdbcConnection();
+            Statement stmt = conn.createStatement();
+
+            ResultSet rs = stmt.executeQuery(
+                    "SELECT last_generated_id FROM id_generators "
+                    + "WHERE csid='" + csid + "'");
+
+            boolean moreRows = rs.next();
+            if (!moreRows) {
+                throw new DocumentNotFoundException(
+                        "ID generator " + "\'" + csid + "\'" + " could not be found.");
+            }
+
+            lastId = rs.getString(1);
+            logger.debug("> retrieved ID: " + lastId);
+
+            rs.close();
+
+        } catch (IllegalStateException ise) {
+            throw ise;
+        } catch (SQLException e) {
+            throw new IllegalStateException("Error retrieving last ID "
+                    + "from the database: " + e.getMessage());
+        } finally {
+            try {
+                if (conn != null) {
+                    conn.close();
+                }
+            } catch (SQLException e) {
+                // Do nothing here
+            }
+        }
+
+        logger.debug("> returning ID: " + lastId);
+
+        return lastId;
+
+    }
+
+    // ---------------------------
     // Operations on ID Generators
     // ---------------------------
-       
-       //////////////////////////////////////////////////////////////////////
-   /**
-       * Adds a new ID generator instance to persistent storage.
-       *
-       * @param  csid     An identifier for an ID generator.
-       *
-       * @param  generator  An ID generator, reflecting its current state,
-       *                  including the values of its constituent parts.
-       *
-    * @throws  BadRequestException if the provided representation of an
-    *          ID generator instance is not in the correct format, contains
-    *          invalid values, or otherwise cannot be used.
-    *
-       * @throws  IllegalStateException if a storage-related error occurred.
-       */
-       public void createIDGenerator(String csid, SettableIDGenerator generator)
-         throws BadRequestException, IllegalStateException {
-       
-               logger.debug("> in createIDGenerator(String, SettableIDGenerator)");
-       
-               // @TODO: Add checks for authorization to perform this operation.
-               
-               if (generator == null) {
-                       throw new BadRequestException("New ID generator " +
-                           "to add cannot be null.");
-               }
-               
-               String serializedGenerator = "";
-               try {
-                       serializedGenerator = IDGeneratorSerializer.serialize(generator);
-               } catch (BadRequestException e) {
-                       throw e;
-               }
-               
-               try {
-                       createIDGenerator(csid, serializedGenerator);
-               } catch (IllegalArgumentException e) {
-                       throw e;
-               } catch (IllegalStateException e) {
-                       throw e;
-               }
-       
-       }
-       
-   //////////////////////////////////////////////////////////////////////
-   /**
-       * Adds a new ID generator to persistent storage, from a serialization
-       * of that generator.
-       *
-       * The serialization method recognized by this method has implementation
-       * dependencies.  Currently, this method expects serialization via XStream's
-       * out-of-the-box serializer, without custom configuration.
-       *
-       * @param  csid     An identifier for an ID generator.
-       *
-       * @param  serializedGenerator  A serialized ID generator, reflecting its current state,
-       *                              including the values of its constituent parts.
-       *
-    * @throws  BadRequestException if the provided representation of an
-    *          ID generator instance is not in the correct format, contains
-    *          invalid values, or otherwise cannot be used.
-    *
-    * @throws  IllegalStateException if a storage-related error occurred.
-       */
-       @Override
-       public void createIDGenerator(String csid, String serializedGenerator)
-         throws BadRequestException, IllegalStateException {
-       
-               logger.debug("> in createIDGenerator(String, String)");
-       
-               // @TODO Add checks for authorization to perform this operation.
-                       
-               if (serializedGenerator == null || serializedGenerator.equals("")) {
-                       throw new BadRequestException(
-                               "Could not understand or parse this representation " + 
-                               "of an ID generator.");
-               }
-               
-               Connection conn = null;
-               try {
-               
-                       conn = getJdbcConnection();
-                       Statement stmt = conn.createStatement();
-                       
-                       // Test whether this ID generator already exists in the database.
-                       //
-                       // @TODO This check should extend further, to other aspects
-                       // of the generator, such as its URI, if any, and its structure,
-                       // so we avoid duplication based on content as well as identifier.
-                       ResultSet rs = stmt.executeQuery(
-                         "SELECT csid FROM id_generators " +
-                         "WHERE csid='" + csid + "'");
-                         
-                       boolean moreRows = rs.next();
-                       
-                       boolean idGeneratorFound = true;
-                       if (! moreRows) {
-                               idGeneratorFound = false;
-                       }
-                               
-                       // If this ID generator already exists in the database,
-                       // throw an Exception.
-                       //
-                       // @TODO This exception needs to convey the meaning that a
-                       // conflict has occurred, so that this status can be reported
-                       // to the client.
-                       if (idGeneratorFound) {
-                               throw new IllegalStateException(
-                                       "Conflict with existing generator when attempting to add " +
-                                       "new ID generator with ID '" +
-                                       csid +
-                                       "' to the database.");
-                         
-                       // Otherwise, add this new ID generator, as a new record to
-            // the database.
-                       } else {
-                       
-                               final String SQL_STATEMENT_STRING =
-                                       "INSERT INTO id_generators " +
-                                       "(" +
-                                         "csid, " +
-                                         "id_generator_state, " + 
-                                         "last_generated_id" +
-                                       ")" +
-                                       " VALUES (?, ?, ?)";
-                                       
-                               PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
-                               ps.setString(1, csid);
-                               ps.setString(2, serializedGenerator);
-                               ps.setNull(3, java.sql.Types.VARCHAR);
-                               
-                               int rowsUpdated = ps.executeUpdate();
-                               if (rowsUpdated != 1) {
-                                       throw new IllegalStateException(
-                                               "Error adding new ID generator '" + csid +
-                                               "'" + " to the database.");
-                               }
-                       
-                       } // end if (idGeneratorFound)
-                       
-                         logger.debug("> successfully added ID generator: " + csid);
-                       
-                       } catch (SQLException e) {
-                               throw new IllegalStateException("Error adding new ID " +
-                                   "generator to the database: " + e.getMessage());
-                       } finally {
-                               try {
-                                       if (conn != null) {
-                                           conn.close();
-                                       }
-                               } catch(SQLException e) {
-                                   // Do nothing here
-                               }
-                       }
-       
-       }
-
-       //////////////////////////////////////////////////////////////////////
-       /**
-       * Returns a requested ID generator from persistent storage.
-       *
-       * @param  csid  An identifier for an ID generator.
-       *
-       * @return  A serialized representation of the requested ID generator.
-       *
-       * @throws  DocumentNotFoundException if the requested ID generator could
-       *          not be found.
-       *
-       * @throws  IllegalStateException if a storage-related error occurred.
-       */
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Adds a new ID generator instance to persistent storage.
+     *
+     * @param  csid     An identifier for an ID generator.
+     *
+     * @param  generator  An ID generator, reflecting its current state,
+     *                  including the values of its constituent parts.
+     *
+     * @throws  BadRequestException if the provided representation of an
+     *          ID generator instance is not in the correct format, contains
+     *          invalid values, or otherwise cannot be used.
+     *
+     * @throws  IllegalStateException if a storage-related error occurred.
+     */
+    public void createIDGenerator(String csid, SettableIDGenerator generator)
+            throws BadRequestException, IllegalStateException {
+
+        logger.debug("> in createIDGenerator(String, SettableIDGenerator)");
+
+        // @TODO: Add checks for authorization to perform this operation.
+
+        if (generator == null) {
+            throw new BadRequestException("New ID generator "
+                    + "to add cannot be null.");
+        }
+
+        String serializedGenerator = "";
+        try {
+            serializedGenerator = IDGeneratorSerializer.serialize(generator);
+        } catch (BadRequestException e) {
+            throw e;
+        }
+
+        try {
+            createIDGenerator(csid, serializedGenerator);
+        } catch (IllegalArgumentException e) {
+            throw e;
+        } catch (IllegalStateException e) {
+            throw e;
+        }
+
+    }
+
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Adds a new ID generator to persistent storage, from a serialization
+     * of that generator.
+     *
+     * The serialization method recognized by this method has implementation
+     * dependencies.  Currently, this method expects serialization via XStream's
+     * out-of-the-box serializer, without custom configuration.
+     *
+     * @param  csid     An identifier for an ID generator.
+     *
+     * @param  serializedGenerator  A serialized ID generator, reflecting its current state,
+     *                              including the values of its constituent parts.
+     *
+     * @throws  BadRequestException if the provided representation of an
+     *          ID generator instance is not in the correct format, contains
+     *          invalid values, or otherwise cannot be used.
+     *
+     * @throws  IllegalStateException if a storage-related error occurred.
+     */
     @Override
-       public IDGeneratorInstance readIDGenerator (String csid) throws
-           DocumentNotFoundException, IllegalStateException {
-       
-               logger.debug("> in readIDGenerator");
-               
-               IDGeneratorInstance instance = null;
-               
-               Connection conn = null;
-               try {
-               
-                       conn = getJdbcConnection();
-                       Statement stmt = conn.createStatement();
+    public void createIDGenerator(String csid, String serializedGenerator)
+            throws BadRequestException, IllegalStateException {
+
+        logger.debug("> in createIDGenerator(String, String)");
+
+        // @TODO Add checks for authorization to perform this operation.
+
+        if (serializedGenerator == null || serializedGenerator.equals("")) {
+            throw new BadRequestException(
+                    "Could not understand or parse this representation "
+                    + "of an ID generator.");
+        }
 
+        Connection conn = null;
+        try {
+
+            conn = getJdbcConnection();
+            Statement stmt = conn.createStatement();
+
+            // Test whether this ID generator already exists in the database.
+            //
+            // @TODO This check should extend further, to other aspects
+            // of the generator, such as its URI, if any, and its structure,
+            // so we avoid duplication based on content as well as identifier.
             ResultSet rs = stmt.executeQuery(
-                         "SELECT csid, displayname, description, " +
-              "id_generator_state, last_generated_id FROM id_generators " +
-                         "WHERE csid='" + csid + "'");
-                         
-                       boolean moreRows = rs.next();
-                       if (! moreRows) {
-                               throw new DocumentNotFoundException(
-                                   "ID generator with ID " +
-                                   "\'" + csid + "\'" +
-                                   " could not be found.");
-                       }
-               
+                    "SELECT csid FROM id_generators "
+                    + "WHERE csid='" + csid + "'");
+
+            boolean moreRows = rs.next();
+
+            boolean idGeneratorFound = true;
+            if (!moreRows) {
+                idGeneratorFound = false;
+            }
+
+            // If this ID generator already exists in the database,
+            // throw an Exception.
+            //
+            // @TODO This exception needs to convey the meaning that a
+            // conflict has occurred, so that this status can be reported
+            // to the client.
+            if (idGeneratorFound) {
+                throw new IllegalStateException(
+                        "Conflict with existing generator when attempting to add "
+                        + "new ID generator with ID '"
+                        + csid
+                        + "' to the database.");
+
+                // Otherwise, add this new ID generator, as a new record to
+                // the database.
+            } else {
+
+                final String SQL_STATEMENT_STRING =
+                        "INSERT INTO id_generators "
+                        + "("
+                        + "csid, "
+                        + "id_generator_state, "
+                        + "last_generated_id"
+                        + ")"
+                        + " VALUES (?, ?, ?)";
+
+                PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
+                ps.setString(1, csid);
+                ps.setString(2, serializedGenerator);
+                ps.setNull(3, java.sql.Types.VARCHAR);
+
+                int rowsUpdated = ps.executeUpdate();
+                if (rowsUpdated != 1) {
+                    throw new IllegalStateException(
+                            "Error adding new ID generator '" + csid
+                            + "'" + " to the database.");
+                }
+
+            } // end if (idGeneratorFound)
+
+            logger.debug("> successfully added ID generator: " + csid);
+
+        } catch (IllegalStateException ise) {
+            throw ise;
+        } catch (SQLException e) {
+            throw new IllegalStateException("Error adding new ID "
+                    + "generator to the database: " + e.getMessage());
+        } finally {
+            try {
+                if (conn != null) {
+                    conn.close();
+                }
+            } catch (SQLException e) {
+                // Do nothing here
+            }
+        }
+
+    }
+
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Returns a requested ID generator from persistent storage.
+     *
+     * @param  csid  An identifier for an ID generator.
+     *
+     * @return  A serialized representation of the requested ID generator.
+     *
+     * @throws  DocumentNotFoundException if the requested ID generator could
+     *          not be found.
+     *
+     * @throws  IllegalStateException if a storage-related error occurred.
+     */
+    @Override
+    public IDGeneratorInstance readIDGenerator(String csid) throws
+            DocumentNotFoundException, IllegalStateException {
+
+        logger.debug("> in readIDGenerator");
+
+        IDGeneratorInstance instance = null;
+
+        Connection conn = null;
+        try {
+
+            conn = getJdbcConnection();
+            Statement stmt = conn.createStatement();
+
+            ResultSet rs = stmt.executeQuery(
+                    "SELECT csid, displayname, description, "
+                    + "id_generator_state, last_generated_id FROM id_generators "
+                    + "WHERE csid='" + csid + "'");
+
+            boolean moreRows = rs.next();
+            if (!moreRows) {
+                throw new DocumentNotFoundException(
+                        "ID generator with ID "
+                        + "\'" + csid + "\'"
+                        + " could not be found.");
+            }
+
             instance = new IDGeneratorInstance();
             instance.setDisplayName(rs.getString(2));
             instance.setDescription(rs.getString(3));
             instance.setGeneratorState(rs.getString(4));
             instance.setLastGeneratedID(rs.getString(5));
-                       
-                       rs.close();
-               
-               } catch (SQLException e) {
-                       throw new IllegalStateException(
-                               "Error retrieving ID generator " +
-                               "\'" + csid + "\'" +
-                               " from database: " + e.getMessage());
-               } finally {
-                       try {
-                               if (conn != null) {
-                                       conn.close();
-                               }
-                       } catch(SQLException e) {
-                               // Do nothing here
-                       }
-               }
-               
-               logger.debug("> retrieved SettableIDGenerator: " +
-            instance.getGeneratorState());
-               
-               return instance;
-                 
-       }
-
-   //////////////////////////////////////////////////////////////////////
-   /**
-    * Returns a list of ID generator instances from persistent storage.
-       *
-       * @return  A list of ID generator instances, with each list item
-    *          constituting a serialized representation of an
-    *          ID generator instance.
-       *
-       * @throws  IllegalStateException if a storage-related error occurred.
-       */
+
+            rs.close();
+
+        } catch (IllegalStateException ise) {
+            throw ise;
+        } catch (SQLException e) {
+            throw new IllegalStateException(
+                    "Error retrieving ID generator "
+                    + "\'" + csid + "\'"
+                    + " from database: " + e.getMessage());
+        } finally {
+            try {
+                if (conn != null) {
+                    conn.close();
+                }
+            } catch (SQLException e) {
+                // Do nothing here
+            }
+        }
+
+        logger.debug("> retrieved SettableIDGenerator: "
+                + instance.getGeneratorState());
+
+        return instance;
+
+    }
+
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Returns a list of ID generator instances from persistent storage.
+     *
+     * @return  A list of ID generator instances, with each list item
+     *          constituting a serialized representation of an
+     *          ID generator instance.
+     *
+     * @throws  IllegalStateException if a storage-related error occurred.
+     */
     @Override
-    public Map<String,IDGeneratorInstance> readIDGeneratorsList()
+    public Map<String, IDGeneratorInstance> readIDGeneratorsList()
             throws IllegalStateException {
 
-               logger.debug("> in readIDGeneratorsList");
+        logger.debug("> in readIDGeneratorsList");
 
-               Map<String,IDGeneratorInstance> generators =
-            new LinkedHashMap<String,IDGeneratorInstance>();
+        Map<String, IDGeneratorInstance> generators =
+                new LinkedHashMap<String, IDGeneratorInstance>();
 
-               Connection conn = null;
-               try {
+        Connection conn = null;
+        try {
 
-                       conn = getJdbcConnection();
-                       Statement stmt = conn.createStatement();
+            conn = getJdbcConnection();
+            Statement stmt = conn.createStatement();
 
-                       ResultSet rs = stmt.executeQuery(
-                         "SELECT csid, displayname, description, " +
-              "id_generator_state, last_generated_id FROM id_generators " +
-              "ORDER BY displayname ASC"); // , priority ASC");
+            ResultSet rs = stmt.executeQuery(
+                    "SELECT csid, displayname, description, "
+                    + "id_generator_state, last_generated_id FROM id_generators "
+                    + "ORDER BY displayname ASC"); // , priority ASC");
 
-                       boolean moreRows = rs.next();
-                       if (! moreRows) {
-                               return generators;
-                       }
+            boolean moreRows = rs.next();
+            if (!moreRows) {
+                return generators;
+            }
 
             IDGeneratorInstance instance = null;
             while (moreRows = rs.next()) {
@@ -670,383 +708,411 @@ public class IDServiceJdbcImpl implements IDService {
                 generators.put(rs.getString(1), instance);
             }
 
-                       rs.close();
-
-               } catch (SQLException e) {
-                       throw new IllegalStateException(
-                               "Error retrieving ID generators " +
-                               " from database: " + e.getMessage());
-               } finally {
-                       try {
-                               if (conn != null) {
-                                       conn.close();
-                               }
-                       } catch(SQLException e) {
-                               // Do nothing here
-                       }
-               }
-
-               return generators;
+            rs.close();
+
+        } catch (IllegalStateException ise) {
+            throw ise;
+        } catch (SQLException e) {
+            throw new IllegalStateException(
+                    "Error retrieving ID generators "
+                    + " from database: " + e.getMessage());
+        } finally {
+            try {
+                if (conn != null) {
+                    conn.close();
+                }
+            } catch (SQLException e) {
+                // Do nothing here
+            }
+        }
+
+        return generators;
     }
 
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Updates an existing ID generator in persistent storage.
+     *
+     * @param  csid     An identifier for an ID generator.
+     *
+     * @param  generator  An ID generator, reflecting its current state,
+     *                  including the values of its constituent parts.
+     *
+     * @throws  DocumentNotFoundException if the requested ID generator could
+     *          not be found.
+     *
+     * @throws  BadRequestException if the provided representation of an
+     *          ID generator instance is not in the correct format, contains
+     *          invalid values, or otherwise cannot be used.
+     *
+     * @throws  IllegalStateException if a storage-related error occurred.
+     */
+    public void updateIDGenerator(String csid, SettableIDGenerator generator)
+            throws BadRequestException, DocumentNotFoundException,
+            IllegalStateException {
+
+        logger.debug("> in updateIDGenerator(String, SettableIDGenerator)");
+
+        // @TODO: Add checks for authorization to perform this operation.
+
+        if (generator == null) {
+            throw new BadRequestException(
+                    "ID generator provided in update operation cannot be null.");
+        }
+
+        String serializedGenerator = "";
+        try {
+            serializedGenerator = IDGeneratorSerializer.serialize(generator);
+        } catch (BadRequestException e) {
+            throw e;
+        }
+
+        try {
+            updateIDGenerator(csid, serializedGenerator);
+        } catch (DocumentNotFoundException e) {
+            throw e;
+        } catch (BadRequestException e) {
+            throw e;
+        } catch (IllegalStateException e) {
+            throw e;
+        }
+
+    }
+
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Updates an existing ID generator in persistent storage,
+     * from a serialization of the current state of that generator.
+     *
+     * The serialization method recognized by this method has implementation
+     * dependencies.  Currently, this method expects serialization via XStream's
+     * out-of-the-box serializer, without custom configuration.
+     *
+     * @param  csid  An identifier for an ID generator.
+     *
+     * @param  serializedGenerator
+     *           A serialized ID generator, reflecting its current state,
+     *           including the values of its constituent parts.
+     *
+     * @throws  DocumentNotFoundException if the requested ID generator could
+     *          not be found.
+     *
+     * @throws  BadRequestException if the provided representation of an
+     *          ID generator instance is not in the correct format, contains
+     *          invalid values, or otherwise cannot be used.
+     *
+     * @throws  IllegalStateException if a storage-related error occurred.
+     */
+    @Override
+    public void updateIDGenerator(String csid, String serializedGenerator)
+            throws DocumentNotFoundException, BadRequestException,
+            IllegalStateException {
+
+        logger.debug("> in updateIDGenerator(String, String)");
+
+        // @TODO: Add checks for authorization to perform this operation.
+
+        if (serializedGenerator == null || serializedGenerator.equals("")) {
+            throw new BadRequestException(
+                    "Could not understand or parse this representation of an ID generator.");
+        }
+
+        SettableIDGenerator generator;
+        try {
+            generator = IDGeneratorSerializer.deserialize(serializedGenerator);
+        } catch (IllegalArgumentException e) {
+            throw e;
+        }
+        String lastId = generator.getCurrentID();
+
+        Connection conn = null;
+        try {
+
+            conn = getJdbcConnection();
+            conn.setAutoCommit(false);
+            Statement stmt = conn.createStatement();
+
+            // Test whether this ID generator already exists in the database.
+            // Using a 'SELECT ... FOR UPDATE' statement will temporarily
+            // lock this row for updates from any other connection, until
+            // the UPDATE is committed, below.
+            ResultSet rs = stmt.executeQuery(
+                    "SELECT csid "
+                    + "FROM id_generators "
+                    + "WHERE csid='"
+                    + csid
+                    + "' FOR UPDATE");
+
+            boolean moreRows = rs.next();
+
+            boolean idGeneratorFound = true;
+            if (!moreRows) {
+                idGeneratorFound = false;
+            }
+
+            // If this ID generator was not found in the
+            // database, an update can't be performed.
+            // Close the connection and throw an exception.
+            if (!idGeneratorFound) {
+                conn.close();
+                throw new DocumentNotFoundException(
+                        "Error updating ID generator '" + csid
+                        + "': generator could not be found in the database.");
+            } // end if (idGeneratorFound)
+
+            // Otherwise, if this ID generator exists in the database,
+            // update its record.
+            final String SQL_STATEMENT_STRING =
+                    "UPDATE id_generators SET "
+                    + "id_generator_state = ?, "
+                    + "last_generated_id = ? "
+                    + "WHERE csid = ?";
+
+            PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
+            ps.setString(1, serializedGenerator);
+            ps.setString(2, lastId);
+            ps.setString(3, csid);
+
+            int rowsUpdated = ps.executeUpdate();
 
-       //////////////////////////////////////////////////////////////////////
-       /**
-       * Updates an existing ID generator in persistent storage.
-       *
-       * @param  csid     An identifier for an ID generator.
-       *
-       * @param  generator  An ID generator, reflecting its current state,
-       *                  including the values of its constituent parts.
-       *
-       * @throws  DocumentNotFoundException if the requested ID generator could
-       *          not be found.
-    *
-    * @throws  BadRequestException if the provided representation of an
-    *          ID generator instance is not in the correct format, contains
-    *          invalid values, or otherwise cannot be used.
-    *
-    * @throws  IllegalStateException if a storage-related error occurred.
-       */
-       public void updateIDGenerator(String csid, SettableIDGenerator generator)
-         throws BadRequestException, DocumentNotFoundException,
-      IllegalStateException {
-       
-               logger.debug("> in updateIDGenerator(String, SettableIDGenerator)");
-       
-               // @TODO: Add checks for authorization to perform this operation.
-       
-               if (generator == null) {
-                       throw new BadRequestException(
-                               "ID generator provided in update operation cannot be null.");
-               }
-               
-               String serializedGenerator = "";
-               try {
-                       serializedGenerator = IDGeneratorSerializer.serialize(generator);
-               } catch (BadRequestException e) {
-                       throw e;
-               }
-       
-               try {
-                       updateIDGenerator(csid, serializedGenerator);
-               } catch (DocumentNotFoundException e ) {
-                       throw e;
-               } catch (BadRequestException e ) {
-                       throw e;
-               } catch (IllegalStateException e ) {
-                       throw e;
-               }
-       
-       }
-       
-       //////////////////////////////////////////////////////////////////////
-       /**
-       * Updates an existing ID generator in persistent storage,
-       * from a serialization of the current state of that generator.
-       *
-       * The serialization method recognized by this method has implementation
-       * dependencies.  Currently, this method expects serialization via XStream's
-       * out-of-the-box serializer, without custom configuration.
-       *
-       * @param  csid  An identifier for an ID generator.
-       *
-       * @param  serializedGenerator
-       *           A serialized ID generator, reflecting its current state,
-       *           including the values of its constituent parts.
-       *
-       * @throws  DocumentNotFoundException if the requested ID generator could
-       *          not be found.
-    *
-    * @throws  BadRequestException if the provided representation of an
-    *          ID generator instance is not in the correct format, contains
-    *          invalid values, or otherwise cannot be used.
-    *
-    * @throws  IllegalStateException if a storage-related error occurred.
-       */
-       @Override
-       public void updateIDGenerator(String csid, String serializedGenerator)
-         throws DocumentNotFoundException, BadRequestException,
-      IllegalStateException {
-       
-               logger.debug("> in updateIDGenerator(String, String)");
-       
-               // @TODO: Add checks for authorization to perform this operation.
-               
-               if (serializedGenerator == null || serializedGenerator.equals("")) {
-                 throw new BadRequestException(
-                       "Could not understand or parse this representation of an ID generator.");
-               }
-       
-               Connection conn = null;
-               try {
-               
-                       conn = getJdbcConnection();
-                       Statement stmt = conn.createStatement();
-               
-                       // Test whether this ID generator already exists in the database.
-                       ResultSet rs = stmt.executeQuery(
-                               "SELECT csid FROM id_generators " +
-                               "WHERE csid='" +
-                               csid + "'");
-                                 
-                       boolean moreRows = rs.next();
-                               
-                       boolean idGeneratorFound = true;
-                       if (! moreRows) {
-                               idGeneratorFound = false;
-                       }
-                               
-                       // If this ID generator already exists in the database,
-                       // update its record.
-                       if (idGeneratorFound) {
-       
-                       final String SQL_STATEMENT_STRING =
-                                 "UPDATE id_generators SET " + 
-                                  "id_generator_state = ?, " + 
-                                  "last_generated_id = ? " + 
-                                 "WHERE csid = ?";
-                                 
-                               SettableIDGenerator generator;
-                               try {
-                                       generator = IDGeneratorSerializer.deserialize(serializedGenerator);
-                               } catch (IllegalArgumentException e) {
-                                       throw e;
-                               }
-                               String lastId = generator.getCurrentID();
-                                       
-                               PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
-                               ps.setString(1, serializedGenerator);
-                               ps.setString(2, lastId);
-                               ps.setString(3, csid);
-                                               
-                               int rowsUpdated = ps.executeUpdate();
-                               if (rowsUpdated != 1) {
-                                       throw new IllegalStateException(
-                                               "Error updating ID generator '" + csid +
-                                               "'" + " in the database.");
-                               }
-                               
-                       // Otherwise, throw an exception, which indicates that the requested
-                       // ID generator was not found.
-                       } else {
-                               throw new DocumentNotFoundException(
-                                 "Error updating ID generator '" + csid +
-                                 "': generator could not be found in the database.");
-                       } // end if (idGeneratorFound)
-               
-                       logger.debug("> successfully updated ID Generator: " + csid);
-               
-               } catch (SQLException e) {
-                       throw new IllegalStateException(
-                               "Error updating ID generator in the database: " + e.getMessage());
-               } finally {
-                       try {
-                               if (conn != null) {
-                                       conn.close();
-                               }
-                       } catch(SQLException e) {
-                               // Do nothing here
-                       }
-               }
-       
-       }
-       
-       //////////////////////////////////////////////////////////////////////
-       /**
-       * Deletes an existing ID generator from persistent storage.
-       *
-       * @param  csid     An identifier for an ID generator.
-       *
-       * @throws  DocumentNotFoundException if the requested ID generator could
-       *          not be found.
-    *
-       * @throws  IllegalStateException if a storage-related error occurred.
-       */
-       public void deleteIDGenerator(String csid)
-         throws DocumentNotFoundException, IllegalStateException {
-       
-               logger.debug("> in deleteIDGenerator");
-               
-               // @TODO: Add checks for authorization to perform this operation.
-               
-               Connection conn = null;
-               try {
-               
-                       conn = getJdbcConnection();
-                       Statement stmt = conn.createStatement();
-                       
-                       // Test whether this ID generator already exists in the database.
-                       ResultSet rs = stmt.executeQuery(
-                         "SELECT csid FROM id_generators " +
-                         "WHERE csid='" +
-                         csid + "'");
-                       boolean moreRows = rs.next();
-                       
-                       boolean idGeneratorFound = true;
-                       if (! moreRows) {
-                               idGeneratorFound = false;
-                       }
-                       
-                       // If this ID generator already exists in the database,
-                       // update its record.
-                       if (idGeneratorFound) {
-               
-                          final String SQL_STATEMENT_STRING =
-                              "DELETE FROM id_generators WHERE csid = ?";
-                               
-                               PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
-                               ps.setString(1, csid);
-                                               
-                               int rowsUpdated = ps.executeUpdate();
-                               if (rowsUpdated != 1) {
-                               throw new IllegalStateException(
-                                       "Error deleting ID generator '" + csid +
-                                       "'" + " in the database.");
-                               }
-               
-                       // Otherwise, throw an exception, which indicates that the requested
-                       // ID generator was not found.
-                       } else {
-                               throw new DocumentNotFoundException(
-                                 "Error deleting ID generator '" + csid +
-                                 "': generator could not be found in the database.");
-                       } // end if (idGeneratorFound)
-               
-                       logger.debug("> successfully deleted ID generator: " + csid);
-               
-               } catch (SQLException e) {
-                       throw new IllegalStateException(
-                               "Error deleting ID generator in database: " + e.getMessage());
-               } finally {
-                       try {
-                               if (conn != null) {
-                                       conn.close();
-                               }
-                       } catch(SQLException e) {
-                               // Do nothing here
-                       }
-               }
-       
-       }
-       
-       // -------------------
+            if (rowsUpdated != 1) {
+                throw new IllegalStateException(
+                        "Error updating ID generator '" + csid
+                        + "'" + " in the database.");
+            }
+
+            conn.commit();
+            conn.close();
+
+            logger.debug("Successfully updated ID Generator: " + csid);
+
+        } catch (IllegalStateException ise) {
+            throw ise;
+        } catch (SQLException e) {
+            throw new IllegalStateException(
+                    "Error updating ID generator in the database: " + e.getMessage());
+        } finally {
+            try {
+                if (conn != null) {
+                    conn.close();
+                }
+            } catch (SQLException e) {
+                // Do nothing here
+            }
+        }
+
+    }
+
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Deletes an existing ID generator from persistent storage.
+     *
+     * @param  csid     An identifier for an ID generator.
+     *
+     * @throws  DocumentNotFoundException if the requested ID generator could
+     *          not be found.
+     *
+     * @throws  IllegalStateException if a storage-related error occurred.
+     */
+    public void deleteIDGenerator(String csid)
+            throws DocumentNotFoundException, IllegalStateException {
+
+        logger.debug("> in deleteIDGenerator");
+
+        // @TODO: Add checks for authorization to perform this operation.
+
+        Connection conn = null;
+        try {
+
+            conn = getJdbcConnection();
+            Statement stmt = conn.createStatement();
+
+            // Test whether this ID generator already exists in the database.
+            ResultSet rs = stmt.executeQuery(
+                    "SELECT csid FROM id_generators "
+                    + "WHERE csid='"
+                    + csid + "'");
+            boolean moreRows = rs.next();
+
+            boolean idGeneratorFound = true;
+            if (!moreRows) {
+                idGeneratorFound = false;
+            }
+
+            // If this ID generator already exists in the database,
+            // update its record.
+            if (idGeneratorFound) {
+
+                final String SQL_STATEMENT_STRING =
+                        "DELETE FROM id_generators WHERE csid = ?";
+
+                PreparedStatement ps = conn.prepareStatement(SQL_STATEMENT_STRING);
+                ps.setString(1, csid);
+
+                int rowsUpdated = ps.executeUpdate();
+                if (rowsUpdated != 1) {
+                    throw new IllegalStateException(
+                            "Error deleting ID generator '" + csid
+                            + "'" + " in the database.");
+                }
+
+                // Otherwise, throw an exception, which indicates that the requested
+                // ID generator was not found.
+            } else {
+                throw new DocumentNotFoundException(
+                        "Error deleting ID generator '" + csid
+                        + "': generator could not be found in the database.");
+            } // end if (idGeneratorFound)
+
+            logger.debug("Successfully deleted ID generator: " + csid);
+
+        } catch (IllegalStateException ise) {
+            throw ise;
+        } catch (SQLException e) {
+            throw new IllegalStateException(
+                    "Error deleting ID generator in database: " + e.getMessage());
+        } finally {
+            try {
+                if (conn != null) {
+                    conn.close();
+                }
+            } catch (SQLException e) {
+                // Do nothing here
+            }
+        }
+
+    }
+
+    // -------------------
     // Database operations
     // -------------------
-    
-   //////////////////////////////////////////////////////////////////////
-   /**
-       * Creates a new instance of the specified JDBC driver class.
-       *
-       * @param   jdbcDriverClassname  The name of a JDBC driver class.
-       *
-       * @throws  IllegalStateException if a new instance of the specified
-       *          JDBC driver class cannot be created.
-       */
-       public void instantiateJdbcDriver(String jdbcDriverClassname)
-       throws IllegalStateException {
-       
-               logger.debug("> in instantiateJdbcDriver(String)");
-       
-               try {
-                       Class.forName(jdbcDriverClassname).newInstance();
-               } catch (ClassNotFoundException e) {
-                       throw new IllegalStateException(
-                               "Error finding JDBC driver class '" +
-                               JDBC_DRIVER_CLASSNAME +
-                               "' to set up database connection.");
-               } catch (InstantiationException e) {
-                       throw new IllegalStateException(
-                               "Error instantiating JDBC driver class '" +
-                               JDBC_DRIVER_CLASSNAME +
-                               "' to set up database connection.");
-               } catch (IllegalAccessException e) {
-                       throw new IllegalStateException(
-                               "Error accessing JDBC driver class '" +
-                               JDBC_DRIVER_CLASSNAME +
-                               "' to set up database connection.");
-               }
-         
-       }
-
-       //////////////////////////////////////////////////////////////////////
-       /**
-       * Opens a connection to the database and returns a JDBC Connection object.
-       *
-       * @return  A JDBC database Connection object.
-       *
-       * @throws  SQLException if a storage-related error occurred.
-       */
-       public Connection getJdbcConnection() throws SQLException {
-       
-               logger.debug("> in getJdbcConnection");
-               
-               Connection conn = null;
-               try {
-                       conn = DriverManager.getConnection(DATABASE_URL,
-                           DATABASE_USERNAME, DATABASE_PASSWORD);
-               } catch (SQLException e) {
-                       throw e;
-               }
-               return conn;
-       
-       }
-               
-   //////////////////////////////////////////////////////////////////////
-   /**
-       * Identifies whether a specified table exists in the database.
-       *
-       * @param   tablename  The name of a database table.
-       *
-       * @return  True if the specified table exists in the database;
-       *          false if the specified table does not exist in the database.
-       *
-       * @throws  IllegalStateException if an error occurs while checking for the
-       *          existence of the specified table.
-       */
-       public boolean hasTable(String tablename) throws IllegalStateException {
-       
-               logger.debug("> in hasTable");
-       
-               if (tablename == null || tablename.equals("")) {
-                       return false;
-               }
-         
-               Connection conn = null;
-               try {
-               
-                       conn = getJdbcConnection();
-                       
-                       // Retrieve a list of tables in the current database. 
-                       final String CATALOG_NAME = null;
-                       final String SCHEMA_NAME_PATTERN = null;
-                       final String[] TABLE_TYPES = null;
-                       ResultSet tablesMatchingTableName =
-                               conn.getMetaData().getTables(
-                                       CATALOG_NAME, SCHEMA_NAME_PATTERN, tablename, TABLE_TYPES);
-               
-                       // Check whether a table with the specified name is in that list. 
-                       boolean moreRows = tablesMatchingTableName.next();
-                       if (! moreRows) {
-                               return false;
-                       } else {
-                               return true;
-                       }
-               
-               } catch (SQLException e) {
-                       throw new IllegalStateException(
-                               "Error while checking for existence of database table: " +
-                               e.getMessage());
-               } finally {
-                       try {
-                               if (conn != null) {
-                                       conn.close();
-                               }
-                       } catch(SQLException e) {
-                               // Do nothing here
-                       }
-               }
-       
-       }
-
-}
\ No newline at end of file
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Creates a new instance of the specified JDBC driver class.
+     *
+     * @param   jdbcDriverClassname  The name of a JDBC driver class.
+     *
+     * @throws  IllegalStateException if a new instance of the specified
+     *          JDBC driver class cannot be created.
+     */
+    public void instantiateJdbcDriver(String jdbcDriverClassname)
+            throws IllegalStateException {
+
+        logger.debug("> in instantiateJdbcDriver(String)");
+
+        try {
+            Class.forName(jdbcDriverClassname).newInstance();
+        } catch (ClassNotFoundException e) {
+            throw new IllegalStateException(
+                    "Error finding JDBC driver class '"
+                    + JDBC_DRIVER_CLASSNAME
+                    + "' to set up database connection.");
+        } catch (InstantiationException e) {
+            throw new IllegalStateException(
+                    "Error instantiating JDBC driver class '"
+                    + JDBC_DRIVER_CLASSNAME
+                    + "' to set up database connection.");
+        } catch (IllegalAccessException e) {
+            throw new IllegalStateException(
+                    "Error accessing JDBC driver class '"
+                    + JDBC_DRIVER_CLASSNAME
+                    + "' to set up database connection.");
+        }
+
+        jdbcDriverInstantiated = true;
+
+    }
+
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Opens a connection to the database and returns a JDBC Connection object.
+     *
+     * @return  A JDBC database Connection object.
+     *
+     * @throws  SQLException if a storage-related error occurred.
+     *
+     * @throws IllegalStateException if the attempt to instantiate the
+     *     JDBC driver fails.
+     */
+    public Connection getJdbcConnection() throws SQLException {
+
+        logger.debug("> in getJdbcConnection");
+
+        if (! jdbcDriverInstantiated) {
+            try {
+                instantiateJdbcDriver(JDBC_DRIVER_CLASSNAME);
+            } catch (IllegalStateException e) {
+                throw e;
+            }
+        }
+
+        Connection conn = null;
+        try {
+            conn = DriverManager.getConnection(DATABASE_URL,
+                    DATABASE_USERNAME, DATABASE_PASSWORD);
+        } catch (SQLException e) {
+            throw e;
+        }
+        return conn;
+
+    }
+
+    //////////////////////////////////////////////////////////////////////
+    /**
+     * Identifies whether a specified table exists in the database.
+     *
+     * @param   tablename  The name of a database table.
+     *
+     * @return  True if the specified table exists in the database;
+     *          false if the specified table does not exist in the database.
+     *
+     * @throws  IllegalStateException if an error occurs while checking for the
+     *          existence of the specified table.
+     */
+    public boolean hasTable(String tablename) throws IllegalStateException {
+
+        logger.debug("> in hasTable");
+
+        if (tablename == null || tablename.equals("")) {
+            return false;
+        }
+
+        Connection conn = null;
+        try {
+
+            conn = getJdbcConnection();
+
+            // Retrieve a list of tables in the current database.
+            final String CATALOG_NAME = null;
+            final String SCHEMA_NAME_PATTERN = null;
+            final String[] TABLE_TYPES = null;
+            ResultSet tablesMatchingTableName =
+                    conn.getMetaData().getTables(
+                    CATALOG_NAME, SCHEMA_NAME_PATTERN, tablename, TABLE_TYPES);
+
+            // Check whether a table with the specified name is in that list.
+            boolean moreRows = tablesMatchingTableName.next();
+            if (!moreRows) {
+                return false;
+            } else {
+                return true;
+            }
+
+        } catch (IllegalStateException ise) {
+            throw ise;
+        } catch (SQLException e) {
+            throw new IllegalStateException(
+                    "Error while checking for existence of database table: "
+                    + e.getMessage());
+        } finally {
+            try {
+                if (conn != null) {
+                    conn.close();
+                }
+            } catch (SQLException e) {
+                // Do nothing here
+            }
+        }
+
+    }
+}