CMIS mit Apache Chemistry – ein Praxisbeispiel

Seite 2: Client-Entwicklung

Inhaltsverzeichnis

Die Client-Schnittstelle gliedert sich in zwei Schichten. Die opencmis-Bindings (Java-Package org.apache.chemistry.opencmis.client.bindings) abstrahieren von den verwendeten Protokollen (AtomPub und SOAP) und setzen das CMIS-Modell auf Java-Klassen um. Ein Entwickler gibt beim Verbindungsaufbau an, welches Protokoll und welche Verbindungsparameter zu verwenden sind (URL zum Server, Benutzerkennung und Passwort). Diese Binding-Klassen sind reine Datenschnittstellen. Sie kapseln zwar das Protokoll ab, folgen aber nicht objektorientierten Prinzipien.

Ferner werden Entwickler für reale Anwendungen schnell bestimmte Komfortfunktionen vermissen. Häufig benötigen sie beispielsweise die Typinformationen, um IDs auf lesbare Namen umzusetzen oder um festzustellen, welchen Datentyp eine bestimmte Property besitzt. Ein clientseitiges Cachen der Typinformationen ist daher wünschenswert. Oft möchte man auch nicht nach jeder kleinen Änderung Daten zum Server senden, sondern mehrere Aufrufe aufsammeln und dann in einem Rutsch abschicken. Die CMIS-Client-API (org.apache.chemistry.opencmis.client.api) leistet das und bietet eine höhere Ebene mit CMIS-Objekten und -Methoden. Intern setzt sie auf das Client-Binding auf. Die meisten Anwendungen sollten die Client-API zur Integration verwenden. Ein kleiner Codeauschnitt kann einen Eindruck geben, wie die API zu verwenden ist. Wer tiefer einsteigen will, sei auf die Projekt-Website verwiesen. Auch die CMIS-Workbench verwendet diese API.

Ein Wort noch zur Programmierumgebung. Am schnellsten lässt sich eine Umgebung mit Apache Maven aufsetzen. Das Build-System wird auch intern zur Produktion von opencmis verwendet. Der Entwickler startet lediglich mit einer Konfigurationsdatei, Maven sorgt dann für den Download aller benötigten Bibliotheken aus öffentlichen Repositories und kann die passende Umgebung für Entwicklungswerkzeuge wie Eclipse erzeugen. Maven ist aber keine Voraussetzung. Der Programmierer kann auch mit Eclipse anfangen und sich manuell seinen Workspace einrichten oder andere Build-Werkzeuge verwenden. Das Package opencmis-ful-xxx.zip enthält alle benötigten Bibliotheken, die in ein Projekt einzubinden sind.

Der erste Schritt in einem CMIS-Client besteht immer im Aufbau der Verbindung zum Server. Dazu bedient man sich der Session-Klasse:

import org.apache.chemistry.opencmis.client.api.Session;
import org.apache.chemistry.opencmis.client.api.SessionFactory;
import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl;
import org.apache.chemistry.opencmis.commons.SessionParameter;
...
SessionFactory f = SessionFactoryImpl.newInstance();
Map<String, String> parameter = new HashMap<String, String>();

// user credentials (not needed for in-memory)
parameter.put(SessionParameter.USER, "ix");
parameter.put(SessionParameter.PASSWORD, "ix");

// connection settings
// AtomPub
parameter.put(SessionParameter.BINDING_TYPE,
BindingType.ATOMPUB.value());
parameter.put(SessionParameter.REPOSITORY_ID, "A1");
parameter.put(SessionParameter.ATOMPUB_URL,
"http://localhost:8080/inmemory/atom");

Im Parameter-Objekt gibt der Entwickler Verbindungsinformationen wie Serveradresse, Benutzer und Passwort an. Für Webservices benötigt er die Adresse jedes einzelnen Web-Services.

     parameter.put(SessionParameter.BINDING_TYPE, 
BindingType.WEBSERVICES.value());
parameter.put(SessionParameter.REPOSITORY_ID, "A1");
parameter.put(SessionParameter.WEBSERVICES_ACL_SERVICE,
"http://localhost:8080/inmemory/services/ACLService?wsdl");
parameter.put(SessionParameter.WEBSERVICES_DISCOVERY_SERVICE,
"http://localhost:8080/inmemory/services/DiscoveryService?wsdl");
parameter.put(SessionParameter.WEBSERVICES_MULTIFILING_SERVICE,
"http://localhost:8080/inmemory/services/MultiFilingService?wsdl");
parameter.put(SessionParameter.WEBSERVICES_NAVIGATION_SERVICE,
"http://localhost:8080/inmemory/services/NavigationService?wsdl");
parameter.put(SessionParameter.WEBSERVICES_OBJECT_SERVICE,
"http://localhost:8080/inmemory/services/ObjectService?wsdl");
parameter.put(SessionParameter.WEBSERVICES_POLICY_SERVICE,
"http://localhost:8080/inmemory/services/PolicyService?wsdl");
parameter.put(SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE,
"http://localhost:8080/inmemory/services/RelationshipService?wsdl");
parameter.put(SessionParameter.WEBSERVICES_REPOSITORY_SERVICE,
"http://localhost:8080/inmemory/services/RepositoryService?wsdl");
parameter.put(SessionParameter.WEBSERVICES_VERSIONING_SERVICE,
"http://localhost:8080/inmemory/services/VersioningService?wsdl");

Der eigentliche Verbindungsaufbau erfolgt dann mit:

session = f.createSession(parameter);

Mit der Session hat der Programmierer Zugriff auf die weiteren Funktionen des Servers. Er kann sich etwa die RepositoryInfo holen und anzeigen lassen:

     RepositoryInfo repoInfo = session.getRepositoryInfo();
System.out.println("Repository Name: " + repoInfo.getName());
System.out.println("Description: " + repoInfo.getDescription());
// ...

oder sich den Inhalt des Root-Folders auflisten lassen:

     Folder rootFolder = session.getRootFolder();
ItemIterable<CmisObject> children = rootFolder.getChildren();
System.out.println("Name: " + obj.getName());
System.out.println("Id: " + obj.getId());
System.out.println("Basistyp: " + obj.getBaseType().getDisplayName());
// ...

Nach dem gleichen Muster kann man weiter verfahren, um den Content eines Dokuments zu holen, Queries abzusetzen oder Ähnliches. Die CMIS-Workbench stellt eine Fundgrube an Beispielcode dar, die zur Orientierung für eigene Zwecke helfen kann.