Index: src/edu/ucsb/nceas/metacat/restservice/CNResourceHandler.java
===================================================================
--- src/edu/ucsb/nceas/metacat/restservice/CNResourceHandler.java	(revision 6868)
+++ src/edu/ucsb/nceas/metacat/restservice/CNResourceHandler.java	(revision 6869)
@@ -54,6 +54,7 @@
 import org.dataone.service.exceptions.NotImplemented;
 import org.dataone.service.exceptions.ServiceFailure;
 import org.dataone.service.exceptions.UnsupportedType;
+import org.dataone.service.exceptions.VersionMismatch;
 import org.dataone.service.types.v1.AccessPolicy;
 import org.dataone.service.types.v1.Checksum;
 import org.dataone.service.types.v1.ChecksumAlgorithmList;
@@ -884,11 +885,12 @@
      * @throws IOException
      * @throws IllegalAccessException
      * @throws InstantiationException
+     * @throws VersionMismatch 
      */
     private void owner(String id) throws JiBXException, InvalidToken,
             ServiceFailure, NotFound, NotAuthorized, NotImplemented,
             InvalidRequest, IOException, InstantiationException,
-            IllegalAccessException {
+            IllegalAccessException, VersionMismatch {
 
         Identifier pid = new Identifier();
         pid.setValue(id);
@@ -999,11 +1001,12 @@
      * @throws IOException
      * @throws SAXException
      * @throws ParserConfigurationException
+     * @throws VersionMismatch 
      */
     protected void setAccess(String pid) throws JiBXException, InvalidToken,
             ServiceFailure, NotFound, NotAuthorized, NotImplemented,
             InvalidRequest, IOException, InstantiationException,
-            IllegalAccessException, ParserConfigurationException, SAXException {
+            IllegalAccessException, ParserConfigurationException, SAXException, VersionMismatch {
 
         long serialVersion = 0L;
         String serialVersionStr = null;
@@ -1181,11 +1184,12 @@
      * @throws InstantiationException
      * @throws IllegalAccessException
      * @throws JiBXException
+     * @throws VersionMismatch 
      */
     public boolean setReplicationPolicy(String pid) throws NotImplemented,
             NotFound, NotAuthorized, ServiceFailure, InvalidRequest,
             InvalidToken, IOException, InstantiationException,
-            IllegalAccessException, JiBXException {
+            IllegalAccessException, JiBXException, VersionMismatch {
 
         boolean result = false;
         ReplicationPolicy policy = null;
@@ -1340,10 +1344,11 @@
      * @throws NotAuthorized
      * @throws InvalidRequest
      * @throws NotFound
+     * @throws VersionMismatch 
      */
     public boolean updateReplicationMetadata(String pid) throws ServiceFailure,
             NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
-            NotFound {
+            NotFound, VersionMismatch {
 
         boolean result = false;
         long serialVersion = 0L;
Index: src/edu/ucsb/nceas/metacat/dataone/CNodeService.java
===================================================================
--- src/edu/ucsb/nceas/metacat/dataone/CNodeService.java	(revision 6868)
+++ src/edu/ucsb/nceas/metacat/dataone/CNodeService.java	(revision 6869)
@@ -51,6 +51,7 @@
 import org.dataone.service.exceptions.NotImplemented;
 import org.dataone.service.exceptions.ServiceFailure;
 import org.dataone.service.exceptions.UnsupportedType;
+import org.dataone.service.exceptions.VersionMismatch;
 import org.dataone.service.types.v1.AccessPolicy;
 import org.dataone.service.types.v1.Checksum;
 import org.dataone.service.types.v1.ChecksumAlgorithmList;
@@ -118,6 +119,7 @@
    * @throws NotAuthorized
    * @throws ServiceFailure
    * @throws InvalidRequest
+   * @throws VersionMismatch
    * 
    */
   @Override
@@ -124,7 +126,7 @@
   public boolean setReplicationPolicy(Session session, Identifier pid,
       ReplicationPolicy policy, long serialVersion) 
       throws NotImplemented, NotFound, NotAuthorized, ServiceFailure, 
-      InvalidRequest, InvalidToken {
+      InvalidRequest, InvalidToken, VersionMismatch {
       
       // The lock to be used for this identifier
       Lock lock = null;
@@ -134,13 +136,15 @@
       
       // are we allowed to do this?
       if (!isAdminAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
-        if (!isAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
-            throw new NotAuthorized("4881", Permission.CHANGE_PERMISSION
-                    + " not allowed by " + subject.getValue() + " on "
-                    + pid.getValue());
-        }
-    }
-    SystemMetadata systemMetadata = null;
+          if (!isAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
+              throw new NotAuthorized("4881", Permission.CHANGE_PERMISSION
+                      + " not allowed by " + subject.getValue() + " on "
+                      + pid.getValue());
+              
+          }
+      }
+      
+      SystemMetadata systemMetadata = null;
       try {
           lock = HazelcastService.getInstance().getLock(pid.getValue());
           lock.lock();
@@ -151,7 +155,12 @@
                   systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
                   
               }
-            
+              
+              // did we get it correctly?
+              if ( systemMetadata == null ) {
+                  throw new NotFound("4884", "Couldn't find an object identified by " + pid.getValue());
+                  
+              }
 
               // does the request have the most current system metadata?
               if ( systemMetadata.getSerialVersion().longValue() != serialVersion ) {
@@ -159,10 +168,11 @@
                      serialVersion + " differs from the current version at " +
                      systemMetadata.getSerialVersion().longValue() +
                      ". Please get the latest copy in order to modify it.";
-                 throw new InvalidRequest("4883", msg);
+                 throw new VersionMismatch("4886", msg);
+                 
               }
               
-          } catch (Exception e) { // Catch is generic since HZ throws RuntimeException
+          } catch (RuntimeException e) { // Catch is generic since HZ throws RuntimeException
               throw new NotFound("4884", "No record found for: " + pid.getValue());
             
           }
@@ -176,19 +186,19 @@
               systemMetadata.setDateSysMetadataModified(Calendar.getInstance().getTime());
               HazelcastService.getInstance().getSystemMetadataMap().put(systemMetadata.getIdentifier(), systemMetadata);
             
-          } catch (Exception e) {
+          } catch (RuntimeException e) {
               throw new ServiceFailure("4882", e.getMessage());
           
           }
           
-    } catch (Exception e) {
-        throw new ServiceFailure("4882", e.getMessage());
-        
-    } finally {
-        lock.unlock();
-        logMetacat.debug("Unlocked identifier " + pid.getValue());
-        
-    }
+      } catch (RuntimeException e) {
+          throw new ServiceFailure("4882", e.getMessage());
+          
+      } finally {
+          lock.unlock();
+          logMetacat.debug("Unlocked identifier " + pid.getValue());
+          
+      }
     
       return true;
   }
@@ -237,8 +247,10 @@
           try {      
               systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
 
+              // did we get it correctly?
               if ( systemMetadata == null ) {
                   logMetacat.debug("systemMetadata is null for " + pid.getValue());
+                  throw new NotFound("4740", "Couldn't find an object identified by " + pid.getValue());
                   
               }
               replicas = systemMetadata.getReplicaList();
@@ -245,11 +257,40 @@
               int count = 0;
               
               if ( replicas == null || replicas.size() < 1 ) {
-                  logMetacat.debug("no replicas to evaluate");
-                  throw new InvalidRequest("4730", "There are no replicas to update.");
+                  logMetacat.debug("No replicas to evaluate for " + pid.getValue());
+                  Replica newReplica = new Replica();
+                  newReplica.setReplicaMemberNode(targetNode);
+                  newReplica.setReplicationStatus(status);
+                  newReplica.setReplicaVerified(Calendar.getInstance().getTime());
+                  try {
+                    // if there is no replica entry, create one
+                    updateReplicationMetadata(session, pid, newReplica, 
+                        systemMetadata.getSerialVersion().longValue());
+                    
+                  } catch (VersionMismatch e) {
+                      // try again if we somehow don't have the correct version
+                      String msg = "The serial version of the system metadata doesn't match. Trying again.";
+                      logMetacat.info(msg);
+                      systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
+                      try {
+                        updateReplicationMetadata(session, pid, newReplica, 
+                            systemMetadata.getSerialVersion().longValue());
+                        
+                      } catch (VersionMismatch e1) {
+                          throw new ServiceFailure("4700", 
+                              "Couldn't get the correct serial version of the system metadata: " +
+                              e1.getCause().getMessage());
+                          
+                      }
+
+                  }
                   
               }
-
+              
+              // refresh the system metadata and replica list
+              systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
+              replicas = systemMetadata.getReplicaList();
+                  
               // find the target replica index in the replica list
               for (Replica replica: replicas) {
                   String replicaNodeStr = replica.getReplicaMemberNode().getValue();
@@ -339,7 +380,7 @@
                       " on target node " + targetNode + ". The exception was: " +
                       failure.getMessage());
               }
-          } catch (Exception e) {
+          } catch (RuntimeException e) {
               throw new ServiceFailure("4700", e.getMessage());
           
           }
@@ -459,10 +500,7 @@
   public Checksum getChecksum(Session session, Identifier pid)
     throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
     NotImplemented {
-        
-    // The lock to be used for thyis identifier
-    Lock lock = null;
-    
+            
     if (!isAuthorized(session, pid, Permission.READ)) {
         throw new NotAuthorized("1400", Permission.READ + " not allowed on " + pid.getValue());  
     }
@@ -471,10 +509,14 @@
     Checksum checksum = null;
     
     try {
-        systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
+        systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);        
+
+        if (systemMetadata == null ) {
+            throw new NotFound("1420", "Couldn't find an object identified by " + pid.getValue());
+        }
         checksum = systemMetadata.getChecksum();
-
-    } catch (Exception e) {
+        
+    } catch (RuntimeException e) {
         throw new ServiceFailure("1410", "An error occurred getting the checksum for " + 
             pid.getValue() + ". The error message was: " + e.getMessage());
       
@@ -713,7 +755,7 @@
               sysmeta.setDateSysMetadataModified(Calendar.getInstance().getTime());
               HazelcastService.getInstance().getSystemMetadataMap().put(sysmeta.getIdentifier(), sysmeta);
               
-          } catch (Exception e) {
+          } catch (RuntimeException e) {
             logMetacat.error("Problem registering system metadata: " + pid.getValue(), e);
               throw new ServiceFailure("4862", "Error inserting system metadata: " + 
                   e.getClass() + ": " + e.getMessage());
@@ -720,7 +762,7 @@
               
           }
           
-      } catch (Exception e) {
+      } catch (RuntimeException e) {
           throw new ServiceFailure("4862", "Error inserting system metadata: " + 
                   e.getClass() + ": " + e.getMessage());
           
@@ -826,7 +868,7 @@
   public Identifier setRightsHolder(Session session, Identifier pid, Subject userId,
       long serialVersion)
       throws InvalidToken, ServiceFailure, NotFound, NotAuthorized,
-      NotImplemented, InvalidRequest {
+      NotImplemented, InvalidRequest, VersionMismatch {
       
       // The lock to be used for this identifier
       Lock lock = null;
@@ -836,12 +878,14 @@
       
       // are we allowed to do this?
       if (!isAdminAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
-        if (!isAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
-            throw new NotAuthorized("4440", "not allowed by "
-                    + subject.getValue() + " on " + pid.getValue());
-        }
-    }
-    SystemMetadata systemMetadata = null;
+          if (!isAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
+              throw new NotAuthorized("4440", "not allowed by "
+                      + subject.getValue() + " on " + pid.getValue());
+              
+          }
+      }
+      
+      SystemMetadata systemMetadata = null;
       try {
           lock = HazelcastService.getInstance().getLock(pid.getValue());
           logMetacat.debug("Locked identifier " + pid.getValue());
@@ -855,10 +899,10 @@
                      serialVersion + " differs from the current version at " +
                      systemMetadata.getSerialVersion().longValue() +
                      ". Please get the latest copy in order to modify it.";
-                 throw new InvalidRequest("4442", msg);
+                 throw new VersionMismatch("4443", msg);
               }
               
-          } catch (Exception e) { // Catch is generic since HZ throws RuntimeException
+          } catch (RuntimeException e) { // Catch is generic since HZ throws RuntimeException
               throw new NotFound("4460", "No record found for: " + pid.getValue());
               
           }
@@ -872,12 +916,12 @@
               systemMetadata.setDateSysMetadataModified(Calendar.getInstance().getTime());
               HazelcastService.getInstance().getSystemMetadataMap().put(pid, systemMetadata);
               
-          } catch (Exception e) {
-          throw new ServiceFailure("4490", e.getMessage());
+          } catch (RuntimeException e) {
+              throw new ServiceFailure("4490", e.getMessage());
           
           }
           
-      } catch (Exception e) {
+      } catch (RuntimeException e) {
           throw new ServiceFailure("4490", e.getMessage());
           
       } finally {
@@ -886,7 +930,7 @@
       
       }
       
-    return pid;
+      return pid;
   }
 
   /**
@@ -912,9 +956,6 @@
     Subject targetNodeSubject, Identifier pid) 
     throws NotImplemented, NotAuthorized, InvalidToken, ServiceFailure, 
     NotFound, InvalidRequest {
-
-    // The lock to be used for this identifier
-    Lock lock = null;
     
     boolean isAllowed = false;
     SystemMetadata sysmeta = null;
@@ -990,6 +1031,7 @@
       } else {
           logMetacat.debug("System metadata for identifier " + pid.getValue() +
           " is null.");          
+          throw new NotFound("4874", "Couldn't find an object identified by " + pid.getValue());
           
       }
 
@@ -1037,7 +1079,8 @@
       Lock lock = null;
       
       try {
-        // are we allowed?
+          lock = HazelcastService.getInstance().getLock(pid.getValue());
+          // are we allowed?
           boolean isAllowed = false;
           CNode cn = D1Client.getCN();
           NodeList nodeList = cn.listNodes();
@@ -1058,7 +1101,6 @@
           // proceed if we're called by a CN
           if ( isAllowed ) {
               // create the coordinating node version of the document      
-              lock = HazelcastService.getInstance().getLock(pid.getValue());
               lock.lock();
               logMetacat.debug("Locked identifier " + pid.getValue());
               sysmeta.setSerialVersion(BigInteger.ONE);
@@ -1108,10 +1150,11 @@
   public boolean setAccessPolicy(Session session, Identifier pid, 
       AccessPolicy accessPolicy, long serialVersion) 
       throws InvalidToken, ServiceFailure, NotFound, NotAuthorized, 
-      NotImplemented, InvalidRequest {
+      NotImplemented, InvalidRequest, VersionMismatch {
       
       // The lock to be used for this identifier
       Lock lock = null;
+      SystemMetadata systemMetadata = null;
       
       boolean success = false;
       
@@ -1118,13 +1161,14 @@
       // get the subject
       Subject subject = session.getSubject();
       
-      // are we allowed to do this?
-      if (!isAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
-          throw new NotAuthorized("4420", "not allowed by " + subject.getValue() + 
-          " on " + pid.getValue());  
+      if (!isAdminAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
+          // are we allowed to do this?
+          if (!isAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
+              throw new NotAuthorized("4420", "not allowed by "
+                      + subject.getValue() + " on " + pid.getValue());
+          }
       }
       
-      SystemMetadata systemMetadata = null;
       try {
           lock = HazelcastService.getInstance().getLock(pid.getValue());
           lock.lock();
@@ -1133,6 +1177,10 @@
           try {
               systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
 
+              if ( systemMetadata == null ) {
+                  throw new NotFound("4400", "Couldn't find an object identified by " + pid.getValue());
+                  
+              }
               // does the request have the most current system metadata?
               if ( systemMetadata.getSerialVersion().longValue() != serialVersion ) {
                  String msg = "The requested system metadata version number " + 
@@ -1139,10 +1187,11 @@
                      serialVersion + " differs from the current version at " +
                      systemMetadata.getSerialVersion().longValue() +
                      ". Please get the latest copy in order to modify it.";
-                 throw new InvalidRequest("4402", msg);
+                 throw new VersionMismatch("4402", msg);
+                 
               }
               
-          } catch (Exception e) {
+          } catch (RuntimeException e) {
               // convert Hazelcast RuntimeException to NotFound
               throw new NotFound("4400", "No record found for: " + pid);
             
@@ -1157,13 +1206,13 @@
               systemMetadata.setDateSysMetadataModified(Calendar.getInstance().getTime());
               HazelcastService.getInstance().getSystemMetadataMap().put(systemMetadata.getIdentifier(), systemMetadata);
             
-          } catch (Exception e) {
+          } catch (RuntimeException e) {
               // convert Hazelcast RuntimeException to ServiceFailure
               throw new ServiceFailure("4430", e.getMessage());
             
           }
           
-      } catch (Exception e) {
+      } catch (RuntimeException e) {
           throw new ServiceFailure("4430", e.getMessage());
           
       } finally {
@@ -1192,11 +1241,13 @@
    * @throws ServiceFailure
    * @throws InvalidRequest
    * @throws NotFound
+   * @throws VersionMismatch
    */
+  @Override
   public boolean updateReplicationMetadata(Session session, Identifier pid,
       Replica replica, long serialVersion) 
       throws NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest,
-      NotFound {
+      NotFound, VersionMismatch {
       
       // The lock to be used for this identifier
       Lock lock = null;
@@ -1235,12 +1286,12 @@
                      serialVersion + " differs from the current version at " +
                      systemMetadata.getSerialVersion().longValue() +
                      ". Please get the latest copy in order to modify it.";
-                 throw new InvalidRequest("4853", msg);
+                 throw new VersionMismatch("4855", msg);
               }
               
-          } catch (Exception e) { // Catch is generic since HZ throws RuntimeException
-            throw new NotFound("4854", "No record found for: " + pid.getValue() +
-                " : " + e.getMessage());
+          } catch (RuntimeException e) { // Catch is generic since HZ throws RuntimeException
+              throw new NotFound("4854", "No record found for: " + pid.getValue() +
+                  " : " + e.getMessage());
             
           }
               
@@ -1269,25 +1320,30 @@
               systemMetadata.setDateSysMetadataModified(Calendar.getInstance().getTime());
               HazelcastService.getInstance().getSystemMetadataMap().put(systemMetadata.getIdentifier(), systemMetadata);
             
-          } catch (Exception e) {
+          } catch (RuntimeException e) {
+              logMetacat.info("Unknown RuntimeException thrown: " + e.getCause().getMessage());
               throw new ServiceFailure("4852", e.getMessage());
           
           }
           
-    } catch (Exception e) {
-        throw new ServiceFailure("4852", e.getMessage());
-
-    } finally {
-        lock.unlock();
-        logMetacat.debug("Unlocked identifier " + pid.getValue());
-        
-    }
+      } catch (RuntimeException e) {
+          logMetacat.info("Unknown RuntimeException thrown: " + e.getCause().getMessage());
+          throw new ServiceFailure("4852", e.getMessage());
+      
+      } finally {
+          lock.unlock();
+          logMetacat.debug("Unlocked identifier " + pid.getValue());
+          
+      }
     
       return true;
       
   }
   
-    @Override
+  /**
+   * 
+   */
+  @Override
   public ObjectList listObjects(Session session, Date startTime, 
       Date endTime, ObjectFormatIdentifier formatid, Boolean replicaStatus,
       Integer start, Integer count)
@@ -1304,7 +1360,10 @@
         return objectList;
   }
 
-	@Override
+	/**
+	 * 
+	 */
+  @Override
 	public ChecksumAlgorithmList listChecksumAlgorithms()
 			throws ServiceFailure, NotImplemented {
 		ChecksumAlgorithmList cal = new ChecksumAlgorithmList();
