Skip to content

Commit 04aef10

Browse files
committed
MLE-27078 More tests for this bug
Made a very confusing private field easier to understand in DocumentManagerImpl.
1 parent 5e00335 commit 04aef10

File tree

5 files changed

+75
-42
lines changed

5 files changed

+75
-42
lines changed

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ MARKLOGIC_LOGS_VOLUME=./docker/marklogic/logs
44
MARKLOGIC_IMAGE=ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi:latest-12
55

66
# Latest public release
7-
#MARKLOGIC_IMAGE=progressofficial/marklogic-db:latest
7+
# MARKLOGIC_IMAGE=progressofficial/marklogic-db:latest

Jenkinsfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ pipeline {
150150
}
151151
}
152152
steps {
153-
setupDockerMarkLogic("ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi:latest-12")
153+
setupDockerMarkLogic("progressofficial/marklogic-db:latest")
154+
154155
sh label: 'run marklogic-client-api tests', script: '''#!/bin/bash
155156
export JAVA_HOME=$JAVA_HOME_DIR
156157
export GRADLE_USER_HOME=$WORKSPACE/$GRADLE_DIR

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

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
2+
* Copyright (c) 2010-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
33
*/
44
package com.marklogic.client.impl;
55

@@ -48,24 +48,29 @@ abstract class DocumentManagerImpl<R extends AbstractReadHandle, W extends Abstr
4848
static final private Logger logger = LoggerFactory
4949
.getLogger(DocumentManagerImpl.class);
5050

51-
private boolean isProcessedMetadataModified = false;
52-
final private Set<Metadata> processedMetadata = new HashSet<Metadata>() {
51+
// UGH. This state variable is used to track if the user modifies the metadataCategories set. That's because the
52+
// default value of "ALL" means something different than if the user sets it to "ALL". Specifically, on a bulk read,
53+
// the expectation is that no metadata is retrieved. So if the value is "ALL" and the user didn't set that, we
54+
// don't get metadata. But if the value is "ALL" and the user did set that, we get all the metadata. UGH!
55+
private boolean isMetadataCategoriesModified;
56+
57+
final private Set<Metadata> metadataCategories = new HashSet<>() {
5358
@Override
5459
public boolean add(Metadata e) {
55-
isProcessedMetadataModified = true;
60+
isMetadataCategoriesModified = true;
5661
return super.add(e);
5762
}
5863

5964
@Override
6065
public boolean addAll(Collection<? extends Metadata> c) {
61-
isProcessedMetadataModified = true;
66+
isMetadataCategoriesModified = true;
6267
return super.addAll(c);
6368
}
6469
};
6570
{
66-
processedMetadata.add(Metadata.ALL);
71+
metadataCategories.add(Metadata.ALL);
6772
// we need to know if the user modifies after us
68-
isProcessedMetadataModified = false;
73+
isMetadataCategoriesModified = false;
6974
}
7075

7176
private RESTServices services;
@@ -113,24 +118,24 @@ public void setContentFormat(Format format) {
113118
@Override
114119
public void setMetadataCategories(Set<Metadata> categories) {
115120
clearMetadataCategories();
116-
processedMetadata.addAll(categories);
121+
metadataCategories.addAll(categories);
117122
}
118123

119124
@Override
120125
public void setMetadataCategories(Metadata... categories) {
121126
clearMetadataCategories();
122127
for (Metadata category : categories)
123-
processedMetadata.add(category);
128+
metadataCategories.add(category);
124129
}
125130

126131
@Override
127132
public Set<Metadata> getMetadataCategories() {
128-
return processedMetadata;
133+
return metadataCategories;
129134
}
130135

131136
@Override
132137
public void clearMetadataCategories() {
133-
processedMetadata.clear();
138+
metadataCategories.clear();
134139
}
135140

136141
@Override
@@ -374,7 +379,7 @@ public <T extends R> T read(DocumentDescriptor desc,
374379
requestLogger,
375380
desc,
376381
transaction,
377-
(metadataHandle != null) ? processedMetadata : null,
382+
(metadataHandle != null) ? metadataCategories : null,
378383
mergeTransformParameters((transform != null) ? transform
379384
: getReadTransform(), extraParams), metadataHandle, contentHandle);
380385

@@ -448,7 +453,7 @@ public DocumentPage read(long serverTimestamp, ServerTransform transform, Transa
448453
transaction,
449454
// the default for bulk is no metadata, which differs from the normal
450455
// default of ALL
451-
(isProcessedMetadataModified || !withContent) ? processedMetadata : null,
456+
(isMetadataCategoriesModified || !withContent) ? metadataCategories : null,
452457
nonDocumentFormat,
453458
mergeTransformParameters((transform != null) ? transform : getReadTransform(), extraParams),
454459
withContent,
@@ -544,7 +549,7 @@ private DocumentPage search(SearchQueryDefinition querydef, long start,
544549

545550
// the default for bulk is no metadata, which differs from the normal
546551
// default of ALL
547-
Set<Metadata> metadata = isProcessedMetadataModified ? processedMetadata
552+
Set<Metadata> metadata = isMetadataCategoriesModified ? metadataCategories
548553
: null;
549554
return services.getBulkDocuments(requestLogger, serverTimestamp, querydef, start,
550555
getPageLength(), transaction, searchHandle, searchView, metadata,
@@ -943,7 +948,7 @@ protected TemporalDescriptor write(DocumentDescriptor desc, String temporalDocum
943948
requestLogger,
944949
desc,
945950
transaction,
946-
(metadataHandle != null) ? processedMetadata : null,
951+
(metadataHandle != null) ? metadataCategories : null,
947952
mergeTransformParameters((transform != null) ? transform
948953
: getWriteTransform(), extraParams), metadataHandle, contentHandle);
949954
}
@@ -1266,7 +1271,7 @@ protected DocumentDescriptorImpl create(DocumentUriTemplate template,
12661271
requestLogger,
12671272
template,
12681273
transaction,
1269-
(metadataHandle != null) ? processedMetadata : null,
1274+
(metadataHandle != null) ? metadataCategories : null,
12701275
mergeTransformParameters((transform != null) ? transform
12711276
: getWriteTransform(), extraParams), metadataHandle, contentHandle);
12721277
}
@@ -1326,7 +1331,7 @@ public void patch(DocumentDescriptor desc, DocumentPatchHandle patch,
13261331
DocumentPatchHandleImpl builtPatch = (patch instanceof DocumentPatchHandleImpl) ? (DocumentPatchHandleImpl) patch
13271332
: null;
13281333
services.patchDocument(requestLogger, desc, transaction,
1329-
(builtPatch != null) ? builtPatch.getMetadata() : processedMetadata,
1334+
(builtPatch != null) ? builtPatch.getMetadata() : metadataCategories,
13301335
(builtPatch != null) ? builtPatch.isOnContent() : true, patch);
13311336
}
13321337

@@ -1360,7 +1365,7 @@ public void patch(String uri, String temporalDocumentURI, String temporalCollec
13601365
extraParams = addTemporalParams(extraParams, temporalCollection, temporalDocumentURI, null);
13611366
DocumentPatchHandleImpl builtPatch = (patch instanceof DocumentPatchHandleImpl) ? (DocumentPatchHandleImpl) patch
13621367
: null;
1363-
services.patchDocument(requestLogger, new DocumentDescriptorImpl(uri, true), transaction, (builtPatch != null) ? builtPatch.getMetadata() : processedMetadata,
1368+
services.patchDocument(requestLogger, new DocumentDescriptorImpl(uri, true), transaction, (builtPatch != null) ? builtPatch.getMetadata() : metadataCategories,
13641369
(builtPatch != null) ? builtPatch.isOnContent() : true, extraParams, sourceDocumentURI, patch);
13651370
}
13661371

@@ -1416,7 +1421,7 @@ public void writeDefaultMetadata(String uri, Transaction transaction)
14161421
logger.info("Resetting metadata for {}", uri);
14171422

14181423
services.deleteDocument(requestLogger,
1419-
new DocumentDescriptorImpl(uri, true), transaction, processedMetadata,
1424+
new DocumentDescriptorImpl(uri, true), transaction, metadataCategories,
14201425
getWriteParams());
14211426
}
14221427

@@ -1433,7 +1438,7 @@ public void writeDefaultMetadata(Transaction transaction, String... uris)
14331438
if (uris.length == 0)
14341439
throw new IllegalArgumentException(
14351440
"Resetting document metadata with empty identifier list");
1436-
services.delete(requestLogger, transaction, processedMetadata, uris);
1441+
services.delete(requestLogger, transaction, metadataCategories, uris);
14371442
}
14381443

14391444
@Override

marklogic-client-api/src/test/java/com/marklogic/client/test/document/ReadJsonAsBinaryTest.java

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,37 @@
1717

1818
import static org.junit.jupiter.api.Assertions.assertEquals;
1919

20+
@Disabled("See MLE-27191 for description of the server bug")
2021
class ReadJsonAsBinaryTest extends AbstractClientTest {
2122

23+
private static final String URI = "/a.json";
24+
2225
@Test
23-
@Disabled("See MLE-27191 for description of the server bug")
24-
void test() {
26+
void genericDocumentManager() {
2527
try (DatabaseClient client = Common.newClient()) {
26-
final String uri = "/a.json";
27-
writeJsonAsBinary(uri, client);
28+
writeJsonAsBinary(URI, client);
2829

2930
GenericDocumentManager docManager = client.newDocumentManager();
31+
// A bulk read works...
32+
verifyBulkRead(docManager);
33+
// But a request for a single URI does not!
34+
verifySingleRead(docManager);
35+
}
36+
}
3037

31-
// A multipart request returns the correct document format.
32-
try (DocumentPage page = docManager.read(uri)) {
33-
DocumentRecord record = page.next();
34-
assertEquals(uri, record.getUri());
35-
assertEquals("application/json", record.getMimetype());
36-
assertEquals(Format.BINARY, record.getFormat());
37-
}
38+
@Test
39+
void managerWithModifiedMetadataCategories() {
40+
try (DatabaseClient client = Common.newClient()) {
41+
writeJsonAsBinary(URI, client);
3842

39-
// But a request for a single URI does not!
40-
try (InputStreamHandle handle = docManager.read(uri, new InputStreamHandle())) {
41-
assertEquals("application/json", handle.getMimetype());
42-
assertEquals(Format.BINARY, handle.getFormat(), "Unfortunately due to MLE-27191, the " +
43-
"format is JSON instead of binary. So this assertion will fail until that bug is fixed. " +
44-
"For a Java Client user, the workaround is to use the read method above and get a DocumentPage " +
45-
"back, as a multipart response seems to identify the correct headers.");
46-
}
43+
GenericDocumentManager docManager = client.newDocumentManager();
4744

45+
// With a default manager, metadata shouldn't be read by default, so this should work.
46+
verifyBulkRead(docManager);
47+
48+
// Setting metadata categories to anything will cause the bug.
49+
docManager.setMetadataCategories(DocumentManager.Metadata.PERMISSIONS);
50+
verifyBulkRead(docManager);
4851
}
4952
}
5053

@@ -56,4 +59,23 @@ private void writeJsonAsBinary(String uri, DatabaseClient client) {
5659
jsonDocManager.setWriteTransform(new ServerTransform("toBinary"));
5760
jsonDocManager.write(uri, metadata, new JacksonHandle(new ObjectMapper().createObjectNode().put("a", 1)));
5861
}
62+
63+
private void verifySingleRead(GenericDocumentManager docManager) {
64+
try (InputStreamHandle handle = docManager.read(URI, new InputStreamHandle())) {
65+
assertEquals("application/json", handle.getMimetype());
66+
assertEquals(Format.BINARY, handle.getFormat(), "Unfortunately due to MLE-27191, the " +
67+
"format is JSON instead of binary. So this assertion will fail until that bug is fixed. " +
68+
"For a Java Client user, the workaround is to use the read method above and get a DocumentPage " +
69+
"back, as a multipart response seems to identify the correct headers.");
70+
}
71+
}
72+
73+
private void verifyBulkRead(GenericDocumentManager docManager) {
74+
try (DocumentPage page = docManager.read(URI)) {
75+
DocumentRecord record = page.next();
76+
assertEquals(URI, record.getUri());
77+
assertEquals("application/json", record.getMimetype());
78+
assertEquals(Format.BINARY, record.getFormat());
79+
}
80+
}
5981
}

test-app/build.gradle

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010-2025 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
2+
* Copyright (c) 2010-2026 Progress Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
33
*/
44

55
buildscript {
@@ -25,6 +25,11 @@ plugins {
2525

2626
apply plugin: "com.marklogic.ml-gradle"
2727

28+
// Sometimes, 3 x 20 isn't enough on Jenkins.
29+
mlWaitTillReady {
30+
maxAttempts = 40
31+
}
32+
2833
dependencies {
2934
implementation "io.undertow:undertow-core:2.3.20.Final"
3035
implementation "io.undertow:undertow-servlet:2.3.20.Final"

0 commit comments

Comments
 (0)