The new website for MarkLogic is Visit it.

To Be or Not to Be: The Truth about Schemas

Back to blog
4 minute read
Back to blog
4 minute read
Person using a tablet

As of MarkLogic 7.0-3, the MarkLogic Java Client API provides some shortcuts to make IO simpler.

The Java programming language and its libraries have long standing support for strong typing. Strong typing helps you write production code by catching many errors early, but it can also complicate things when you know your code to be safe but the compiler doesn’t. Imagine trying to claim your suitcase when you don’t have the claim check tag – you can see your suitcase, but, for sensible reasons, the clerk won’t let you take it.

You can see an example of type safety in the javax.xml.transform.Transformer class in the core Java API. The transform() function takes Source and Result adapters for all of the built-in Java classes that can provide input or output on a document. For instance, if you want to use a DOM document for input, you have to use the DOMSource adapter instead of the Document itself. That way, strong typing guarantees that the transform() function can take input from the object. The downside, however, is that you have to create the adapter.

The MarkLogic Java Client API takes the same approach as the Transformer API, providing adapters (called handles by MarkLogic) in the API not just for XML but for binary, JSON, and text formats as well. The respective handle gives you the benefits of strong typing – when you’re writing a document, the handle guarantees that the Java API can take input from a DOM document, a Jackson stream, or an in-memory byte[] array. That also gives you extensibility. By writing a handle, you can tell the Java API how to read or write content using new libraries that aren’t supported out of the box. But, once you know which IO representations are supported, you no longer need strong typing to check the input or output. As with the clerk with the suitcases, you’d like the API to trust that you know what you’re doing.

That’s why the Java Client API has introduced new overloads to provide a shortcut. Shortcut methods are easy to recognize because each name appends “As” to the name of a strongly-typed method. For instance, in DocumentManager, you’ll find a readAs() shortcut for the strongly typed read() method and a writeAs() shortcut for the strongly-typed write() method. The read shortcut take the class of the IO object and returns an instance of the IO object. The write shortcut takes an instance of the IO object.

Here’s an example. In the strongly-typed approach, you can read an XML document as a DOM document by passing a DOMHandle to the read() method:

XMLDocumentManager docMgr = client.newXMLDocumentManager();

String docId = “/example/theDocument.xml”;

// strongly-typed read
Document theDocument =, new DOMHandle()).get();

While you can instantiate the DOMHandle and get the DOM document inline, the new shortcut approach is easier. You pass the DOM Document class directly to the readAs() method, and it returns the DOM document:

XMLDocumentManager docMgr = client.newXMLDocumentManager();

String docId = “/example/theDocument.xml”;

// shortcut read
Document theDocument = docMgr.readAs(docId, Document.class);

Similarly, the strongly-typed approach to write a DOM document wraps the document with a DOMHandle:

// strongly-typed write
write(docId, new DOMHandle(theDocument));

To use the shortcut instead, you just pass the DOM Document directly to the writeAs() method:

// shortcut write
writeAs(docId, theDocument);

A couple of things to note. First, behind the scenes, the shortcut method creates the built-in handle for the class or object. As a result, the shortcut approach is never more efficient than the strongly-typed approach. If you’re ingesting documents for hours at a stretch, you probably want to use the strongly-typed handles. For ordinary application workloads, the difference is insignificant.

Second, by dispensing with strong typing, a shortcut method creates a small risk because an IO class without a corresponding handle will throw a runtime exception. However, the supported IO classes are all standard for Java, so you’re not likely to run into that problem.

The shortcut methods help improve the readability and maintainability of your code. That’s particularly clear for IO on your domain POJOs. MarkLogic’s Java Client API takes advantage of the core Java JAXB library, which can marshal and unmarshal any POJO tree structure if you annotate the root class for the tree.

To use shortcut methods with POJO classes, you just register the POJO classes using the JAXBHandle factory before you create the database client. Thereafter, you can treat your POJO classes as IO classes, passing the object when writing and passing the class when reading back the object:


// … create the database client and XMLDocumentManager …

String docId = “/example/FashionForward.xml”;

// shortcut read
Product product = docMgr.readAs(docId, Product.class);

// modify the product

// shortcut write
writeAs(docId, product);

If you have other data structures with different root classes – for instance, Customer or Supplier data structures – you can register those root classes at the same time as the Product class.

In addition, you can use the registry to augment the built-in handles with extra handles and your own handles. You can look at the source code to understand how to write a factory for a new handle. After you register the new handle, the shortcut methods will work with the new IO objects.

When would you still use strongly-typed IO methods instead of the new shortcut IO methods?

  • When you want compile-time checking of input and output types.
  • When you want a slight increase in efficiency for a large number of requests.
  • When you need to set the format or mime type on a handle.

When those edge cases don’t apply, consider accelerating and simplifying your coding by taking the shortcut with the new *As() methods.

To find out more, take a look at the MarkLogic Java Client API on GitHub (and learn about other great new capabilities that Sam Mefford is adding to the library).

Share this article

Read More

Related Posts

Like what you just read, here are a few more articles for you to check out or you can visit our blog overview page to see more.


Poker Fun with XQuery

In this post, we dive into building a full five-card draw poker game with a configurable number of players. Written in XQuery 1.0, along with MarkLogic extensions to the language, this game provides examples of some great programming capabilities, including usage of maps, recursions, random numbers, and side effects. Hopefully, we will show those new to XQuery a look at the language that they may not get to see in other tutorials or examples.

All Blog Articles

Protecting passwords in ml-gradle projects

If you are getting involved in a project using ml-gradle, this tip should come in handy if you are not allowed to put passwords (especially the admin password!) in plain text. Without this restriction, you may have multiple passwords in your file if there are multiple MarkLogic users that you need to configure. Instead of storing these passwords in, you can retrieve them from a location where they’re encrypted using a Gradle credentials plugin.

All Blog Articles

Getting Started with Apache Nifi: Migrating from Relational to MarkLogic

Apache NiFi introduces a code-free approach of migrating content directly from a relational database system into MarkLogic. Here we walk you through getting started with migrating data from a relational database into MarkLogic

All Blog Articles

Sign up for a Demo

Don’t waste time stitching together components. MarkLogic combines the power of a multi-model database, search, and semantic AI technology in a single platform with mastering, metadata management, government-grade security and more.

Request a Demo