Chapter 11. CMIS bindings

This chapter covers

  • The CMIS bindings: Web Services, AtomPub, and Browser
  • Capturing CMIS traffic
  • CMIS schema

So far you’ve become acquainted with the CMIS domain model and with APIs for several programming languages. But we haven’t yet shown you how CMIS clients and CMIS repositories communicate with each other over the wire.

A big part of the CMIS specification describes how the CMIS domain model is mapped to the bytes that are transferred. These mappings are called bindings. CMIS 1.0 defines two bindings, the Web Services binding and the AtomPub binding; and CMIS 1.1 adds a third, the Browser binding.

The big advantage of using a CMIS library is that it hides most of the binding details. You don’t need to know how your request is serialized into XML or JSON, and you don’t need to know how to parse the response from the repository. Nevertheless, having a basic understanding of how the bindings work can help when you’re debugging your application. It’s also necessary when you’re reading the following chapters about security and performance, because the different bindings have different strengths and characteristics.

For this chapter, you need a basic understanding of XML and JSON. You should also have some high-level understanding of HTTP, Web Services, SOAP, AtomPub, HTML, and JavaScript.

Getting the specifications

If you haven’t done so yet, now is the time to download the CMIS specifications:

The specification document is available in an HTML version and a PDF version. The PDF version is the better choice because it contains a complete rendering of the document, including diagrams. The specification also includes schema files and a set of sample requests and responses for each binding. They’re useful to have around as you read this chapter.

11.1. CMIS binding overview

Usually, the first question when we start talking about the bindings is, “Why are there three bindings and not just one?” CMIS has been designed to work in enterprise environments. It turned out to also work well in other scenarios—for example, over the internet—but the design focus was on enterprise environments.

Many companies invested in big and often expensive Web Services infrastructures a few years ago. They want to, and sometimes have to, use features such as authentication, logging, and auditing that they have in place. To be accepted in such an environment, CMIS had to speak Web Services and tie into these existing IT landscapes. Integrating a RESTful service into such an environment can be difficult, tedious, and expensive.

11.1.1. The RESTful trend

In spite of this long history, there has been a trend over the last few years to move away from Web Services and to use RESTful interfaces instead. CMIS also had to provide an answer for environments that banned Web Services and their complexity. It’s debatable how RESTful the CMIS AtomPub binding is, but it follows REST principles and the AtomPub specification. As a result, any AtomPub client can interact with a CMIS repository. Today, the CMIS AtomPub binding is more popular than the Web Services binding.

11.1.2. The need for JavaScript support

After CMIS 1.0 was released, applications of all kinds emerged; CMIS worked well for desktop, mobile, and web applications. Only one scenario wasn’t covered by the two bindings: consuming CMIS directly from a JavaScript application in a web browser turned out to be very difficult. If you’ve ever tried using Web Services from a JavaScript application, you know that it’s problematic and not a fun experience. The AtomPub binding had two major issues. First, the XML parsers in some web browsers had major difficulties with XML namespaces. Second, AtomPub works by walking through links. For example, to get to the download link from a document, a client has to make several calls and follow the chain of links. Libraries like OpenCMIS avoid most of the calls by caching those links, but doing that in a stateless JavaScript application is a major effort and not a feasible approach.

CMIS 1.1 introduced the Browser binding for that reason. The Browser binding has been tailored for JavaScript applications in web browsers. It uses JSON and HTML forms for communication between application and repository. It turns out that this binding is more efficient, faster, and easier to implement than the other two bindings and has the potential to replace at least the AtomPub binding in the long run.

A CMIS-compliant repository must expose the Web Services and AtomPub bindings. Support for the Browser binding is optional, and it will take a while for most repositories to expose this new binding.

Before we dive into the details of each binding, let’s first look at the traffic between a CMIS client and a CMIS repository. The next section explains how to capture the traffic.

11.1.3. Capturing CMIS traffic for inspection

The best way to get an impression of the CMIS bindings is to see them in action (as the book title implies). Because all CMIS bindings are based on HTTP, any HTTP debug proxy should be able to capture CMIS requests and responses as long as they aren’t encrypted.

Capture tools

If you don’t already have a favorite capture tool in your programmer’s toolbox, either of these will help you capture CMIS traffic:

The CMIS client has to be configured to use the proxy. If you want to capture the traffic to and from the CMIS Workbench, open the Workbench’s start script (workbench .bat or workbench.sh, depending on your OS) in a text editor and add the following parameters to the JAVA_OPTS environment variable:

-Dhttp.proxyHost=localhost -Dhttp.proxyPort=8888

The host and port values depend on your debug proxy setup. If you run the client and the repository on the same machine, make sure you don’t use localhost as the host name in the CMIS binding URL. Use the name of your machine or your IP address instead. If you use localhost, the traffic isn’t routed through your proxy (although in some cases you may find that localhost works).

After the Workbench is properly configured, the debug proxy shows you all of its HTTP requests and responses.

11.1.4. Try it—tracing requests from part 1

If you would like to dig in further for more detail, try rerunning any of the examples from part 1 under your new trace configuration. While doing so, try to identify which API call maps to which HTTP call. Try changing the binding in the example, and see the differences across the wire.

The OpenCMIS client library can also log all URLs it calls when the log level is set to DEBUG. In the Workbench, you can see the log and change the log level by clicking the Log button on the toolbar. Doing so opens a log window with a drop-down menu at the bottom where you can change the log level. Try copying the logged URLs and opening them in a web browser.

If you don’t want to set up a debug proxy, you can also use the request-recording facility of the InMemory Repository. Open the InMemory start script (run.bat or run.sh) in a text editor, and find this parameter:

-Dcmis.server.record=false

Change the value to true, and restart the server.

Doing so creates a directory named record in the server directory. Each request or response from this point on is written to a separate file in that location. The InMemory server applies some XML and JSON formatting on output, so these files don’t exactly reflect what is sent over the wire. But the formatted files are easier to read than the real (raw) traffic.

The next sections explain in more detail what you’ll observe in that output.

11.2. A close look at the three bindings

For space considerations, we can’t cover all aspects of the three CMIS bindings in this book. That would require a full book itself. But the following sections provide the basics and entry points that will make you familiar enough to solve most problems. Note that each subsection gives you an example of what that binding looks like over the wire. Refer to the CMIS specification for the full normative details.

11.2.1. The Web Services binding

The Web Services binding is what you probably expected. It maps CMIS operations directly to SOAP calls.

This binding covers the entire CMIS specification. That is, everything defined in the specification can be done with this binding. In addition to the operation parameters defined in the specification, some operations have an extra extension parameter. This parameter lets you send and receive extra, repository-specific data. The other bindings have different means to add extra data. There’s also a way to add binding-agnostic extensions. We’ll explain those when we talk about the CMIS schema a bit later in this chapter.

The nine Web Services and associated WSDL

The CMIS specification divides all operations into nine different services. This is reflected in the CMIS Web Services Description Language (WSDL; www.w3.org/TR/wsdl). For these services, nine different endpoints are defined. For the sake of simplicity, most repositories have only one WSDL that consolidates all these services, but a few have one WSDL per service.

MTOM encoding

All communications using the CMIS Web Services binding must be Message Transmission Optimization Mechanism (MTOM) encoded. MTOM (www.w3.org/TR/soap12-mtom/) defines how binary data is attached to SOAP messages. The CMIS specification defines that MTOM must also be used for operations and services that don’t transport content.

Web Services tools should be able to generate stubs from the CMIS WSDL, but in some cases you have to manually enable MTOM support for all operations. If you’re familiar with SOAP and Web Services, there shouldn’t be any surprises, except for the following: Many Web Services toolkits aren’t designed to handle big messages that contain content and may load them into main memory. That can be fatal if the document you want to send or receive is bigger than available memory or if the toolkit discards the request due to its size. Libraries like OpenCMIS are crafted to avoid loading messages to main memory and can handle documents of arbitrary size when this binding is used.

Exceptions in Web Services

SOAP faults indicate CMIS exceptions. They must include the type of the exception and a message. They also contain an error code (a number), which is repository-specific and not used by many repositories. The exception types map to the exception types in the CMIS domain model and consequently map to Java exceptions in OpenCMIS and .NET exceptions in DotCMIS.

One of the biggest challenges with the Web Services binding is user authentication. We’ll cover that in chapter 12, because it’s a subject worthy of deeper discussion.

Example of a getObjects response over the wire

Listing 11.1 shows a complete example of a typical getObjects call to retrieve a document. Note that we inserted lots of extra page breaks to accommodate book formatting restrictions, so you can ignore those. Remember that these responses can be void of any line breaks in their raw transmitted form. As you examine the listing, note the length of these XML responses for comparison to the length of the JSON responses you’ll see later.

Listing 11.1. Example of an XML response for a typical getObjects request

11.2.2. The AtomPub binding

The AtomPub binding is built on the AtomPub specification (http://tools.ietf.org/html/rfc5023). AtomPub was mainly designed for publishing and simple editing of resources. The CMIS specification extends AtomPub to support features like hierarchies, versioning, renditions, permissions, and so on.

The AtomPub binding follows the REST paradigm by using the HTTP methods GET, POST, PUT, and DELETE in the following manner:

  • GET requests fetch data.
  • POST requests create new objects.
  • PUT requests update data and objects.
  • DELETE requests remove objects.

This binding covers most of the CMIS specification. Note, though, that it doesn’t support the createDocumentFromSource operation. Other unsupported operations such as getRenditions are implicitly covered by getObject. There are also a few values this binding doesn’t return. If you need details, refer to the AtomPub section in the official CMIS specification. The operation applyACL works slightly different from the description in the CMIS domain model; we’ll cover the details in chapter 12. The specification also doesn’t define how the filename (cmis:contentStreamFileName) can be set with this binding when a document is created. OpenCMIS and DotCMIS add an extra <filename> tag to the document creation request. Note that this isn’t part of the CMIS standard but is understood by all OpenCMIS-based servers.

Exceptions in AtomPub

Exceptions are expressed by HTTP status codes. Unfortunately, some exceptions share the same status code. For example, a constraint exception and a versioning exception aren’t distinguishable by a CMIS client. Therefore, the OpenCMIS server framework sends additional information that clients can use to figure out the right exception type. This isn’t part of the CMIS standard, but the OpenCMIS and the DotCMIS client libraries interpret this additional information, if they’re present; thus, this is more of a recommendation at this point.

The AtomPub service document and URL templates

The entry point for CMIS clients is the service document. This XML document lists all available repositories, describes their capabilities, and provides URLs and URL templates for Atom collections, feeds, and entries. A CMIS client can navigate from here, for example, to the root folder or the types collection. The URL templates allow clients to directly access the Atom entry of a CMIS object by its ID or its path.

Let’s assume the URL template to get an object by ID looks like this:

http://example.com/repository/id?id={id}&filter={filter}
          &includeAllowableActions={includeAllowableActions}
          &includeACL={includeACL}
          &includePolicyIds={includePolicyIds}
          &includeRelationships={includeRelationships}
          &renditionFilter={renditionFilter}

The parts in curly brackets have to be replaced by the client with parameter values. If a client doesn’t provide a value for a parameter (that is, it sends an empty string), the repository has to assume the default value for this parameter, which is defined in the specification.

Let’s look at a specific example. To select the document with the object ID 123456 with all default parameter values, the client must generate this URL:

http://example.com/repository/id?id=123456
          &filter=&includeAllowableActions=&includeACL=&
          includePolicyIds=&includeRelationships=&renditionFilter=

The repository returns an Atom entry with the details of this document. (See the example in listing 11.2.)

AtomPub links

Most CMIS operations aren’t directly accessible from the service document. For example, to access the content of a document, the client must first get the document’s Atom entry. The Atom entry contains a link to the content. What this content link looks like is repository-specific and can’t be guessed by the client (and therefore must be treated by clients as opaque). That is, two HTTP calls are necessary to access the content. Libraries like OpenCMIS cache these links and drastically reduce the number of repeat calls to the repository.

If you know AtomPub, you’re already familiar with CMIS requests and responses. You’ll notice a few additional CMIS-specific links, though. You can look them up in the specification, but most of them are self-explanatory. You might also notice the XML namespace http://docs.oasis-open.org/ns/cmis/restatom/200908/, which is often used with the namespace prefix cmisra. XML tags with this namespace encapsulate CMIS-specific data structures, which are defined in the CMIS XML schema. We’ll talk about this schema a bit later in this chapter.

CRUD operations (create, read, update, and delete)

To update properties or delete an object, the client has to get the Atom entry and use the URL of the self link in the entry to make an HTTP PUT (or, respectively, an HTTP DELETE) request. The payload of the HTTP PUT request is an Atom entry that contains all the properties that should be updated.

To create an object, the client must send an HTTP POST request either to the URL of the prospective parent folder or to the Unfiled Collection if the object shouldn’t be filed. (You can find the URL of the Unfiled Collection in the service document.) The payload of the HTTP POST request is an Atom entry that describes the new object. If the object is a document, the content can optionally be embedded as a Base64-encoded string into this entry to prevent the need for a second PUT request dedicated to sending the binary content.

Clients and repositories can extend an Atom entry with additional data that is specified neither in Atom nor in the CMIS specification. For example, a repository could expose a link in an Atom entry to a feature that is repository-specific. If a client or a repository doesn’t understand such an extension, it should ignore it. We’ll talk more about extensions in the upcoming schema section. Listing 11.2 shows the AtomPub version of the same response we showed you for Web Services in listing 11.1.

Listing 11.2. Example of an XML response for a typical getObjects request (AtomPub)

11.2.3. The Browser binding

The objective of the Browser binding is to enable a JavaScript application in a web browser to access data in a CMIS repository. The binding only makes use of features that are available in the HTML and JavaScript specifications. It only uses the HTTP methods GET and POST: GET for requests that read data, and POST for requests that create, modify, or delete data. CMIS repositories return JSON responses as well as binary contents of documents. CMIS clients use URL parameters and HTML form data to communicate with the repository. Multipart messages are used to transport content from the client to the repository. A simple HTML form is sufficient to create a document in a CMIS repository.

The Browser binding covers the entire specification. There are no restrictions as in AtomPub, so in that respect the feature set is comparable with the Web Services binding. This includes the error handling. The Browser binding uses the same HTTP status codes as AtomPub but additionally sends a JSON response that contains the exception type and a message. HTTP status codes can be tricky in a browser application, but adding the parameter suppressResponseCodes with the value true to a URL can turn them off. The repository will then always return the HTTP status code 200.

The service document

In contrast to those in the AtomPub binding, the URLs of this binding are entirely predictable. That is, the specification defines URL patterns that work for all repositories. Similar to the AtomPub binding, the application must first get the service document. The service document contains information about all repositories available at this endpoint, two base URLs per repository. One URL is called the repository URL and the other one is called the root folder URL. The repository URL is used for all requests that are independent of the folder hierarchy, such as accessing or changing type definitions, performing a query, or getting content changes. A URL that is derived from the root folder URL always addresses an object, either by its ID or its path. The term root folder URL is a bit misleading because unfiled objects can also be addressed with this URL, so don’t be confused. To select an object by path, the object’s path is attached to the root folder URL.

To select an object by ID, the URL parameter objectId with the object’s ID is attached to the root folder URL. If the parameter objectId is set, it takes precedence over the path.

Let’s assume the root folder URL is http://example.com/repository/root. To select the document with the object ID 123456 and the path /myfolder/doc.txt, the following three URLs would work:

This one is by ID:

http://example.com/repository/root?objectId=123456

This one is by path:

http://example.com/repository/root/myfolder/doc.txt

In this one, the objectId parameter wins over the path:

http://example.com/repository/root/another/path?objectId=123456

Such URLs are called object URLs. If an object URL points to a document, the content of this document is returned by default. If it points to a folder, the children of this folder are the default return type. For all other base types, the object details are returned.

A client can specify which aspect of the object the repository should return by setting the parameter cmisselector. For example, a URL that gets the object details of a document could look like this:

http://example.com/repository/root?objectId=123456&cmisselector=object

And a URL to get the versions of a document could look like this:

http://example.com/repository/root/myfolder/doc.txt
          ?cmisselector=versions

Other URL parameters are similar to the parameters in the AtomPub URL templates. Property filters can be defined; allowable actions, ACLs, and policies can be turned on and off; a rendition filter can be set; and so on. For operations that return lists, such as getChildren, the offset, the length, the order of the list, and other things can be defined. The official CMIS 1.1 specification is the best complete reference for all the supported parameters and operations.

The succinct feature

A feature that is unique to the Browser binding is the succinct flag. All bindings transport for each property the property ID, the data type, the query name, the display name, the local name, and the value. That makes it easier for clients that don’t know the type definition of the object to work with these properties. But if the client knows the type definition, this is extra weight. The succinct parameter with the value true can be attached to all Browser binding URLs that return objects. The repository then only sends the property ID and the value, which makes the response more compact.

Try capturing a URL from the CMIS Workbench, and open in it a web browser. The Workbench always sets the succinct flag. Remove that flag from the URL, and reload the URL in the web browser. You’ll see that the response is now considerably larger.

CRUD operations

Operations that create, read, update, or delete objects use HTTP POST instead of HTTP GET. Data is transmitted in the same format that web browsers use to send HTML form data to a server. The form data must be URL encoded or sent as a multipart message. If content is attached to the request, then it must be a multipart request. (Thus, that only applies to the operations createDocument, setContentStream, appendContentStream, and checkIn.)

To indicate which operation should be invoked, the parameter cmisaction must be included. If a new document should be created, the value of cmisaction must be createDocument. To delete an object, cmisaction must be delete, and so on. The CMIS specification defines a cmisaction value for each operation as well as all other required and optional parameters.

Complex data structures are broken down to multiple parameters and parameter names with indexes. For example, to transmit the two base properties for creating a document (cmis:name and cmis:objectTypeId), the four properties shown in table 11.1 are required.

Table 11.1. Example parameters and values for createDocument

Parameter name

Parameter value

propertyId[0] cmis:name
propertyValue[0] myNewDocument.txt
propertyId[1] cmis:objectTypeId
propertyValue[1] cmis:document

You need a parameter pair (propertyId and propertyValue) to set one single-value property. The indexes indicate which parameters belong together, but the order doesn’t matter. This pattern is used for all complex data structures and lists such as ACLs or lists of object IDs or change tokens.

Transporting parameter names and values

At first glance, it looks unnecessarily complex to split a property into two parameters. Wouldn’t it be simpler to use the property ID as the parameter name?

It would, but that could lead to ambiguities. Here’s the reason why. The HTML specification says parameter names are case insensitive but property IDs are case sensitive. If a repository provided a type with two properties that differed only in the capitalization of the property ID, the client (such as a web browser) would normalize the parameter names, and it wouldn’t be possible to identify which property the application meant. The chance of such a situation occurring isn’t very high, but to prevent any kind of ambiguity, the Technical Committee fixed all parameter names.

Apart from that, parameter names in multipart messages should only use 7-bit ASCII characters because they’re used in HTTP headers. Property IDs with characters outside this charset are very likely, so it’s better to avoid compatibility issues and use fixed parameter names instead.

As with the other two bindings, you can add JSON structures that aren’t defined in the CMIS specification. Clients that don’t understand these should ignore them. The names of these extensions should be chosen carefully, though. In the other two bindings, the XML namespace can distinguish an extension tag from a CMIS or an Atom tag. Because JSON has no namespaces, the names should be as unique as possible. Future versions of CMIS may introduce more elements, and a name clash could lead to incompatibilities.

To learn more about the Browser binding and how to use it, see appendix D. It shows how to build a JavaScript application that accesses a CMIS repository. It also demonstrates how to use JSON-P and callbacks to work with a repository that’s hosted on a different server. In chapter 12, we cover user authentication and CSRF attack protection.

JSON create request examples

This section shows two examples of JSON requests. The first is an extremely simple example of createFolder:

cmisaction=createFolder&
  propertyId[0]=cmis%3AobjectTypeId&
  propertyValue[0]=cmis%3Afolder&
  propertyId[1]=cmis%3Aname&
  propertyValue[1]=myFolder&
  succinct=true

The second is a more complicated example of a createDocument multipart message:

--aPacHeCheMIStryoPEncmiS6a5a1a37createDocument13b766ab8a531763c9a
Content-Disposition: form-data; name="cmisaction"
Content-Type: text/plain; charset=utf-8

createDocument
--aPacHeCheMIStryoPEncmiS6a5a1a37createDocument13b766ab8a531763c9a
Content-Disposition: form-data; name="propertyId[0]"
Content-Type: text/plain; charset=utf-8

cmis:objectTypeId
--aPacHeCheMIStryoPEncmiS6a5a1a37createDocument13b766ab8a531763c9a
Content-Disposition: form-data; name="propertyValue[0]"
Content-Type: text/plain; charset=utf-8

cmis:document
--aPacHeCheMIStryoPEncmiS6a5a1a37createDocument13b766ab8a531763c9a
Content-Disposition: form-data; name="propertyId[1]"
Content-Type: text/plain; charset=utf-8

cmis:name
--aPacHeCheMIStryoPEncmiS6a5a1a37createDocument13b766ab8a531763c9a
Content-Disposition: form-data; name="propertyValue[1]"
Content-Type: text/plain; charset=utf-8

myDoc.txt
--aPacHeCheMIStryoPEncmiS6a5a1a37createDocument13b766ab8a531763c9a
Content-Disposition: form-data; name="versioningState"
Content-Type: text/plain; charset=utf-8

none
--aPacHeCheMIStryoPEncmiS6a5a1a37createDocument13b766ab8a531763c9a
Content-Disposition: form-data; name="content"; filename=myDoc.txt
Content-Type: text/plain
Content-Transfer-Encoding: binary

Hello World!
--aPacHeCheMIStryoPEncmiS6a5a1a37createDocument13b766ab8a531763c9a--
JSON object response example

Listing 11.3 shows a typical example of a response for requested CMIS object details via the Browser binding, with the succinct flag set to true.

Listing 11.3. JSON object response

To build compatible clients and servers, these XML and JSON responses must be clearly defined. The next section explains the CMIS schemas that provide these definitions.

11.3. CMIS schemas and schema extensions

The CMIS specification defines two schemas: an XML schema for the Web Services and AtomPub bindings and the Orderly (JSON) schema for the Browser binding. The schemas define the structure, restrictions, and extension points of the XML and JSON serialization of the CMIS data. The schemas are almost equivalent.

The XML schema was introduced with CMIS 1.0 and slightly extended in CMIS 1.1. The JSON schema came with CMIS 1.1. It’s possible to translate any CMIS XML structure into JSON, but not necessarily vice versa because the succinct feature exists only for the Browser binding.

11.3.1. XML schema

Reading and understanding the XML schema is straightforward, if you’re generally familiar with XML schemas. The XSD files are part of the CMIS specification. The schema is broken into the following three files:

  • CMIS-Core.xsd contains the core definitions and is used by the Web Services and AtomPub bindings.
  • CMIS-Messaging.xsd adds message definitions for the Web Services binding.
  • CMIS-RestAtom.xsd contains XML definitions used only by the AtomPub binding.
JSON schema

JSON has no comparable schema standard. There are a few different initiatives, but none of them have been widely accepted yet. The CMIS Technical Committee decided to adopt and extend Orderly (http://orderly-json.org/). Orderly describes the structure of a JSON document in a simple format. The original Orderly specification by Lloyd Hilaiel wasn’t sufficient for CMIS, and the Technical Committee had to add a few features to it. The Orderly specification that is used by CMIS can be found in an appendix of the CMIS specification. To understand the CMIS Orderly schema, it’s recommended that you pull down a copy and scan through it.

Schema extension points

The CMIS schema defines several extension points, where clients and repositories can stick extra data. CMIS structures are extensible if they contain an Any element in the XML schema or if the structure in the Orderly schema ends with *.

These extension points are meant to work across all bindings so a developer can implement a binding-agnostic application with extensions. The other extensions that we’ve mentioned so far were binding-specific (for example, an additional Atom link) and are of limited use.

Repository extensions

Extensions can be useful for repository vendors to expose additional features that aren’t covered by CMIS. Generic CMIS clients ignore them, and specific clients can make use of the features without switching the protocol. But if an additional feature can be mapped to a CMIS structure—for example, to a secondary type—it’s usually better to do this. It eases the life of the application developers significantly.

In CMIS 1.0 it wasn’t possible for a client to detect up front whether a repository supported a specific non-CMIS feature. That changed with CMIS 1.1. A CMIS 1.1 repository’s info may list all additional specifications that are supported by the repository on top of CMIS. Such a feature doesn’t necessarily depend on a schema extension. It might, for example, indicate that a specific type is available or define specific semantics for certain properties or secondary types. But if there are schema extensions, a CMIS 1.1 repository should announce those in the repository info.

Which binding should I use?

Answering this question properly depends on the repository, the environment, and the library you’re using.

The Browser binding is the fastest and most lightweight binding. If it’s supported on both ends, it’s the best choice for all kinds of applications. The most common binding at the moment (available on all CMIS servers) is the AtomPub binding. It’s usually faster than the Web Services binding and supported in environments that don’t have a Web Services stack. Note that there are repositories with broken (not conforming 100%) AtomPub binding implementations, most notably SharePoint 2010.

The Web Services binding is the last resort. Most implementations are stable and correct but comparatively slow. On the upside, in environments with a Web Services infrastructure, this binding may be easy to implement and integrate.

Now let’s jump back from the level of bytes on the wire and look into the OpenCMIS low-level API.

11.4. The OpenCMIS low-level API

When you compare the bindings with the OpenCMIS, DotCMIS, and ObjectiveCMIS APIs, you might notice a disconnection. The APIs provide an object-oriented interface with a lot of convenience, simplified data structures, and high-level operations that don’t exist in CMIS. On the other hand, these APIs hide extension points and access to the data structures that are transferred over the wire.

It turns out that there’s a layer between the bindings and these APIs called the low-level API. The low-level API provides a set of interfaces and operations that model all the services and operations in the CMIS specification one-to-one. For each of the nine CMIS services, there’s an interface. For each operation, there’s a method with exactly the same name and the same parameters, in the same order. The data objects are very close to the data structures used on the wire. The semantics and behavior are as described in the CMIS domain model. You can use the CMIS specification as a manual for these interfaces.

The high-level API with which you’re now familiar always calls the low-level API. That is, the high-level API never touches the bindings directly. The step from the low-level API to the bindings isn’t that big. Method calls are translated to HTTP requests, and the data is transformed to XML or JSON and back.

The low-level API gives you full control over the data you send and receive. It lets you access and exploit all CMIS extension points, for example. But there’s a price to pay. The code you have to write to use this API is much longer, and there are no safety nets. No trail markers help you ensure that you’re following the CMIS domain model path.

Let’s create a new folder in the root folder with the high-level API and then do the same with the low-level API. Here’s a typical example of using the high-level API that we’ve been using throughout the book:

Now let’s see what’s required to do this at the low level:

11.4.1. Reasons to use the low-level API

There’s usually no good reason to use the low-level API. The only semi-valid reason is to get hold of or set extension values. Before you start fiddling with the low-level API because you think there’s no other way, ask on the Apache Chemistry mailing list; there could be a more elegant way to solve your problem.

If you’re starting to get all misty, thinking you’ll never see this low-level API again, cheer up. If you’re planning to implement your own CMIS server with the OpenCMIS server framework (see chapter 14), your paths will cross again. These are the same interfaces and data classes that are used on the server side. But instead of calling the interface methods, you have to implement them.

With that knowledge about the bindings and the low-level API, you can now dive into the security and performance aspects of CMIS.

11.5. Summary

This chapter provided some high-level insight into the three CMIS bindings and their differences, principles of operation, and use cases. Knowing about the CMIS bindings will help you debug, tune, deploy, and, sometimes, develop CMIS applications. The chapter also described how to capture CMIS wire traffic, which is useful for learning about the bindings and for debugging your application.

The description of the bindings takes up more than 120 pages in the CMIS 1.1 specification plus schema and sample files. Due to space considerations, we could only provide an overview here. The specification itself is always the best and most authoritative reference for all operations, parameters, and patterns not covered here.

The following chapters cover security and performance topics. These can vary for each binding, and a basic understanding of how the bindings work is assumed for some details.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset