Skip to content

Commit a19cfd9

Browse files
committed
Improved test for HTTP chunking
Also fixed a bug in the error handling where a `FailedRequest` was constructed and populated, but it was not actually passed into the `FailedRequestException`, thereby causing a null-pointer error when certain parts of the `FailedRequestException` were added.
1 parent ee32c39 commit a19cfd9

File tree

2 files changed

+41
-33
lines changed

2 files changed

+41
-33
lines changed

marklogic-client-api/src/main/java/com/marklogic/client/impl/OkHttpServices.java

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4594,22 +4594,27 @@ private <U extends OkHttpResultIterator> U makeResults(
45944594
}
45954595
List<BodyPart> partList = getPartList(entity);
45964596

4597+
String mlErrorCode = null;
4598+
String mlErrorMessage = null;
45974599
try {
4598-
Headers trailer = response.trailers();
4599-
String code = trailer.get("ml-error-code");
4600-
String msg = trailer.get("ml-error-message");
4601-
String sha = trailer.get("ml-content-sha256");
4602-
4603-
if (code != null && !"N/A".equals(code)) {
4604-
FailedRequest failure = new FailedRequest();
4605-
failure.setMessageString(code);
4606-
failure.setStatusString(msg);
4607-
throw new FailedRequestException("failed to " + operation + " "
4608-
+ entityType + " at rows" + ": " + code + ", " + msg);
4609-
}
4600+
Headers trailers = response.trailers();
4601+
mlErrorCode = trailers.get("ml-error-code");
4602+
mlErrorMessage = trailers.get("ml-error-message");
46104603
} catch (IOException e) {
4611-
throw new RuntimeException("No trailer header in repsonse");
4604+
// This does not seem worthy of causing the entire operation to fail; we also don't expect this to occur, as it
4605+
// should only occur due to a programming error where the response body has already been consumed
4606+
logger.warn("Unexpected IO error while getting HTTP response trailers: " + e.getMessage());
46124607
}
4608+
4609+
if (mlErrorCode != null && !"N/A".equals(mlErrorCode)) {
4610+
FailedRequest failure = new FailedRequest();
4611+
failure.setMessageString(mlErrorCode);
4612+
failure.setStatusString(mlErrorMessage);
4613+
failure.setStatusCode(500);
4614+
throw new FailedRequestException("failed to " + operation + " "
4615+
+ entityType + " at rows" + ": " + mlErrorCode + ", " + mlErrorMessage, failure);
4616+
}
4617+
46134618
Closeable closeable = response;
46144619
return makeResults(constructor, reqlog, operation, entityType, partList, response, closeable);
46154620
}

marklogic-client-api/src/test/java/com/marklogic/client/test/rows/RowManagerTest.java

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@
1616
package com.marklogic.client.test.rows;
1717

1818
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
19-
import static org.junit.Assert.assertArrayEquals;
20-
import static org.junit.Assert.assertEquals;
21-
import static org.junit.Assert.assertFalse;
22-
import static org.junit.Assert.assertNotNull;
23-
import static org.junit.Assert.assertTrue;
19+
import static org.junit.Assert.*;
2420

2521
import java.io.IOException;
2622
import java.io.LineNumberReader;
@@ -40,6 +36,7 @@
4036
import javax.xml.xpath.XPathExpressionException;
4137

4238
import com.fasterxml.jackson.databind.node.ObjectNode;
39+
import com.marklogic.client.FailedRequestException;
4340
import com.marklogic.client.datamovement.DataMovementManager;
4441
import com.marklogic.client.datamovement.WriteBatcher;
4542
import com.marklogic.client.io.*;
@@ -527,27 +524,33 @@ public void testSQL0Result() {
527524
assertEquals("", exception);
528525
}
529526

527+
/**
528+
* This test was added to take advantage of MarkLogic 11's support for HTTP chunking. It is expected that when calls
529+
* are made to /v1/rows, the TE and ML-Check-ML11-Headers headers will be added, thus triggering HTTP chunking in the
530+
* server. The SQL query in this test is designed to produce an error for the "last" musician of the 4 in the test
531+
* database. OkHttpServices is then expected to check for the special MarkLogic trailers in the HTTP response -
532+
* ml-error-code and ml-error-message. And then the end result is that a FailedRequestException is expected.
533+
*
534+
* You can verify this test works by commenting out the sections in OkHttpServices that check for the special
535+
* MarkLogic trailers in the HTTP response, and/or commenting out the two places where the TE/ML-Check-ML11-Headers
536+
* headers are sent.
537+
*/
530538
@Test
531-
public void testSQLException() {
539+
public void testMarklogicHeadersProduceExpectedError() {
532540
if (!Common.markLogicIsVersion11OrHigher()) {
533541
return;
534542
}
535543

536544
RowManager rowMgr = Common.client.newRowManager();
537-
PlanBuilder p = rowMgr.newPlanBuilder();
538-
PlanBuilder.ExportablePlan builtPlan =
539-
p.fromSql("select case when lastName = 'Davis' then fn_error(fn_qname('', 'SQL-TABLENOTFOUND'), 'Internal Server Error') end, opticUnitTest.musician.* from (select * from opticUnitTest.musician order by lastName)");
540-
String exception = "";
541-
int rowNum = 0;
542-
try {
543-
for (RowRecord row: rowMgr.resultRows(builtPlan)) {
544-
rowNum++;
545-
}
546-
} catch (Exception e) {
547-
exception = e.toString();
548-
}
549-
assertEquals(0, rowNum);
550-
assertEquals("com.marklogic.client.FailedRequestException: failed to apply resource at rows: SQL-TABLENOTFOUND, Internal Server Error", exception);
545+
PlanBuilder.ExportablePlan builtPlan = rowMgr.newPlanBuilder()
546+
.fromSql("select case when lastName = 'Davis' then fn_error(fn_qname('', 'SQL-TABLENOTFOUND'), 'Internal Server Error') end, " +
547+
"opticUnitTest.musician.* from (select * from opticUnitTest.musician order by lastName)");
548+
549+
FailedRequestException ex = assertThrows(FailedRequestException.class, () -> rowMgr.resultRows(builtPlan));
550+
assertEquals(500, ex.getServerStatusCode());
551+
assertEquals("SQL-TABLENOTFOUND", ex.getServerMessage());
552+
assertEquals("Local message: failed to apply resource at rows: SQL-TABLENOTFOUND, Internal Server Error. Server Message: SQL-TABLENOTFOUND",
553+
ex.getMessage());
551554
}
552555

553556
@Test

0 commit comments

Comments
 (0)