Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9f7d2b8
Merge branch 'master' into develop
rjrudin Nov 30, 2023
585311c
Bumped to 6.4-SNAPSHOT
rjrudin Nov 30, 2023
029c175
DEVEXP-668 Added test for fromSql with no rows returned
rjrudin Dec 19, 2023
1ba3bef
Merge pull request #1625 from marklogic/feature/668-fromSql
rjrudin Dec 20, 2023
0077b00
Removing buggy usage of `execute`
rjrudin Jan 4, 2024
15bd554
Merge pull request #1627 from marklogic/feature/update-rows
rjrudin Jan 5, 2024
4ddf618
MLE-4116: Can now configure trust store
rjrudin Jan 11, 2024
2528119
MLE-4119: User can now submit an Optic update plan
rjrudin Jan 5, 2024
e4a7eaf
Merge pull request #1630 from marklogic/feature/4119-optic-update
rjrudin Jan 12, 2024
e324d60
Merge pull request #1629 from marklogic/feature/4116-truststore
rjrudin Jan 12, 2024
0c9409e
Improved error message when Optic update plan fails
rjrudin Jan 18, 2024
dd2e861
Merge pull request #1631 from marklogic/feature/update-error-message
rjrudin Jan 19, 2024
2f0aacf
Bumped to 6.5-SNAPSHOT
rjrudin Jan 24, 2024
1a55b22
Revert "Merge pull request #1631 from marklogic/feature/update-error-…
rjrudin Jan 24, 2024
8dd765f
Revert "Merge pull request #1630 from marklogic/feature/4119-optic-up…
rjrudin Jan 24, 2024
a31bda5
Merge pull request #1633 from marklogic/feature/revert-optic-update
rjrudin Jan 24, 2024
732f557
Bumped dependencies
rjrudin Jan 24, 2024
5a7ebaa
Merge pull request #1634 from marklogic/feature/bumps
rjrudin Jan 24, 2024
aa62109
Improved 2-way SSL test
rjrudin Jan 25, 2024
715b04a
Merge pull request #1635 from marklogic/feature/ssl-test-tweak
rjrudin Jan 25, 2024
f9cebe4
Removing OBE test
rjrudin Jan 25, 2024
e30370a
Fixed logback version number
rjrudin Jan 25, 2024
e579c73
Updated test to work with MarkLogic 10
rjrudin Jan 29, 2024
e01c236
Bumped to 6.5.0
rjrudin Jan 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group=com.marklogic
version=6.4.1
version=6.5.0
describedName=MarkLogic Java Client API
publishUrl=file:../marklogic-java/releases

Expand Down
15 changes: 7 additions & 8 deletions marklogic-client-api-functionaltests/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,16 @@ dependencies {
implementation 'org.skyscreamer:jsonassert:1.5.1'
implementation 'org.slf4j:slf4j-api:1.7.36'
implementation 'commons-io:commons-io:2.11.0'
implementation 'com.squareup.okio:okio:3.4.0'
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'com.fasterxml.jackson.core:jackson-core:2.15.2'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.fasterxml.jackson.core:jackson-core:2.15.3'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.3'
implementation "org.jdom:jdom2:2.0.6.1"
implementation "com.marklogic:ml-app-deployer:4.5.2"
implementation "com.marklogic:ml-app-deployer:4.6.1"

testImplementation 'ch.qos.logback:logback-classic:1.3.5'
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
testImplementation 'ch.qos.logback:logback-classic:1.3.14'
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1'
testImplementation 'org.xmlunit:xmlunit-legacy:2.9.0'
testImplementation 'org.apache.commons:commons-lang3:3.12.0'
testImplementation 'org.apache.commons:commons-lang3:3.14.0'
testImplementation 'org.apache.httpcomponents:httpclient:4.5.14'
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -423,71 +423,4 @@ public void testPointInTimeQueryNonDeterministicSet() {
// Doc count should be zero after both batchers are done.
assertEquals(0, dbClient.newServerEval().xquery(query1).eval().next().getNumber().intValue());
}

/*
* Trigger batch failure by calling incorrect meta data values
*/

@Test
public void testOnBatchFailure() {
String jsonDoc = "{" +
"\"employees\": [" +
"{ \"firstName\":\"Will\" , \"lastName\":\"Kirkham\" }," +
"{ \"firstName\":\"Hus\" , \"lastName\":\"Wattan\" }," +
"{ \"firstName\":\"Rod\" , \"lastName\":\"Mendez\" }]" +
"}";

// Use WriteBatcher to write the files.
WriteBatcher wbatcher = dmManager.newWriteBatcher();

wbatcher.withBatchSize(1000);
StringHandle handle = new StringHandle();
handle.set(jsonDoc);
String uri = null;

// Insert 100 documents
for (int i = 0; i < 100; i++) {
uri = "lastname" + i + ".json";
wbatcher.add(uri, handle);
}
wbatcher.flushAndWait();

List<String> docExporterList = Collections.synchronizedList(new ArrayList<String>());

QueryManager queryMgr = dbClient.newQueryManager();
StringQueryDefinition querydef = queryMgr.newStringDefinition();
querydef.setCriteria("Will AND Hus");
StringBuilder onBatchFailureStr = new StringBuilder();

QueryBatcher exportBatcher = dmManager.newQueryBatcher(querydef)
.withBatchSize(50)
.onUrisReady(
new ExportListener()
.withMetadataCategory(DocumentManager.Metadata.METADATAVALUES)
.onDocumentReady(doc -> {
String uriOfDoc = doc.getUri();
docExporterList.add(uriOfDoc);
}
)
.onFailure((batch, throwable) -> {
onBatchFailureStr.append("From onBatchFailure QA Exception");
System.out.println("From onBatchFailure " + throwable.getMessage());
System.out.println("From onBatchFailure QA Exception");
}
)
)
.onUrisReady(batch -> {
System.out.println("Batch Numer is " + batch.getJobBatchNumber());
})
.onQueryFailure(exception -> {
System.out.println("Exceptions thrown from testOnBatchFailure callback onQueryFailure");
exception.printStackTrace();
});
dmManager.startJob(exportBatcher);

exportBatcher.awaitCompletion();

assertTrue(onBatchFailureStr.toString().contains("From onBatchFailure QA Exception"),
"Unexpected exception: " + onBatchFailureStr);
}
}
29 changes: 13 additions & 16 deletions marklogic-client-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,49 +16,46 @@ dependencies {
implementation 'org.glassfish.jaxb:jaxb-core:2.3.0.1'
}

// Forcing usage of 3.4.0 instead of 3.2.0 to address vulnerability - https://security.snyk.io/vuln/SNYK-JAVA-COMSQUAREUPOKIO-5820002
implementation 'com.squareup.okio:okio:3.4.0'
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'
implementation 'io.github.rburgst:okhttp-digest:2.7'

implementation 'com.sun.mail:javax.mail:1.6.2'
implementation 'javax.ws.rs:javax.ws.rs-api:2.1.1'
implementation 'org.slf4j:slf4j-api:1.7.36'
implementation 'com.fasterxml.jackson.core:jackson-core:2.15.2'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.15.2'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.15.2'
implementation 'com.fasterxml.jackson.core:jackson-core:2.15.3'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.15.3'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.3'
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.15.3'

// Only used by extras (which some examples then depend on)
// Forcing codec version to avoid vulnerability with older version in httpclient
compileOnly 'commons-codec:commons-codec:1.15'
compileOnly 'commons-codec:commons-codec:1.16.0'
compileOnly 'org.apache.httpcomponents:httpclient:4.5.14'
compileOnly 'org.jdom:jdom2:2.0.6.1'
compileOnly 'org.dom4j:dom4j:2.1.4'
compileOnly 'com.google.code.gson:gson:2.10.1'

testImplementation 'org.junit.jupiter:junit-jupiter:5.9.3'
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1'
// Forcing junit version to avoid vulnerability with older version in xmlunit
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.xmlunit:xmlunit-legacy:2.9.1'
testImplementation project(':examples')

// Allows talking to the Manage API. It depends on the Java Client itself, which will usually be a slightly older
// version, but that should not have any impact on the tests.
testImplementation "com.marklogic:ml-app-deployer:4.5.2"
testImplementation "com.marklogic:ml-app-deployer:4.6.1"

// Starting with mockito 5.x, Java 11 is required, so sticking with 4.x as we have to support Java 8.
testImplementation "org.mockito:mockito-core:4.11.0"
testImplementation "org.mockito:mockito-inline:4.11.0"
testImplementation 'com.squareup.okio:okio:3.4.0'
testImplementation "com.squareup.okhttp3:mockwebserver:4.11.0"
testImplementation "com.squareup.okhttp3:mockwebserver:4.12.0"

testImplementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.2'
testImplementation 'ch.qos.logback:logback-classic:1.3.5'
testImplementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.15.3'
testImplementation 'ch.qos.logback:logback-classic:1.3.14'
// schema validation issue with testImplementation 'xerces:xercesImpl:2.12.0'
testImplementation 'org.opengis.cite.xerces:xercesImpl-xsd11:2.12-beta-r1667115'
testImplementation 'org.apache.commons:commons-lang3:3.12.0'
testImplementation 'org.apache.commons:commons-lang3:3.14.0'
testImplementation 'org.apache.httpcomponents:httpclient:4.5.14'
testImplementation 'com.opencsv:opencsv:4.6'
testImplementation 'org.geonames:geonames:1.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,49 @@ public DatabaseClientBuilder withKeyStoreAlgorithm(String algorithm) {
props.put(PREFIX + "ssl.keystore.algorithm", algorithm);
return this;
}

/**
* Supports constructing an {@code X509TrustManager} based on the given file path, which should point to a Java
* key store or trust store.
*
* @param path
* @return
* @since 6.5.0
*/
public DatabaseClientBuilder withTrustStorePath(String path) {
props.put(PREFIX + "ssl.truststore.path", path);
return this;
}

/**
* @param password optional password for a trust store
* @return
* @since 6.5.0
*/
public DatabaseClientBuilder withTrustStorePassword(String password) {
props.put(PREFIX + "ssl.truststore.password", password);
return this;
}

/**
* @param type e.g. "JKS"
* @return
* @since 6.5.0
*/
public DatabaseClientBuilder withTrustStoreType(String type) {
props.put(PREFIX + "ssl.truststore.type", type);
return this;
}

/**
* @param algorithm e.g. "SunX509"
* @return
* @since 6.5.0
*/
public DatabaseClientBuilder withTrustStoreAlgorithm(String algorithm) {
props.put(PREFIX + "ssl.truststore.algorithm", algorithm);
return this;
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1303,6 +1303,10 @@ public String getCertificatePassword() {
* <li>marklogic.client.ssl.keystore.password = must be a String; optional password for a key store; since 6.4.0.</li>
* <li>marklogic.client.ssl.keystore.type = must be a String; optional type for a key store, defaults to "JKS"; since 6.4.0.</li>
* <li>marklogic.client.ssl.keystore.algorithm = must be a String; optional algorithm for a key store, defaults to "SunX509"; since 6.4.0.</li>
* <li>marklogic.client.ssl.truststore.path = must be a String; specifies a file path for a trust store for SSL and/or certificate authentication; since 6.5.0.</li>
* <li>marklogic.client.ssl.truststore.password = must be a String; optional password for a trust store; since 6.5.0.</li>
* <li>marklogic.client.ssl.truststore.type = must be a String; optional type for a trust store, defaults to "JKS"; since 6.5.0.</li>
* <li>marklogic.client.ssl.truststore.algorithm = must be a String; optional algorithm for a trust store, defaults to "SunX509"; since 6.5.0.</li>
* </ol>
*
* @param propertySource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedHashMap;
import java.util.Map;
Expand Down Expand Up @@ -317,9 +318,29 @@ private X509TrustManager getTrustManager() {
throw new IllegalArgumentException("Trust manager must be an instanceof " + X509TrustManager.class.getName());
}
}

String path = getNullableStringValue("ssl.truststore.path");
if (path != null && path.trim().length() > 0) {
return buildTrustManagerFromTrustStorePath(path);
}

return null;
}

/**
* Added in 6.5.0 to support configuring a trust manager via properties.
*
* @param path
* @return
*/
private X509TrustManager buildTrustManagerFromTrustStorePath(String path) {
final String password = getNullableStringValue("ssl.truststore.password");
final String type = getNullableStringValue("ssl.truststore.type", "JKS");
final String algorithm = getNullableStringValue("ssl.truststore.algorithm", "SunX509");
KeyStore trustStore = SSLUtil.getKeyStore(path, password != null ? password.toCharArray() : null, type);
return (X509TrustManager) SSLUtil.getTrustManagers(algorithm, trustStore)[0];
}

private SSLContext getSSLContext() {
Object val = propertySource.apply(PREFIX + "sslContext");
if (val != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,7 @@ public void execute(Plan plan) {
@Override
public void execute(Plan plan, Transaction transaction) {
PlanBuilderBaseImpl.RequestPlan requestPlan = checkPlan(plan);
RequestParameters params = newRowsParamsBuilder(requestPlan)
.withOutput("execute")
.getRequestParameters();
RequestParameters params = newRowsParamsBuilder(requestPlan).getRequestParameters();
RESTServiceResultIterator iter = submitPlan(requestPlan, params, transaction);
if (iter != null) {
iter.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public static TrustManager[] getDefaultTrustManagers() {
* @param trustManagerAlgorithm e.g. "SunX509".
* @param optionalKeyStore if not null, used to initialize the TrustManagerFactory constructed based on the
* given algorithm.
* @return
* @return an array of at least length 1 where the first instance is an {@code X509TrustManager}
*/
public static TrustManager[] getTrustManagers(String trustManagerAlgorithm, KeyStore optionalKeyStore) {
TrustManagerFactory trustManagerFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void invalidQuery() {
RowManager rowManager = client.newRowManager();
PlanBuilder op = rowManager.newPlanBuilder();
PlanBuilder.ModifyPlan plan = op
.fromView("opticUnitTest", "musician")
.fromView("opticUnitTest", "musician_ml10")
.where(op.eq(op.col("dob"), op.xs.string("this is not a valid date")));

List<JsonNode> returnedRows = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@

import java.io.BufferedReader;
import java.io.StringReader;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -203,6 +200,24 @@ public void testJsonRowsForest2Threads() throws Exception {
public void testJsonDocs1Thread() throws Exception {
runDocsTest(jsonBatcher(1));
}

@Test
void noRowsReturned() {
RowBatcher<JsonNode> rowBatcher = jsonBatcher(1);
RowManager rowMgr = rowBatcher.getRowManager();
RawQueryDSLPlan plan = rowMgr.newRawQueryDSLPlan(
new StringHandle("op.fromView('rowBatcherUnitTest', 'code').where(op.eq(op.col('field1'), 12345))"));

List<JsonNode> results = new ArrayList<>();
rowBatcher.withBatchView(plan).onSuccess(batch -> results.add(batch.getRowsDoc()));
moveMgr.startJob(rowBatcher);
rowBatcher.awaitCompletion();
moveMgr.stopJob(rowBatcher);

assertEquals(0, results.size(), "Expecting no results as the Optic query shouldn't match any rows; " +
"also expecting no error to occur.");
}

@Test
public void testJsonDocs3Threads() throws Exception {
runDocsTest(jsonBatcher(3));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -481,24 +481,30 @@ private void testViewRows(RowSet<RowRecord> rows) {
assertEquals( 2, rowNum);
}

@Test
public void testSQL() {
RowManager rowMgr = Common.client.newRowManager();
PlanBuilder p = rowMgr.newPlanBuilder();
PlanBuilder.ExportablePlan builtPlan =
p.fromSql("select * from opticUnitTest.musician_ml10");
int rowNum = 0;
String exception = "";
try {
for (RowRecord row: rowMgr.resultRows(builtPlan)) {
rowNum++;
}
} catch (Exception e) {
exception = e.toString();
}
assertEquals(4, rowNum);
assertEquals("", exception);
}
@Test
void testSQL() {
final String query = "select * from opticUnitTest.musician_ml10";
RowManager mgr = Common.client.newRowManager();

RowSet<RowRecord> rows = mgr.resultRows(mgr.newPlanBuilder().fromSql(query));
assertEquals(4, rows.stream().count());

JsonNode doc = mgr.resultDoc(mgr.newPlanBuilder().fromSql(query), new JacksonHandle()).get();
assertEquals(3, doc.get("columns").size());
assertEquals(4, doc.get("rows").size());
}

@Test
void sqlNoRows() {
final String query = "select * from opticUnitTest.musician_ml10 where lastName = 'NOT_FOUND'";
RowManager mgr = Common.client.newRowManager();

RowSet<RowRecord> rows = mgr.resultRows(mgr.newPlanBuilder().fromSql(query));
assertEquals(0, rows.stream().count());

JsonNode doc = mgr.resultDoc(mgr.newPlanBuilder().fromSql(query), new JacksonHandle()).get();
assertNull(doc);
}

@Test
public void testSQL0Result() {
Expand Down
Loading