From b6c7c5bee02b720ab784093f898cca2230ea25c3 Mon Sep 17 00:00:00 2001 From: Aron Roberts Date: Thu, 17 Sep 2009 03:19:21 +0000 Subject: [PATCH] CSPACE-448: ID Service returns 404, not 400, when an ID Generator is not found. Currently uses DocumentNotFoundException in common module; this may need to be re-thought. --- .../services/id/IDResource.java | 180 +++++++-- .../services/id/IDService.java | 17 +- .../services/id/IDServiceJdbcImpl.java | 381 ++++++++++-------- .../id/test/IDServiceJdbcImplTest.java | 57 +-- 4 files changed, 405 insertions(+), 230 deletions(-) diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/IDResource.java b/services/id/service/src/main/java/org/collectionspace/services/id/IDResource.java index 90932fbf0..968e3be8c 100644 --- a/services/id/service/src/main/java/org/collectionspace/services/id/IDResource.java +++ b/services/id/service/src/main/java/org/collectionspace/services/id/IDResource.java @@ -23,6 +23,9 @@ package org.collectionspace.services.id; +import java.util.Collections; +import java.util.List; + import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -34,6 +37,10 @@ import javax.ws.rs.core.Response; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; +// May at some point instead use +// org.jboss.resteasy.spi.NotFoundException +import org.collectionspace.services.common.repository.DocumentNotFoundException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,36 +71,13 @@ public class IDResource { // do nothing } - - ////////////////////////////////////////////////////////////////////// - /** - * Placeholder for retrieving list of available ID Generators. - * Currently returns an empty entity body. - * - * Implemented to facilitate a HEAD method test in ServicesTest - * - * @return An empty entity body (for now). - */ - @GET - @Path("") - public Response getIDGenerators() { - - logger.debug("> in getIDGenerators()"); - - // @TODO Replace this placeholder code. - Response response = Response.status(Response.Status.NO_CONTENT) - .entity("").type(MediaType.TEXT_PLAIN).build(); - - return response; - } - ////////////////////////////////////////////////////////////////////// /** * Generates and returns a new ID, from the specified ID generator. * * @param csid An identifier for an ID generator. * - * @return A new ID from the specified ID generator. + * @return A new ID created ("generated") by the specified ID generator. */ @POST @Path("/{csid}/ids") @@ -131,7 +115,7 @@ public class IDResource { // Obtain a new ID from the specified ID generator, // and return it in the entity body of the response. - newId = service.newID(csid); + newId = service.createID(csid); if (newId == null || newId.equals("")) { response = Response.status(Response.Status.INTERNAL_SERVER_ERROR) @@ -144,13 +128,17 @@ public class IDResource { response = Response.status(Response.Status.OK) .entity(newId).type(MediaType.TEXT_PLAIN).build(); - // @TODO Return an XML-based error results format with the - // responses below. - - // @TODO An IllegalStateException often indicates an overflow - // of an IDPart. Consider whether returning a 400 Bad Request - // status code is still warranted, or whether returning some other - // status would be more appropriate. + // @TODO Return an XML-based error results format with the + // responses below. + + // @TODO An IllegalStateException often indicates an overflow + // of an IDPart. Consider whether returning a 400 Bad Request + // status code is still warranted, or whether returning some other + // status would be more appropriate. + + } catch (DocumentNotFoundException dnfe) { + response = Response.status(Response.Status.NOT_FOUND) + .entity(dnfe.getMessage()).type(MediaType.TEXT_PLAIN).build(); } catch (IllegalStateException ise) { response = Response.status(Response.Status.BAD_REQUEST) @@ -170,4 +158,132 @@ public class IDResource { } + ////////////////////////////////////////////////////////////////////// + /** + * Creates a new ID generator. + * + * @param generatorRepresentation A representation of an ID generator. + */ + @POST + @Path("") + @Consumes(MediaType.APPLICATION_XML) + public Response createIDGenerator() { + + logger.debug("> in createIDGenerator(String)"); + + // @TODO Implement this stubbed method + + // @TODO Replace this placeholder code. + Response response = Response.status(Response.Status.CREATED) + .entity("").type(MediaType.TEXT_PLAIN).build(); + +/* + // @TODO Replace this placeholder code. + // Return a URL for the newly-created resource in the + // Location header + String csid = "TEST-1"; + String url = "/idgenerators/" + csid; + List locationList = Collections.singletonList(url); + response.getMetadata() + .get("Location") + .putSingle("Location", locationList); +*/ + + return response; + + } + + ////////////////////////////////////////////////////////////////////// + /** + * Returns a representation of a single ID Generator resource. + * + * @param csid An identifier for an ID generator. + * + * @return A representation of an ID generator resource. + */ + @GET + @Path("/{csid}") + @Produces(MediaType.APPLICATION_XML) + public Response readIDGenerator(@PathParam("csid") String csid) { + + logger.debug("> in readIDGenerator(String)"); + +/* + // @TODO Replace this placeholder code. + Response response = Response.status(Response.Status.NO_CONTENT) + .entity("").type(MediaType.TEXT_PLAIN).build(); + + return response; +*/ + Response response = null; + response = response.ok().build(); + String resourceRepresentation = ""; + + try { + + resourceRepresentation = service.readIDGenerator(csid); + + if (resourceRepresentation == null || + resourceRepresentation.equals("")) { + response = Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("ID Service returned null or empty ID Generator") + .type(MediaType.TEXT_PLAIN) + .build(); + return response; + } + + response = Response.status(Response.Status.OK) + .entity(resourceRepresentation) + .type(MediaType.APPLICATION_XML) + .build(); + + // @TODO Return an XML-based error results format with the + // responses below. + + } catch (DocumentNotFoundException dnfe) { + response = Response.status(Response.Status.NOT_FOUND) + .entity(dnfe.getMessage()).type(MediaType.TEXT_PLAIN).build(); + + } catch (IllegalStateException ise) { + response = Response.status(Response.Status.BAD_REQUEST) + .entity(ise.getMessage()).type(MediaType.TEXT_PLAIN).build(); + + } catch (IllegalArgumentException iae) { + response = Response.status(Response.Status.BAD_REQUEST) + .entity(iae.getMessage()).type(MediaType.TEXT_PLAIN).build(); + + // This is guard code that should never be reached. + } catch (Exception e) { + response = Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity(e.getMessage()).type(MediaType.TEXT_PLAIN).build(); + } + + return response; + + } + + ////////////////////////////////////////////////////////////////////// + /** + * Placeholder for retrieving a list of available ID Generator resources. + * Currently returns an empty entity body. + * + * Implemented to facilitate a HEAD method test in ServiceLayerTest. + * + * @return An empty entity body (for now). + */ + @GET + @Path("") + @Produces(MediaType.APPLICATION_XML) + public Response readIDGeneratorsList() { + + logger.debug("> in readIDGeneratorsList()"); + + // @TODO Replace this placeholder code. + Response response = Response.status(Response.Status.NO_CONTENT) + .entity("").type(MediaType.TEXT_PLAIN).build(); + + return response; + } + + } diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/IDService.java b/services/id/service/src/main/java/org/collectionspace/services/id/IDService.java index c437d7c8d..783c85ce9 100644 --- a/services/id/service/src/main/java/org/collectionspace/services/id/IDService.java +++ b/services/id/service/src/main/java/org/collectionspace/services/id/IDService.java @@ -17,6 +17,11 @@ package org.collectionspace.services.id; +// May at some point instead use +// org.jboss.resteasy.spi.NotFoundException +import org.collectionspace.services.common.repository.DocumentNotFoundException; + + /** * IDService * @@ -37,11 +42,11 @@ public interface IDService { // Read single object // Generates and returns a new ID from the specified ID generator. - public String newID(String csid) - throws IllegalArgumentException, IllegalStateException; + public String createID(String csid) throws DocumentNotFoundException, + IllegalArgumentException, IllegalStateException; // Returns the last-generated ID associated with the specified ID generator. - public String getLastID(String csid) + public String readLastID(String csid) throws IllegalArgumentException, IllegalStateException; // Read a list of objects (aka read multiple) @@ -53,12 +58,12 @@ public interface IDService { // Create // Adds a new ID generator. - public void addIDGenerator(String csid, String serializedIDGenerator) + public void createIDGenerator(String csid, String serializedIDGenerator) throws IllegalArgumentException, IllegalStateException; // Read single object - public String getIDGenerator(String csid) - throws IllegalArgumentException, IllegalStateException; + public String readIDGenerator(String csid) throws DocumentNotFoundException, + IllegalArgumentException, IllegalStateException; // Read a list of objects (aka read multiple) diff --git a/services/id/service/src/main/java/org/collectionspace/services/id/IDServiceJdbcImpl.java b/services/id/service/src/main/java/org/collectionspace/services/id/IDServiceJdbcImpl.java index 68e07065f..2e7b1b5c6 100644 --- a/services/id/service/src/main/java/org/collectionspace/services/id/IDServiceJdbcImpl.java +++ b/services/id/service/src/main/java/org/collectionspace/services/id/IDServiceJdbcImpl.java @@ -29,7 +29,8 @@ // 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 Hibernate for JDBC for accessing database-managed persistence. +// better yet, substitute JPA or Hibernate for JDBC for accessing +// database-managed persistence. // @TODO Remove any hard-coded dependencies on MySQL. @@ -72,6 +73,7 @@ // - "save/read" (appears to be used by Hibernate), // - "persist/find" (used by JPA) // - or? +// For now have used CRUD-like names, consistent with other classes. package org.collectionspace.services.id; @@ -82,6 +84,10 @@ import java.sql.SQLException; import java.sql.PreparedStatement; import java.sql.Statement; +// May at some point instead use +// org.jboss.resteasy.spi.NotFoundException +import org.collectionspace.services.common.repository.DocumentNotFoundException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -161,98 +167,11 @@ public class IDServiceJdbcImpl implements IDService { } } + + // ----------------- + // Operations on IDs + // ----------------- - ////////////////////////////////////////////////////////////////////// - /** - * 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."); - } - - } - - ////////////////////////////////////////////////////////////////////// - /** - * 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 tablebase table: " + e.getMessage()); - } finally { - try { - if (conn != null) { - conn.close(); - } - } catch(SQLException e) { - // Do nothing here - } - } - - } - ////////////////////////////////////////////////////////////////////// /** * Generates and returns a new ID associated with a specified ID generator. @@ -269,10 +188,11 @@ public class IDServiceJdbcImpl implements IDService { * * @throws IllegalStateException if a storage-related error occurred. */ - public String newID(String csid) throws + @Override + public String createID(String csid) throws DocumentNotFoundException, IllegalArgumentException, IllegalStateException { - logger.debug("> in newID"); + logger.debug("> in createID"); // @TODO Where relevant, implement logic to check for ID availability, // after generating a candidate ID. @@ -283,13 +203,15 @@ public class IDServiceJdbcImpl implements IDService { String lastId = ""; if (csid == null || csid.equals("")) { - throw new IllegalArgumentException( + throw new DocumentNotFoundException( "Identifier for ID generator must not be null or empty."); } String serializedGenerator = ""; try { - serializedGenerator = getIDGenerator(csid); + serializedGenerator = readIDGenerator(csid); + } catch (DocumentNotFoundException e ) { + throw e; } catch (IllegalArgumentException e ) { throw e; } catch (IllegalStateException e ) { @@ -313,7 +235,7 @@ public class IDServiceJdbcImpl implements IDService { // Retrieve the last ID associated with this generator // from persistent storage. - lastId = getLastID(csid); + lastId = readLastID(csid); // If there was no last generated ID associated with this generator, // get a new ID. @@ -382,15 +304,15 @@ public class IDServiceJdbcImpl implements IDService { if (rowsUpdated != 1) { throw new IllegalStateException( - "Error updating last-generated ID in the database for ID generator '" + - csid + "'"); + "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()); + throw new IllegalStateException("Error updating last-generated " + + "ID in the database: " + e.getMessage()); } finally { try { if (conn != null) { @@ -416,10 +338,11 @@ public class IDServiceJdbcImpl implements IDService { * * @throws IllegalStateException if a storage-related error occurred. */ - public String getLastID(String csid) throws IllegalArgumentException, + @Override + public String readLastID(String csid) throws IllegalArgumentException, IllegalStateException { - logger.debug("> in getLastID"); + logger.debug("> in readLastID"); // @TODO Where relevant, implement logic to check for ID availability, // after generating a candidate ID. @@ -434,7 +357,8 @@ public class IDServiceJdbcImpl implements IDService { Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery( - "SELECT last_generated_id FROM id_generators WHERE id_generator_csid='" + csid + "'"); + "SELECT last_generated_id FROM id_generators " + + "WHERE id_generator_csid='" + csid + "'"); boolean moreRows = rs.next(); if (! moreRows) { @@ -448,8 +372,8 @@ public class IDServiceJdbcImpl implements IDService { rs.close(); } catch (SQLException e) { - throw new IllegalStateException("Error retrieving last ID from the database: " + - e.getMessage()); + throw new IllegalStateException("Error retrieving last ID " + + "from the database: " + e.getMessage()); } finally { try { if (conn != null) { @@ -465,6 +389,10 @@ public class IDServiceJdbcImpl implements IDService { return lastId; } + + // --------------------------- + // Operations on ID Generators + // --------------------------- ////////////////////////////////////////////////////////////////////// /** @@ -477,15 +405,16 @@ public class IDServiceJdbcImpl implements IDService { * * @throws IllegalStateException if a storage-related error occurred. */ - public void addIDGenerator(String csid, SettableIDGenerator generator) + public void createIDGenerator(String csid, SettableIDGenerator generator) throws IllegalArgumentException, IllegalStateException { - logger.debug("> in addIDGenerator(String, SettableIDGenerator)"); + logger.debug("> in createIDGenerator(String, SettableIDGenerator)"); // @TODO: Add checks for authorization to perform this operation. if (generator == null) { - throw new IllegalArgumentException("New ID generator to add cannot be null."); + throw new IllegalArgumentException("New ID generator " + + "to add cannot be null."); } String serializedGenerator = ""; @@ -496,7 +425,7 @@ public class IDServiceJdbcImpl implements IDService { } try { - addIDGenerator(csid, serializedGenerator); + createIDGenerator(csid, serializedGenerator); } catch (IllegalArgumentException e) { throw e; } catch (IllegalStateException e) { @@ -521,16 +450,18 @@ public class IDServiceJdbcImpl implements IDService { * * @throws IllegalStateException if a storage-related error occurred. */ - public void addIDGenerator(String csid, String serializedGenerator) + @Override + public void createIDGenerator(String csid, String serializedGenerator) throws IllegalArgumentException, IllegalStateException { - logger.debug("> in addIDGenerator(String, String)"); + logger.debug("> in createIDGenerator(String, String)"); // @TODO Add checks for authorization to perform this operation. if (serializedGenerator == null || serializedGenerator.equals("")) { throw new IllegalArgumentException( - "Could not understand or parse this representation of an ID generator."); + "Could not understand or parse this representation " + + "of an ID generator."); } Connection conn = null; @@ -541,10 +472,12 @@ public class IDServiceJdbcImpl implements IDService { // 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. + // @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 id_generator_csid FROM id_generators WHERE id_generator_csid='" + csid + "'"); + "SELECT id_generator_csid FROM id_generators " + + "WHERE id_generator_csid='" + csid + "'"); boolean moreRows = rs.next(); @@ -553,10 +486,12 @@ public class IDServiceJdbcImpl implements IDService { idGeneratorFound = false; } - // If this ID generator already exists in the database, throw an Exception. + // 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. + // @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 " + @@ -584,7 +519,8 @@ public class IDServiceJdbcImpl implements IDService { int rowsUpdated = ps.executeUpdate(); if (rowsUpdated != 1) { throw new IllegalStateException( - "Error adding new ID generator '" + csid + "'" + " to the database."); + "Error adding new ID generator '" + csid + + "'" + " to the database."); } } // end if (idGeneratorFound) @@ -592,8 +528,8 @@ public class IDServiceJdbcImpl implements IDService { logger.debug("> successfully added ID generator: " + csid); } catch (SQLException e) { - throw new IllegalStateException("Error adding new ID generator to the database: " + - e.getMessage()); + throw new IllegalStateException("Error adding new ID " + + "generator to the database: " + e.getMessage()); } finally { try { if (conn != null) { @@ -605,6 +541,70 @@ public class IDServiceJdbcImpl implements IDService { } } + + ////////////////////////////////////////////////////////////////////// + /** + * 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 IllegalArgumentException if the requested ID generator could + * not be found. + * + * @throws IllegalStateException if a storage-related error occurred. + */ + public String readIDGenerator (String csid) throws + DocumentNotFoundException, IllegalArgumentException, + IllegalStateException { + + logger.debug("> in readIDGenerator"); + + String serializedGenerator = null; + + Connection conn = null; + try { + + conn = getJdbcConnection(); + Statement stmt = conn.createStatement(); + + ResultSet rs = stmt.executeQuery( + "SELECT id_generator_state FROM id_generators " + + "WHERE id_generator_csid='" + csid + "'"); + + boolean moreRows = rs.next(); + if (! moreRows) { + throw new DocumentNotFoundException( + "ID generator with ID " + + "\'" + csid + "\'" + + " could not be found."); + } + + serializedGenerator = rs.getString(1); + + 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: " + serializedGenerator); + + return serializedGenerator; + + } ////////////////////////////////////////////////////////////////////// /** @@ -655,13 +655,15 @@ public class IDServiceJdbcImpl implements IDService { * 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 csid An identifier for an ID generator. * - * @param serializedGenerator A serialized ID generator, reflecting its current state, - * including the values of its constituent parts. + * @param serializedGenerator + * A serialized ID generator, reflecting its current state, + * including the values of its constituent parts. * * @throws IllegalStateException if a storage-related error occurred. */ + @Override public void updateIDGenerator(String csid, String serializedGenerator) throws IllegalArgumentException, IllegalStateException { @@ -682,7 +684,8 @@ public class IDServiceJdbcImpl implements IDService { // Test whether this ID generator already exists in the database. ResultSet rs = stmt.executeQuery( - "SELECT id_generator_csid FROM id_generators WHERE id_generator_csid='" + + "SELECT id_generator_csid FROM id_generators " + + "WHERE id_generator_csid='" + csid + "'"); boolean moreRows = rs.next(); @@ -692,7 +695,8 @@ public class IDServiceJdbcImpl implements IDService { idGeneratorFound = false; } - // If this ID generator already exists in the database, update its record. + // If this ID generator already exists in the database, + // update its record. if (idGeneratorFound) { final String SQL_STATEMENT_STRING = @@ -717,7 +721,8 @@ public class IDServiceJdbcImpl implements IDService { int rowsUpdated = ps.executeUpdate(); if (rowsUpdated != 1) { throw new IllegalStateException( - "Error updating ID generator '" + csid + "'" + " in the database."); + "Error updating ID generator '" + csid + + "'" + " in the database."); } // Otherwise, throw an exception, which indicates that the requested @@ -768,7 +773,8 @@ public class IDServiceJdbcImpl implements IDService { // Test whether this ID generator already exists in the database. ResultSet rs = stmt.executeQuery( - "SELECT id_generator_csid FROM id_generators WHERE id_generator_csid='" + + "SELECT id_generator_csid FROM id_generators " + + "WHERE id_generator_csid='" + csid + "'"); boolean moreRows = rs.next(); @@ -777,7 +783,8 @@ public class IDServiceJdbcImpl implements IDService { idGeneratorFound = false; } - // If this ID generator already exists in the database, update its record. + // If this ID generator already exists in the database, + // update its record. if (idGeneratorFound) { final String SQL_STATEMENT_STRING = @@ -789,7 +796,8 @@ public class IDServiceJdbcImpl implements IDService { int rowsUpdated = ps.executeUpdate(); if (rowsUpdated != 1) { throw new IllegalStateException( - "Error deleting ID generator '" + csid + "'" + " in the database."); + "Error deleting ID generator '" + csid + + "'" + " in the database."); } // Otherwise, throw an exception, which indicates that the requested @@ -817,6 +825,45 @@ public class IDServiceJdbcImpl implements IDService { } + // ------------------- + // 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. @@ -831,58 +878,60 @@ public class IDServiceJdbcImpl implements IDService { Connection conn = null; try { - conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD); + conn = DriverManager.getConnection(DATABASE_URL, + DATABASE_USERNAME, DATABASE_PASSWORD); } catch (SQLException e) { throw e; } return conn; } - - ////////////////////////////////////////////////////////////////////// - /** - * Returns a requested ID generator from persistent storage. - * - * @param csid An identifier for an ID generator. + + ////////////////////////////////////////////////////////////////////// + /** + * Identifies whether a specified table exists in the database. * - * @return A serialized representation of the requested ID generator. + * @param tablename The name of a database table. * - * @throws IllegalArgumentException if the requested ID generator could not be found. + * @return True if the specified table exists in the database; + * false if the specified table does not exist in the database. * - * @throws IllegalStateException if a storage-related error occurred. + * @throws IllegalStateException if an error occurs while checking for the + * existence of the specified table. */ - public String getIDGenerator (String csid) throws IllegalArgumentException, IllegalStateException { + public boolean hasTable(String tablename) throws IllegalStateException { - logger.debug("> in getIDGenerator"); - - String serializedGenerator = null; - + logger.debug("> in hasTable"); + + if (tablename == null || tablename.equals("")) { + return false; + } + Connection conn = null; try { conn = getJdbcConnection(); - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery( - "SELECT id_generator_state FROM id_generators WHERE id_generator_csid='" + csid + "'"); - - boolean moreRows = rs.next(); + // 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) { - throw new IllegalArgumentException( - "ID generator with ID " + - "\'" + csid + "\'" + - " could not be found."); + return false; + } else { + return true; } - serializedGenerator = rs.getString(1); - - rs.close(); - } catch (SQLException e) { throw new IllegalStateException( - "Error retrieving ID generator " + - "\'" + csid + "\'" + - " from database: " + e.getMessage()); + "Error while checking for existence of tablebase table: " + + e.getMessage()); } finally { try { if (conn != null) { @@ -892,11 +941,7 @@ public class IDServiceJdbcImpl implements IDService { // Do nothing here } } - - logger.debug("> retrieved SettableIDGenerator: " + serializedGenerator); - - return serializedGenerator; - } - } + +} \ No newline at end of file diff --git a/services/id/service/src/test/java/org/collectionspace/services/id/test/IDServiceJdbcImplTest.java b/services/id/service/src/test/java/org/collectionspace/services/id/test/IDServiceJdbcImplTest.java index aa9cf422f..adf4d1384 100644 --- a/services/id/service/src/test/java/org/collectionspace/services/id/test/IDServiceJdbcImplTest.java +++ b/services/id/service/src/test/java/org/collectionspace/services/id/test/IDServiceJdbcImplTest.java @@ -23,6 +23,10 @@ package org.collectionspace.services.id.test; +// May at some point instead use +// org.jboss.resteasy.spi.NotFoundException +import org.collectionspace.services.common.repository.DocumentNotFoundException; + import org.collectionspace.services.id.*; import org.testng.Assert; @@ -63,55 +67,59 @@ public class IDServiceJdbcImplTest { } @Test(dependsOnMethods = {"hasRequiredDatabaseTable"}) - public void addIDGenerator() { + public void createIDGenerator() throws DocumentNotFoundException, + IllegalArgumentException, IllegalStateException { try { jdbc.deleteIDGenerator(DEFAULT_CSID); } catch (Exception e) { // Fail silently; this is guard code. } - jdbc.addIDGenerator(DEFAULT_CSID, getSpectrumEntryNumberGenerator()); + jdbc.createIDGenerator(DEFAULT_CSID, getSpectrumEntryNumberGenerator()); } - @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "addIDGenerator"}) - public void readIDGenerator() { + @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "createIDGenerator"}) + public void readIDGenerator() throws DocumentNotFoundException, + IllegalArgumentException, IllegalStateException { - serializedGenerator = jdbc.getIDGenerator(DEFAULT_CSID); + serializedGenerator = jdbc.readIDGenerator(DEFAULT_CSID); generator = IDGeneratorSerializer.deserialize(serializedGenerator); Assert.assertEquals(generator.getCsid(), DEFAULT_CSID); } - @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "addIDGenerator", + @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "createIDGenerator", "readIDGenerator"}) - public void updateIDGenerator() { + public void updateIDGenerator() throws DocumentNotFoundException, + IllegalArgumentException, IllegalStateException { final String NEW_DESCRIPTION = "new description"; // Retrieve an existing generator, deserialize it, // update its contents, serialize it, and write it back. - serializedGenerator = jdbc.getIDGenerator(DEFAULT_CSID); + serializedGenerator = jdbc.readIDGenerator(DEFAULT_CSID); generator = IDGeneratorSerializer.deserialize(serializedGenerator); generator.setDescription(NEW_DESCRIPTION); serializedGenerator = IDGeneratorSerializer.serialize(generator); jdbc.updateIDGenerator(DEFAULT_CSID, serializedGenerator); - serializedGenerator = jdbc.getIDGenerator(DEFAULT_CSID); + serializedGenerator = jdbc.readIDGenerator(DEFAULT_CSID); generator = IDGeneratorSerializer.deserialize(serializedGenerator); Assert.assertEquals(generator.getDescription(), NEW_DESCRIPTION); } - @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "addIDGenerator", + @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "createIDGenerator", "readIDGenerator", "updateIDGenerator"}) public void deleteIDGenerator() { jdbc.deleteIDGenerator(DEFAULT_CSID); } - @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "addIDGenerator", + @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "createIDGenerator", "readIDGenerator", "updateIDGenerator", "deleteIDGenerator"}) - public void newID() { + public void createID() throws DocumentNotFoundException, + IllegalArgumentException, IllegalStateException { try { jdbc.deleteIDGenerator(DEFAULT_CSID); @@ -121,11 +129,11 @@ public class IDServiceJdbcImplTest { // exists in the database. } - jdbc.addIDGenerator(DEFAULT_CSID, getSpectrumEntryNumberGenerator()); + jdbc.createIDGenerator(DEFAULT_CSID, getSpectrumEntryNumberGenerator()); - Assert.assertEquals(service.newID(DEFAULT_CSID), "E1"); - Assert.assertEquals(service.newID(DEFAULT_CSID), "E2"); - Assert.assertEquals(service.newID(DEFAULT_CSID), "E3"); + Assert.assertEquals(service.createID(DEFAULT_CSID), "E1"); + Assert.assertEquals(service.createID(DEFAULT_CSID), "E2"); + Assert.assertEquals(service.createID(DEFAULT_CSID), "E3"); try { jdbc.deleteIDGenerator(DEFAULT_CSID); @@ -133,11 +141,11 @@ public class IDServiceJdbcImplTest { Assert.fail("Could not delete ID generator '" + DEFAULT_CSID + "'."); } - jdbc.addIDGenerator(DEFAULT_CSID, getChinAccessionNumberGenerator()); + jdbc.createIDGenerator(DEFAULT_CSID, getChinAccessionNumberGenerator()); - Assert.assertEquals(service.newID(DEFAULT_CSID), CURRENT_YEAR + ".1.1"); - Assert.assertEquals(service.newID(DEFAULT_CSID), CURRENT_YEAR + ".1.2"); - Assert.assertEquals(service.newID(DEFAULT_CSID), CURRENT_YEAR + ".1.3"); + Assert.assertEquals(service.createID(DEFAULT_CSID), CURRENT_YEAR + ".1.1"); + Assert.assertEquals(service.createID(DEFAULT_CSID), CURRENT_YEAR + ".1.2"); + Assert.assertEquals(service.createID(DEFAULT_CSID), CURRENT_YEAR + ".1.3"); try { jdbc.deleteIDGenerator(DEFAULT_CSID); @@ -152,10 +160,11 @@ public class IDServiceJdbcImplTest { // 1. The ID Service is running and accessible to this test; and // 2. There is no ID generator retrievable through that service // with the identifier 'non-existent identifier'. - @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "newID"}, - expectedExceptions = IllegalArgumentException.class) - public void newIDNonExistentGenerator() { - nextId = service.newID("non-existent identifier"); + @Test(dependsOnMethods = {"hasRequiredDatabaseTable", "createID"}, + expectedExceptions = DocumentNotFoundException.class) + public void createIDNonExistentGenerator() throws DocumentNotFoundException, + IllegalArgumentException, IllegalStateException { + nextId = service.createID("non-existent identifier"); } // --------------------------------------------------------------- -- 2.47.3