We’ve joined forces with Smartlogic to reveal smarter decisions—together.

To Be or Not to Be: The Truth about Schemas

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 = docMgr.read(docId, 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).

Start a discussion

Connect with the community




Most Recent

View All

Unifying Data, Metadata, and Meaning

We're all drowning in data. Keeping up with our data - and our understanding of it - requires using tools in new ways to unify data, metadata, and meaning.
Read Article

How to Achieve Data Agility

Successfully responding to changes in the business landscape requires data agility. Learn what visionary organizations have done, and how you can start your journey.
Read Article

Scaling Memory in MarkLogic Server

This not-too-technical article covers a number of questions about MarkLogic Server and its use of memory. Learn more about how MarkLogic uses memory, why you might need more memory, when you need more memory, and how you can add more memory.
Read Article
This website uses cookies.

By continuing to use this website you are giving consent to cookies being used in accordance with the MarkLogic Privacy Statement.