SlideShare a Scribd company logo
OpenCMIS Introduction2FlorianMüllerSoftware Architect, Alfrescotwitter: @florian_mueller
OpenCMIS3OpenCMIS is a sub-project ofApache Chemistry is an umbrella project for CMIS implementationsJavaPythonPHPServer and client implementation of the CMIS specification
OpenCMIS goals4OpenCMIS hides the bindings and provides binding agnostic APIs and SPIsOpenCMIS adds a lot of convenienceDevelopers should focus on the domain model!
Current state5OpenCMIS has contributors from Alfresco, Open Text, SAP and NuxeoOpenCMIS 0.1.0 has been released in SeptemberThe code is pretty mature and stable and has been tested against all major ECM vendorsThe some areas of client API will be refactored and simplified within the next monthOpenCMIS is an active Open Source project
OpenCMIS Architecture6Server, client, common and test modules
OpenCMIS Server7One Servlet per binding that map the requests to an SPIRepository vendors have to implement two interfacesNot our focus today…… for CMIS connector developersSOAPAtomPubCMIS Service FactoryCMIS ServiceCMIS ServiceCMIS Service
OpenCMIS client8Client APIOO APIEasy to useBuild-in cachingClient Binding APILow-levelVery close to the CMIS specificationMore control, less comfort… for CMIS application developers
Let’s start9Download it! http://incubator.apache.org/chemistry/opencmis.htmlUse Maven!Build the latest and greatest! http://incubator.apache.org/chemistry/opencmis-how-to-build.htmlGet hold of the OpenCMIS Jars<dependency>    <groupId>org.apache.chemistry.opencmis</groupId>    <artifactId>chemistry-opencmis-client-impl</artifactId>    <version>0.1.0-incubating</version></dependency>
Connect to a repository – Variant 110Map<String, String> parameter = new HashMap<String, String>();parameter.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());parameter.put(SessionParameter.ATOMPUB_URL, "http://cmis.alfresco.com/service/cmis");parameter.put(SessionParameter.REPOSITORY_ID, "84ccfe80-b325-4d79-ab4d-080a4bdd045b");parameter.put(SessionParameter.USER, "admin");parameter.put(SessionParameter.PASSWORD, "admin");SessionFactory factory = SessionFactoryImpl.newInstance();Session session = factory.createSession(parameter);CMIS is stateless!OpenCMIS introduces a session concept to support caching.
Connect to a repository – Variant 211Map<String, String> parameter = new HashMap<String, String>();parameter.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());parameter.put(SessionParameter.ATOMPUB_URL, "http://cmis.alfresco.com/service/cmis");parameter.put(SessionParameter.REPOSITORY_ID, "84ccfe80-b325-4d79-ab4d-080a4bdd045b");parameter.put(SessionParameter.USER, "admin");parameter.put(SessionParameter.PASSWORD, "admin");SessionFactory factory = SessionFactoryImpl.newInstance();List<Repository> repositories = factory.getRepositories(parameter);Session session = repositories.get(0).createSession();Alfresco only exposes one repository!This is the simplest way to create a session.
Walking around12RepositoryInfori = session.getRepositoryInfo();String id = ri.getId();String name = ri.getName();Folder rootFolder = session.getRootFolder();String rootFolderId = rootFolder.getId();for(CmisObject object: rootFolder.getChildren()) {    String name = object.getName();if(objectinstanceof Document) {        Document doc = (Document) object;        long size = doc.getContentStreamLength();       }}
Walking around13ObjectId id = session.createObjectId(“1234567890”):CmisObject object = session.getObject(id);// CmisObject object = session.getObjectByPath(“/my/path/doc”);String creator = object.getCreatedBy();Property<?> myProp = object.getProperty(“my:prop”);String propId      = myProp.getId();String displayName = myProp.getDefinition().getDisplayName();String queryName   = myProp.getDefinition().getQueryName();PropertyTypedatatype = myProp.getType();Object value       = myProp.getFirstValue();
Caching14Repository InfoRetrieved and cached during session creationWill not be updated during the lifetime of a sessionType DefinitionsCached whenever a type definition is retrieved –explicitly or implicitlyWill not be updated during the lifetime of a session(OpenCMIS can be forced to forget Repository Infos and Type Definitions. That is similar to creating a new session.)What is cached and when?
Caching15CMIS ObjectsObject caching is turned on by defaultLRU cache with 1000 objectsgetObject() might return stale objectsif an old copy is found in the cacheRefresh objects manuallyCmisObject object = session.getObject(id);	object.refresh(); object.refreshIfOld(60 * 1000); What is cached and when?
Caching16Turn caching offsession.getDefaultContext().setCacheEnabled(false); Turn caching off for one requestOperationContextoc = session.createOperationContext(); oc.setCacheEnabled(false);CmisObject object = session.getObject(id, oc); Control the cache!
CMIS Workbench17A tool for CMIS developers
Demos18Children and parentsPagingPropertiesContentQueryCreate, update and delete foldersCreate, update and delete documentsCode samples
Navigation19import org.apache.chemistry.opencmis.commons.*;import org.apache.chemistry.opencmis.commons.data.*;import org.apache.chemistry.opencmis.commons.enums.*;import org.apache.chemistry.opencmis.client.api.*;// get root folderFolder root = session.getRootFolder();String rootFolderName = root.getName();println "Root folder: ${rootFolderName}"// print root folder childrenfor(CmisObject object: root.getChildren()) {    String name = object.getName();    String typeId =  object.getType().getId();    String path = object.getPaths().get(0);println "${name} ${typeId} (${path})"    // get parents    /*for(CmisObject parent: object.getParents()) {        String parentName = parent.getName();println " Parent: ${parentName}"    }    */}
Paging20import org.apache.chemistry.opencmis.commons.*;import org.apache.chemistry.opencmis.commons.data.*;import org.apache.chemistry.opencmis.commons.enums.*;import org.apache.chemistry.opencmis.client.api.*;Folder root = session.getRootFolder();printList( root.getChildren() )//printList( root.getChildren().getPage(3) )//printList( root.getChildren().skipTo(2) )//printList( root.getChildren().skipTo(2).getPage(3) )void printList(ItemIterable<CmisObject> list) {list.each { println "${it.name} ${it.type.id}" }    long numItems = list.getTotalNumItems();booleanhasMore = list.getHasMoreItems();println "--------------------------------------"println "Total number: ${numItems}"println "Has more: ${hasMore}" println "--------------------------------------"}

More Related Content

OpenCMIS Part 1

  • 2. OpenCMIS3OpenCMIS is a sub-project ofApache Chemistry is an umbrella project for CMIS implementationsJavaPythonPHPServer and client implementation of the CMIS specification
  • 3. OpenCMIS goals4OpenCMIS hides the bindings and provides binding agnostic APIs and SPIsOpenCMIS adds a lot of convenienceDevelopers should focus on the domain model!
  • 4. Current state5OpenCMIS has contributors from Alfresco, Open Text, SAP and NuxeoOpenCMIS 0.1.0 has been released in SeptemberThe code is pretty mature and stable and has been tested against all major ECM vendorsThe some areas of client API will be refactored and simplified within the next monthOpenCMIS is an active Open Source project
  • 5. OpenCMIS Architecture6Server, client, common and test modules
  • 6. OpenCMIS Server7One Servlet per binding that map the requests to an SPIRepository vendors have to implement two interfacesNot our focus today…… for CMIS connector developersSOAPAtomPubCMIS Service FactoryCMIS ServiceCMIS ServiceCMIS Service
  • 7. OpenCMIS client8Client APIOO APIEasy to useBuild-in cachingClient Binding APILow-levelVery close to the CMIS specificationMore control, less comfort… for CMIS application developers
  • 8. Let’s start9Download it! http://incubator.apache.org/chemistry/opencmis.htmlUse Maven!Build the latest and greatest! http://incubator.apache.org/chemistry/opencmis-how-to-build.htmlGet hold of the OpenCMIS Jars<dependency> <groupId>org.apache.chemistry.opencmis</groupId> <artifactId>chemistry-opencmis-client-impl</artifactId> <version>0.1.0-incubating</version></dependency>
  • 9. Connect to a repository – Variant 110Map<String, String> parameter = new HashMap<String, String>();parameter.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());parameter.put(SessionParameter.ATOMPUB_URL, "http://cmis.alfresco.com/service/cmis");parameter.put(SessionParameter.REPOSITORY_ID, "84ccfe80-b325-4d79-ab4d-080a4bdd045b");parameter.put(SessionParameter.USER, "admin");parameter.put(SessionParameter.PASSWORD, "admin");SessionFactory factory = SessionFactoryImpl.newInstance();Session session = factory.createSession(parameter);CMIS is stateless!OpenCMIS introduces a session concept to support caching.
  • 10. Connect to a repository – Variant 211Map<String, String> parameter = new HashMap<String, String>();parameter.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());parameter.put(SessionParameter.ATOMPUB_URL, "http://cmis.alfresco.com/service/cmis");parameter.put(SessionParameter.REPOSITORY_ID, "84ccfe80-b325-4d79-ab4d-080a4bdd045b");parameter.put(SessionParameter.USER, "admin");parameter.put(SessionParameter.PASSWORD, "admin");SessionFactory factory = SessionFactoryImpl.newInstance();List<Repository> repositories = factory.getRepositories(parameter);Session session = repositories.get(0).createSession();Alfresco only exposes one repository!This is the simplest way to create a session.
  • 11. Walking around12RepositoryInfori = session.getRepositoryInfo();String id = ri.getId();String name = ri.getName();Folder rootFolder = session.getRootFolder();String rootFolderId = rootFolder.getId();for(CmisObject object: rootFolder.getChildren()) { String name = object.getName();if(objectinstanceof Document) { Document doc = (Document) object; long size = doc.getContentStreamLength(); }}
  • 12. Walking around13ObjectId id = session.createObjectId(“1234567890”):CmisObject object = session.getObject(id);// CmisObject object = session.getObjectByPath(“/my/path/doc”);String creator = object.getCreatedBy();Property<?> myProp = object.getProperty(“my:prop”);String propId = myProp.getId();String displayName = myProp.getDefinition().getDisplayName();String queryName = myProp.getDefinition().getQueryName();PropertyTypedatatype = myProp.getType();Object value = myProp.getFirstValue();
  • 13. Caching14Repository InfoRetrieved and cached during session creationWill not be updated during the lifetime of a sessionType DefinitionsCached whenever a type definition is retrieved –explicitly or implicitlyWill not be updated during the lifetime of a session(OpenCMIS can be forced to forget Repository Infos and Type Definitions. That is similar to creating a new session.)What is cached and when?
  • 14. Caching15CMIS ObjectsObject caching is turned on by defaultLRU cache with 1000 objectsgetObject() might return stale objectsif an old copy is found in the cacheRefresh objects manuallyCmisObject object = session.getObject(id); object.refresh(); object.refreshIfOld(60 * 1000); What is cached and when?
  • 15. Caching16Turn caching offsession.getDefaultContext().setCacheEnabled(false); Turn caching off for one requestOperationContextoc = session.createOperationContext(); oc.setCacheEnabled(false);CmisObject object = session.getObject(id, oc); Control the cache!
  • 16. CMIS Workbench17A tool for CMIS developers
  • 17. Demos18Children and parentsPagingPropertiesContentQueryCreate, update and delete foldersCreate, update and delete documentsCode samples
  • 18. Navigation19import org.apache.chemistry.opencmis.commons.*;import org.apache.chemistry.opencmis.commons.data.*;import org.apache.chemistry.opencmis.commons.enums.*;import org.apache.chemistry.opencmis.client.api.*;// get root folderFolder root = session.getRootFolder();String rootFolderName = root.getName();println "Root folder: ${rootFolderName}"// print root folder childrenfor(CmisObject object: root.getChildren()) { String name = object.getName(); String typeId = object.getType().getId(); String path = object.getPaths().get(0);println "${name} ${typeId} (${path})" // get parents /*for(CmisObject parent: object.getParents()) { String parentName = parent.getName();println " Parent: ${parentName}" } */}
  • 19. Paging20import org.apache.chemistry.opencmis.commons.*;import org.apache.chemistry.opencmis.commons.data.*;import org.apache.chemistry.opencmis.commons.enums.*;import org.apache.chemistry.opencmis.client.api.*;Folder root = session.getRootFolder();printList( root.getChildren() )//printList( root.getChildren().getPage(3) )//printList( root.getChildren().skipTo(2) )//printList( root.getChildren().skipTo(2).getPage(3) )void printList(ItemIterable<CmisObject> list) {list.each { println "${it.name} ${it.type.id}" } long numItems = list.getTotalNumItems();booleanhasMore = list.getHasMoreItems();println "--------------------------------------"println "Total number: ${numItems}"println "Has more: ${hasMore}" println "--------------------------------------"}
  • 20. Properties21import org.apache.chemistry.opencmis.commons.*;import org.apache.chemistry.opencmis.commons.data.*;import org.apache.chemistry.opencmis.commons.enums.*;import org.apache.chemistry.opencmis.client.api.*;CmisObject object = session.getObjectByPath("/User Homes/florian/Test Folder/MyText");for(Property<?> property: object.getProperties()) { String propId = property.getId(); String displayName = property.getDefinition().getDisplayName(); String queryName = property.getDefinition().getQueryName();PropertyTypedatatype = property.getType(); Object value = property.getFirstValue();println "${displayName}: ${value}"println " Data type: ${datatype}"println " Id: ${propId}"println " Query name: ${queryName}"println ""}
  • 21. Content22import org.apache.chemistry.opencmis.commons.*;import org.apache.chemistry.opencmis.commons.data.*;import org.apache.chemistry.opencmis.commons.enums.*;import org.apache.chemistry.opencmis.client.api.*;CmisObject object = session.getObjectByPath("/User Homes/florian/Test Folder/MyText");if(!(objectinstanceof Document)) { throw new Exception("Not a document!");}Document doc = (Document) object;ContentStream content = doc.getContentStream();if(content == null) { throw new Exception("Document has no content!");}String filename = content.getFileName();String mimeType = content.getMimeType();long length = content.getLength();InputStream stream = content.getStream();println "File: ${filename}"println "MIME Type: ${mimeType}"println "Size: ${length} bytes"println "Has stream: " + (stream != null)
  • 22. Query23import org.apache.chemistry.opencmis.commons.*import org.apache.chemistry.opencmis.commons.data.*import org.apache.chemistry.opencmis.commons.enums.*import org.apache.chemistry.opencmis.client.api.*String cql = "SELECT cmis:objectId, cmis:name, cmis:contentStreamLength FROM cmis:document";ItemIterable<QueryResult> results = session.query(cql, false);//ItemIterable<QueryResult> results = session.query(cql, false).getPage(10);//ItemIterable<QueryResult> results = session.query(cql, false).skipTo(10).getPage(10);for(QueryResult hit: results) { for(PropertyData<?> property: hit.getProperties()) { String queryName = property.getQueryName(); Object value = property.getFirstValue();println "${queryName}: ${value}" }println "--------------------------------------"}
  • 23. Folders24import org.apache.chemistry.opencmis.commons.*;import org.apache.chemistry.opencmis.commons.data.*;import org.apache.chemistry.opencmis.commons.enums.*;import org.apache.chemistry.opencmis.client.api.*;Folder root = session.getRootFolder();// create a new folderMap<String, Object> properties = new HashMap<String, Object>();properties.put("cmis:objectTypeId", "cmis:folder");properties.put("cmis:name", "a new folder");Folder newFolder = root.createFolder(properties);printProperties(newFolder);// update propertiesMap<String, Object> updateproperties = new HashMap<String, Object>();updateproperties.put("cmis:name", "renamed folder");newFolder.updateProperties(updateproperties);newFolder.refresh();printProperties(newFolder);// delete foldernewFolder.deleteTree(true, UnfileObject.DELETE, true);
  • 24. Documents25import org.apache.chemistry.opencmis.commons.*;import org.apache.chemistry.opencmis.commons.data.*;import org.apache.chemistry.opencmis.commons.enums.*;import org.apache.chemistry.opencmis.commons.impl.dataobjects.*;import org.apache.chemistry.opencmis.client.api.*;Folder root = session.getRootFolder();// create a new documentString name = "myNewDocument.txt";Map<String, Object> properties = new HashMap<String, Object>();properties.put("cmis:objectTypeId", "cmis:document");properties.put("cmis:name", name);byte[] content = "Hello World!".getBytes();InputStream stream = new ByteArrayInputStream(content);ContentStreamcontentStream = new ContentStreamImpl(name, content.length, "text/plain", stream);Document newDoc = root.createDocument(properties, contentStream, VersioningState.MAJOR);printProperties(newDoc);// delete documentnewDoc.delete(true);void printProperties(CmisObject object) {object.properties.each { println "${it.id}: ${it.firstValue}" }println "--------------------------------------"}
  • 25. CMIS Extensions26CMIS specifies extension pointsArbitrary data can be attached to CMIS structuresClients and servers either understand the extension or ignore themAlfresco sends aspect data as CMIS extensionAlfresco will accept aspect data through CMIS extensionsThere will be an Alfresco addition to OpenCMISthat handles aspects How to get and set of aspect properties?