MarkLogic Java API

The MarkLogic Java API support reading, writing, and deleting document content and metadata as well as querying documents.

Before Starting

Before using the API, create a REST server for your database. If the database has existing documents, modify the roles with privileges to read and write those documents to inherit from rest-reader and rest-writer.

Creating a Database Client

Use {@link com.marklogic.client.DatabaseClientFactory}.newClient() to create a client for a database. You can then use the {@link com.marklogic.client.DatabaseClient} factory methods (which begin with "new") to create document, configuration, and query managers.

Working with Document Managers

Use the {@link com.marklogic.client.DatabaseClient} to create the appropriate document manager for the format of the content -- a {@link com.marklogic.client.document.BinaryDocumentManager} for a binary document or an {@link com.marklogic.client.document.XMLDocumentManager} for an XML document. The client also provides {@link com.marklogic.client.document.JSONDocumentManager} and {@link com.marklogic.client.document.TextDocumentManager} document manager for those formats. Use {@link com.marklogic.client.document.GenericDocumentManager} if you don't know the format or need to process multiple documents with different formats.

To identify a document in the database, you use a String with the document URI.

To access document content, you create a handle object that supports the appropriate representation. This concept of content handles is core to the Java API (making use of the Adapter design pattern so the API can read or write content with a diverse and extensible set of representations).

For instance, consider a binary JPEG file. To write this file to the database, you create a {@link com.marklogic.client.io.FileHandle} and call the handle's set() method with the File object. You then pass the handle to the operation that writes the binary content to the database.

Similarly, let's say you want to read the content of an XML document from the database into a DOM document. You pass a {@link com.marklogic.client.io.DOMHandle} to the operation that reads the XML content. The read operation populates the DOMHandle with the content. You can then call the handle's get() method to get the org.w3c.dom.Document object. In short, a handle acts as a container for content in a representation.

To read document content from the database, pass the document URI string and a handle to the read() method of the document manager. Then use the methods of the handle to get the content. The following example reads the content of the /db/path/to/myDoc.xml database document into a DOM document:

XMLDocumentManager docMgr = client.newXMLDocumentManager();
String docId = "/db/path/to/myDoc.xml";
DOMHandle handle = new DOMHandle();

docMgr.read(docId, handle);

org.w3c.dom.Document document = handle.get();

To write content to a document in the database, set the content in a handle and then pass the document URI string and the content handle to the write() method of the document manager. The following example write the content of the /db/path/to/myDoc.xml database document from a DOM document:

org.w3c.dom.Document document = ... create or modify the document ...;

XMLDocumentManager docMgr = client.newXMLDocumentManager();
String docId = "/db/path/to/myDoc.xml";
DOMHandle handle = new DOMHandle();
handle.set(document);

docMgr.write(docId, handle);

To learn which handles you can use to read the content of an XML document, look at the classes that implement {@link com.marklogic.client.io.marker.XMLReadHandle}. To learn which handles you can use to write the content of an XML document, look at the classes that implement {@link com.marklogic.client.io.marker.XMLWriteHandle}. {@link com.marklogic.client.document.BinaryDocumentManager}, {@link com.marklogic.client.document.JSONDocumentManager}, {@link com.marklogic.client.document.TextDocumentManager}, and {@link com.marklogic.client.document.GenericDocumentManager} each have corresponding read and write handles that identify the handle classes that can be used when reading and writing documents of that format.

You can read or write document metadata in the same request as document content or separately.

Working with the Query Options Manager

To prepare a database for search applications, you will have created indexes on the fields and elements of documents. A QueryOptionsHandle object provides hooks for configuring search and query applications' use of indexes. Use {@link com.marklogic.client.admin.QueryOptionsManager} to write, read, and delete query options. Use {@link com.marklogic.client.io.QueryOptionsHandle} to manipulate QueryOptions configurations. Use {@link com.marklogic.client.admin.config.QueryOptionsBuilder} to build new configurations or add to existing ones.

The following example writes new query options named "shipments" with a single constraint. The constraint, of type "value" names the "port" location within documents for queries that use the "shipments" query options.

QueryOptionsManager optionsMgr = client.newQueryOptionsManager();

QueryOptionsHandle handle = new QueryOptionsHandle();
QueryOptionsBuilder builder = new QueryOptionsBuilder();

handle.withConstraints(
	builder.constraint("port",
		builder.value(
			builder.elementTermIndex(new QName("port")))));

optionsMgr.writeOptions("shipments", handle);

Working with the Query Manager

Use {@link com.marklogic.client.query.QueryManager} to search documents or extract values, co-occurrences of values, or full tuple records from document indexes. The search() method takes the name for search options that you wrote to the database previously, a query definition including the search criteria, and a handle for representing the results. You can supply search criteria as a string, keys-value pairs, or a structure. You can represent results as JSON, XML, or a Java data structure.

The following example uses the "shipments" query options written to database previously. The search criteria matches documents that contain the term "electronics" as well as a <port> element with a value of "Lisbon". The example reads the search results into a DOM document.

QueryManager queryMgr = client.newQueryManager();

StringQueryDefinition querydef = queryMgr.newStringDefinition("shipments");
querydef.setCriteria("electronics port:Lisbon");

DOMHandle handle = new DOMHandle();

queryMgr.search(querydef, handle);

org.w3c.dom.Document results = handle.get();

Besides XML or JSON, you can also get search results as a Java data structure by using {@link com.marklogic.client.io.SearchHandle}. This approach is often the most convenient way to manipulate search results as demonstrated in the following example:

QueryManager queryMgr = client.newQueryManager();

StringQueryDefinition querydef = queryMgr.newStringDefinition("shipments");
querydef.setCriteria("electronics port:Lisbon");

SearchHandle results = new SearchHandle();

queryMgr.search(querydef, results);

... do something at the response level (total response, metrics, and so on) ...
for (MatchDocumentSummary docSummary: results.getMatchResults()) {
    ... do something for a matching document ...
    for (MatchLocation location : docSummary.getMatchLocations()) {
        ... do something at the match location level ...
        for (MatchSnippet snippet : location.getSnippets()) {
            if (snippet.isHighlighted()) {
                ... do something with highlighted text ...
            } else {
                ... do something with unhighlighted text ...
            }
        }
    }
}

Concise Code with Fluent Interfaces

The API makes use of the Fluent Interface design pattern so that, when you become familiar with the API, you can execute operations concisely.

For instance, because the read() method returns the content handle, the earlier read operation can be expressed in a single line:

org.w3c.dom.Document document =
    client.newXMLDocumentManager().read(
        client.newDocId("/db/path/to/myDoc.xml"),
        new DOMHandle()
        ).get();

Because most handles provide a with() method that sets the content and returns the handle, you can a write operation in a single line:

org.w3c.dom.Document document = ... create or modify the document ...;

client.newXMLDocumentManager().write(
    client.newDocId("/db/path/to/myDoc.xml"),
    new DOMHandle().with(document)
    );

When convenient, you can write a search operation in a single line:

org.w3c.dom.Document results = 
    client.newQueryManager().search(
        queryMgr.newStringDefinition("shipments").withCriteria("electronics port:Lisbon"),
        new DOMHandle()
        ).get();