Using CMISQL from Java

Updated: March 18, 2024

CMISQL is the CMIS Query Language. It's possible to make CMISQL queries from Java code inside a Nuxeo bundle, much in the same way that you may used to make NXQL queries.

You can find out more about the CMIS support in Nuxeo Platform on the CMIS Page. You can find more information on the CMISQL syntax in the CMIS specification.


In Nuxeo CMISQL, JOINs are not enabled by default. They are only available if you set the nuxeo.conf property org.nuxeo.cmis.joins=true, and you are using the VCS storage backend. CMISQL JOINs are not supported with the DBS storage backend (MongoDB), because the underlying storage cannot do relational queries.

The following is a simple example of code making a query:

Constructing the CallContext

When constructing the CallContext, you should pass the ServletContext, HttpServletRequest and HttpServletResponse if available from your context. These are important for rendition URLs for instance.

Making a CMISQL Query

import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
import org.apache.chemistry.opencmis.commons.server.CallContext;
import org.apache.chemistry.opencmis.commons.server.CmisServiceFactory;
import org.apache.chemistry.opencmis.server.impl.CallContextImpl;
import org.apache.chemistry.opencmis.server.shared.TempStoreOutputStreamFactory;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.IterableQueryResult;
import org.nuxeo.ecm.core.opencmis.bindings.NuxeoCmisServiceFactory;
import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoCmisService;

public class CMISQuery {

    /** Threshold over which temporary files are not kept in memory. */
    public static final int THRESHOLD = 1024 * 1024;

    public CallContext getCallContext(CoreSession session) {
        ServletContext servletContext = null; // pass this if available
        HttpServletRequest request = null; // pass this if available
        HttpServletResponse response = null; // pass this if available
        CmisServiceFactory serviceFactory = new NuxeoCmisServiceFactory();
        TempStoreOutputStreamFactory streamFactory = TempStoreOutputStreamFactory.newInstance(
                null, THRESHOLD, -1, false);
        CallContextImpl callContext = new CallContextImpl(
                CallContext.BINDING_LOCAL, CmisVersion.CMIS_1_1,
                session.getRepositoryName(), servletContext, request, response,
                serviceFactory, streamFactory);
        callContext.put(CallContext.USERNAME, session.getPrincipal().getName());
        return callContext;

    public void query(CoreSession session) {
        NuxeoCmisService cmisService = new NuxeoCmisService(session);
        try {
            cmisService.setCallContext(getCallContext(session)); // pass also servlet info if available
            // example CMISQL query
            String query = "SELECT cmis:objectId, dc:title FROM cmis:document WHERE dc:title LIKE 'foo%'";
            boolean searchAllVersions = true;
            // use try-with-resources when calling cmisService.queryAndFetch for automatic closing
            try (IterableQueryResult result = cmisService.queryAndFetch(query, searchAllVersions)) {
                for (Map<String, Serializable> row : result) {
                    // do something with the result
        } finally { // you MUST always close cmisService in a finally block