diff --git a/marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/fastfunctest/TestBug18920.java b/marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/fastfunctest/TestBug18920.java index 505f542e7..3b53cfa17 100644 --- a/marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/fastfunctest/TestBug18920.java +++ b/marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/fastfunctest/TestBug18920.java @@ -16,6 +16,7 @@ package com.marklogic.client.fastfunctest; +import com.marklogic.client.ContentNoVersionException; import com.marklogic.client.FailedRequestException; import com.marklogic.client.admin.ServerConfigurationManager; import com.marklogic.client.admin.ServerConfigurationManager.UpdatePolicy; @@ -29,6 +30,8 @@ import java.io.File; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; public class TestBug18920 extends AbstractFunctionalTest { @@ -81,23 +84,9 @@ public void testBug18920() { String docUri = desc.getUri(); System.out.println(docUri); - String exception = ""; - String statusCode = ""; - String expectedException = "com.marklogic.client.FailedRequestException: Local message: Content version required to write document. Server Message: RESTAPI-CONTENTNOVERSION: (err:FOER0000) No content version supplied: uri /bug18920/xml-original.xml"; - int expCode = 0; // update document with no content version - try { - docMgr.write(docUri, handle); - } catch (FailedRequestException e) { - exception = e.toString(); - statusCode = e.getFailedRequest().getMessageCode(); - expCode = e.getFailedRequest().getStatusCode(); - } - System.out.println("Exception is " + exception); - System.out.println("Status message --- codenumber are " + statusCode + " --- " + expCode); - assertTrue( statusCode.contains("RESTAPI-CONTENTNOVERSION")); - assertTrue( expCode == 428); - assertTrue( exception.contains(expectedException)); + ContentNoVersionException ex = assertThrows(ContentNoVersionException.class, () -> docMgr.write(docUri, handle)); + assertEquals(428, ex.getServerStatusCode()); } @AfterAll diff --git a/marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/fastfunctest/TestOptimisticLocking.java b/marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/fastfunctest/TestOptimisticLocking.java index e62f17eeb..c71e4827e 100644 --- a/marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/fastfunctest/TestOptimisticLocking.java +++ b/marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/fastfunctest/TestOptimisticLocking.java @@ -17,6 +17,8 @@ package com.marklogic.client.fastfunctest; import com.fasterxml.jackson.databind.JsonNode; +import com.marklogic.client.ContentNoVersionException; +import com.marklogic.client.ContentWrongVersionException; import com.marklogic.client.DatabaseClient; import com.marklogic.client.FailedRequestException; import com.marklogic.client.ResourceNotFoundException; @@ -46,7 +48,7 @@ import java.security.NoSuchAlgorithmException; import java.time.Instant; import java.time.temporal.ChronoUnit; - +import java.util.concurrent.atomic.AtomicReference; public class TestOptimisticLocking extends AbstractFunctionalTest { @@ -109,24 +111,10 @@ public void testRequired() throws KeyManagementException, NoSuchAlgorithmExcepti // create document descriptor DocumentDescriptor desc = docMgr.newDescriptor(docId); + AtomicReference descRef = new AtomicReference<>(desc); desc.setVersion(badVersion); - - String exception = ""; - String expectedException = "com.marklogic.client.FailedRequestException: Local message: Content version must match to write document. Server Message: RESTAPI-CONTENTWRONGVERSION: (err:FOER0000) Content version mismatch: uri /optimistic-locking/xml-original.xml doesn't match if-match: 1111"; - - // CREATE - // write document with bad version - try - { - docMgr.write(desc, handle); - } catch (FailedRequestException e) { - exception = e.toString(); - } - - boolean isExceptionThrown = exception.contains(expectedException); - assertTrue( isExceptionThrown); - System.out.println(exception); + assertThrows(ContentWrongVersionException.class, () -> docMgr.write(descRef.get(), handle)); // write document with unknown version desc.setVersion(DocumentDescriptor.UNKNOWN_VERSION); @@ -151,36 +139,14 @@ public void testRequired() throws KeyManagementException, NoSuchAlgorithmExcepti // update with bad version desc.setVersion(badVersion); - - String updateException = ""; - String expectedUpdateException = "com.marklogic.client.FailedRequestException: Local message: Content version must match to write document. Server Message: RESTAPI-CONTENTWRONGVERSION: (err:FOER0000) Content version mismatch: uri /optimistic-locking/xml-original.xml has current version"; - - try { - docMgr.write(desc, updateHandle); - } catch (FailedRequestException e) { - updateException = e.toString(); - } - System.out.println(updateException); - boolean isUpdateExceptionThrown = updateException.contains(expectedUpdateException); - assertTrue( isUpdateExceptionThrown); + assertThrows(ContentWrongVersionException.class, () -> docMgr.write(descRef.get(), updateHandle)); // update with unknown version desc.setVersion(DocumentDescriptor.UNKNOWN_VERSION); - - String updateUnknownException = ""; - String expectedUpdateUnknownException = "com.marklogic.client.FailedRequestException: Local message: Content version required to write document. Server Message: RESTAPI-CONTENTNOVERSION: (err:FOER0000) No content version supplied: uri /optimistic-locking/xml-original.xml"; - - try { - docMgr.write(desc, updateHandle); - } catch (FailedRequestException e) { - updateUnknownException = e.toString(); - } - - boolean isUpdateUnknownExceptionThrown = updateUnknownException.contains(expectedUpdateUnknownException); - System.out.println(updateUnknownException); - assertTrue( isUpdateUnknownExceptionThrown); + assertThrows(ContentNoVersionException.class, () -> docMgr.write(descRef.get(), updateHandle)); desc = docMgr.exists(docId); + descRef.set(desc); goodVersion = desc.getVersion(); System.out.println("version before update: " + goodVersion); @@ -197,35 +163,11 @@ public void testRequired() throws KeyManagementException, NoSuchAlgorithmExcepti // DELETE // delete using bad version desc.setVersion(badVersion); - - String deleteException = ""; - String expectedDeleteException = "com.marklogic.client.FailedRequestException: Local message: Content version must match to delete document. Server Message: RESTAPI-CONTENTWRONGVERSION: (err:FOER0000) Content version mismatch: uri /optimistic-locking/xml-original.xml has current version"; - - try { - docMgr.delete(desc); - } catch (FailedRequestException e) { - deleteException = e.toString(); - } - - boolean isDeleteExceptionThrown = deleteException.contains(expectedDeleteException); - System.out.println("Delete exception" + deleteException); - assertTrue( isDeleteExceptionThrown); + assertThrows(ContentWrongVersionException.class, () -> docMgr.delete(descRef.get())); // delete using unknown version desc.setVersion(DocumentDescriptor.UNKNOWN_VERSION); - - String deleteUnknownException = ""; - String expectedDeleteUnknownException = "com.marklogic.client.FailedRequestException: Local message: Content version required to delete document. Server Message: RESTAPI-CONTENTNOVERSION: (err:FOER0000) No content version supplied: uri /optimistic-locking/xml-original.xml"; - - try { - docMgr.delete(desc); - } catch (FailedRequestException e) { - deleteUnknownException = e.toString(); - } - - boolean isDeleteUnknownExceptionThrown = deleteUnknownException.contains(expectedDeleteUnknownException); - System.out.println("Delete exception" + deleteUnknownException); - assertTrue( isDeleteUnknownExceptionThrown); + assertThrows(ContentNoVersionException.class, () -> docMgr.delete(descRef.get())); // delete using good version desc = docMgr.exists(docId); @@ -291,20 +233,7 @@ public void testOptionalWithUnknownVersion() throws KeyManagementException, NoSu DocumentDescriptor desc = docMgr.newDescriptor(docId); desc.setVersion(badVersion); - - String exception = ""; - String expectedException = "com.marklogic.client.FailedRequestException: Local message: Content version must match to write document. Server Message: RESTAPI-CONTENTWRONGVERSION"; - - // CREATE - // write document with bad version - try { - docMgr.write(desc, handle); - } catch (FailedRequestException e) { - exception = e.toString(); - } - - boolean isExceptionThrown = exception.contains(expectedException); - assertTrue( isExceptionThrown); + assertThrows(ContentWrongVersionException.class, () -> docMgr.write(desc, handle)); // write document with unknown version desc.setVersion(DocumentDescriptor.UNKNOWN_VERSION); @@ -329,18 +258,7 @@ public void testOptionalWithUnknownVersion() throws KeyManagementException, NoSu // update with bad version desc.setVersion(badVersion); - - String updateException = ""; - String expectedUpdateException = "com.marklogic.client.FailedRequestException: Local message: Content version must match to write document. Server Message: RESTAPI-CONTENTWRONGVERSION"; - - try { - docMgr.write(desc, updateHandle); - } catch (FailedRequestException e) { - updateException = e.toString(); - } - - boolean isUpdateExceptionThrown = updateException.contains(expectedUpdateException); - assertTrue( isUpdateExceptionThrown); + assertThrows(ContentWrongVersionException.class, () -> docMgr.write(desc, updateHandle)); // update with unknown version desc.setVersion(DocumentDescriptor.UNKNOWN_VERSION); @@ -366,18 +284,7 @@ public void testOptionalWithUnknownVersion() throws KeyManagementException, NoSu // DELETE // delete using bad version desc.setVersion(badVersion); - - String deleteException = ""; - String expectedDeleteException = "com.marklogic.client.FailedRequestException: Local message: Content version must match to delete document"; - - try { - docMgr.delete(desc); - } catch (FailedRequestException e) { - deleteException = e.toString(); - } - - boolean isDeleteExceptionThrown = deleteException.contains(expectedDeleteException); - assertTrue( isDeleteExceptionThrown); + assertThrows(ContentWrongVersionException.class, () -> docMgr.delete(desc)); // delete using unknown version desc.setVersion(DocumentDescriptor.UNKNOWN_VERSION); @@ -441,21 +348,10 @@ public void testOptionalWithGoodVersion() throws KeyManagementException, NoSuchA // create document descriptor DocumentDescriptor desc = docMgr.newDescriptor(docId); - desc.setVersion(badVersion); - - String exception = ""; - String expectedException = "com.marklogic.client.FailedRequestException: Local message: Content version must match to write document. Server Message: RESTAPI-CONTENTWRONGVERSION"; - // CREATE // write document with bad version - try { - docMgr.write(desc, handle); - } catch (FailedRequestException e) { - exception = e.toString(); - } - - boolean isExceptionThrown = exception.contains(expectedException); - assertTrue( isExceptionThrown); + desc.setVersion(badVersion); + assertThrows(ContentWrongVersionException.class, () -> docMgr.write(desc, handle)); // write document with unknown version desc.setVersion(DocumentDescriptor.UNKNOWN_VERSION); @@ -480,18 +376,7 @@ public void testOptionalWithGoodVersion() throws KeyManagementException, NoSuchA // update with bad version desc.setVersion(badVersion); - - String updateException = ""; - String expectedUpdateException = "com.marklogic.client.FailedRequestException: Local message: Content version must match to write document. Server Message: RESTAPI-CONTENTWRONGVERSION"; - - try { - docMgr.write(desc, updateHandle); - } catch (FailedRequestException e) { - updateException = e.toString(); - } - - boolean isUpdateExceptionThrown = updateException.contains(expectedUpdateException); - assertTrue( isUpdateExceptionThrown); + assertThrows(ContentWrongVersionException.class, () -> docMgr.write(desc, updateHandle)); // update with good version desc.setVersion(goodVersion); @@ -517,18 +402,7 @@ public void testOptionalWithGoodVersion() throws KeyManagementException, NoSuchA // DELETE // delete using bad version desc.setVersion(badVersion); - - String deleteException = ""; - String expectedDeleteException = "com.marklogic.client.FailedRequestException: Local message: Content version must match to delete document"; - - try { - docMgr.delete(desc); - } catch (FailedRequestException e) { - deleteException = e.toString(); - } - - boolean isDeleteExceptionThrown = deleteException.contains(expectedDeleteException); - assertTrue( isDeleteExceptionThrown); + assertThrows(ContentWrongVersionException.class, () -> docMgr.delete(desc)); // delete using good version desc.setVersion(goodVersion); diff --git a/marklogic-client-api/src/main/java/com/marklogic/client/ContentNoVersionException.java b/marklogic-client-api/src/main/java/com/marklogic/client/ContentNoVersionException.java new file mode 100644 index 000000000..10cf9c44f --- /dev/null +++ b/marklogic-client-api/src/main/java/com/marklogic/client/ContentNoVersionException.java @@ -0,0 +1,16 @@ +package com.marklogic.client; + +import com.marklogic.client.impl.FailedRequest; + +/** + * Represents a "RESTAPI-CONTENTNOVERSION" error from the REST API that can occur when using optimistic locking. + * + * @since 6.3.0 + */ +public class ContentNoVersionException extends FailedRequestException { + + public ContentNoVersionException(String message, FailedRequest failedRequest) { + super(message, failedRequest); + } + +} diff --git a/marklogic-client-api/src/main/java/com/marklogic/client/ContentWrongVersionException.java b/marklogic-client-api/src/main/java/com/marklogic/client/ContentWrongVersionException.java new file mode 100644 index 000000000..14292acfe --- /dev/null +++ b/marklogic-client-api/src/main/java/com/marklogic/client/ContentWrongVersionException.java @@ -0,0 +1,16 @@ +package com.marklogic.client; + +import com.marklogic.client.impl.FailedRequest; + +/** + * Represents a "RESTAPI-CONTENTWRONGVERSION" error from the REST API that can occur when using optimistic locking. + * + * @since 6.3.0 + */ +public class ContentWrongVersionException extends FailedRequestException { + + public ContentWrongVersionException(String message, FailedRequest failedRequest) { + super(message, failedRequest); + } + +} diff --git a/marklogic-client-api/src/main/java/com/marklogic/client/impl/OkHttpServices.java b/marklogic-client-api/src/main/java/com/marklogic/client/impl/OkHttpServices.java index d114b2ea5..a39ca9346 100644 --- a/marklogic-client-api/src/main/java/com/marklogic/client/impl/OkHttpServices.java +++ b/marklogic-client-api/src/main/java/com/marklogic/client/impl/OkHttpServices.java @@ -18,13 +18,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.marklogic.client.*; import com.marklogic.client.DatabaseClient.ConnectionResult; -import com.marklogic.client.DatabaseClientFactory.BasicAuthContext; -import com.marklogic.client.DatabaseClientFactory.CertificateAuthContext; import com.marklogic.client.DatabaseClientFactory.DigestAuthContext; -import com.marklogic.client.DatabaseClientFactory.KerberosAuthContext; -import com.marklogic.client.DatabaseClientFactory.MarkLogicCloudAuthContext; -import com.marklogic.client.DatabaseClientFactory.SAMLAuthContext; -import com.marklogic.client.DatabaseClientFactory.SSLHostnameVerifier; import com.marklogic.client.DatabaseClientFactory.SecurityContext; import com.marklogic.client.bitemporal.TemporalDescriptor; import com.marklogic.client.bitemporal.TemporalDocumentManager.ProtectionLevel; @@ -437,7 +431,7 @@ public Response apply(Request.Builder funcBuilder) { if (status == STATUS_PRECONDITION_REQUIRED) { FailedRequest failure = extractErrorFields(response); if (failure.getMessageCode().equals("RESTAPI-CONTENTNOVERSION")) { - throw new FailedRequestException( + throw new ContentNoVersionException( "Content version required to delete document", failure); } throw new FailedRequestException( @@ -450,9 +444,7 @@ public Response apply(Request.Builder funcBuilder) { if (status == STATUS_PRECONDITION_FAILED) { FailedRequest failure = extractErrorFields(response); if (failure.getMessageCode().equals("RESTAPI-CONTENTWRONGVERSION")) { - throw new FailedRequestException( - "Content version must match to delete document", - failure); + throw new ContentWrongVersionException("Content version must match to delete document", failure); } else if (failure.getMessageCode().equals("RESTAPI-EMPTYBODY")) { throw new FailedRequestException( "Empty request body sent to server", failure); @@ -1308,8 +1300,7 @@ private TemporalDescriptor putPostDocumentImpl(RequestLogger reqlog, String meth if (status == STATUS_PRECONDITION_REQUIRED) { FailedRequest failure = extractErrorFields(response); if (failure.getMessageCode().equals("RESTAPI-CONTENTNOVERSION")) { - throw new FailedRequestException( - "Content version required to write document", failure); + throw new ContentNoVersionException("Content version required to write document", failure); } throw new FailedRequestException( "Precondition required to write document", failure); @@ -1321,8 +1312,7 @@ private TemporalDescriptor putPostDocumentImpl(RequestLogger reqlog, String meth if (status == STATUS_PRECONDITION_FAILED) { FailedRequest failure = extractErrorFields(response); if (failure.getMessageCode().equals("RESTAPI-CONTENTWRONGVERSION")) { - throw new FailedRequestException( - "Content version must match to write document", failure); + throw new ContentWrongVersionException("Content version must match to write document", failure); } else if (failure.getMessageCode().equals("RESTAPI-EMPTYBODY")) { throw new FailedRequestException( "Empty request body sent to server", failure); @@ -1453,8 +1443,7 @@ private TemporalDescriptor putPostDocumentImpl(RequestLogger reqlog, String meth if (status == STATUS_PRECONDITION_REQUIRED) { FailedRequest failure = extractErrorFields(response); if (failure.getMessageCode().equals("RESTAPI-CONTENTNOVERSION")) { - throw new FailedRequestException( - "Content version required to write document", failure); + throw new ContentNoVersionException("Content version required to write document", failure); } throw new FailedRequestException( "Precondition required to write document", failure); @@ -1466,8 +1455,7 @@ private TemporalDescriptor putPostDocumentImpl(RequestLogger reqlog, String meth if (status == STATUS_PRECONDITION_FAILED) { FailedRequest failure = extractErrorFields(response); if (failure.getMessageCode().equals("RESTAPI-CONTENTWRONGVERSION")) { - throw new FailedRequestException( - "Content version must match to write document", failure); + throw new ContentWrongVersionException("Content version must match to write document", failure); } else if (failure.getMessageCode().equals("RESTAPI-EMPTYBODY")) { throw new FailedRequestException( "Empty request body sent to server", failure); @@ -4398,7 +4386,7 @@ private void checkStatus(Response response, int status, String operation, String failure); } if ("RESTAPI-CONTENTNOVERSION".equals(failure.getMessageCode())) { - throw new FailedRequestException("Content version required to " + + throw new ContentNoVersionException("Content version required to " + operation + " " + entityType + " at " + path, failure); } else if (status == STATUS_FORBIDDEN) { throw new ForbiddenUserException("User is not allowed to "