Devoxx08 - Nuxeo Core, JCR 2, CMIS

Post on 14-May-2015

2.235 views 0 download

Tags:

description

Nuxeo Core, JCR 2, CMIS: learn how to use content repositories APIs
 to store and manipulate rich documents.

Transcript of Devoxx08 - Nuxeo Core, JCR 2, CMIS

www.devoxx.com

Using content repositories: Nuxeo Core, JCR 2, CMIS

Florent GuillaumeHead of R&DNuxeo

www.devoxx.com

Overall presentation goal

Learn how to use content repositories APIsto store and manipulate rich documents

www.devoxx.com

Speaker’s qualificationsFlorent Guillaume is Head of R&D at Nuxeo, a leading vendor of Open Source ECM platforms

Florent Guillaume is a member of international normalization technical committees: JSR-283, Oasis CMIS

Florent Guillaume architected and wrote an ECM system (Nuxeo CPS) and is a lead architect on another (Nuxeo EP)

Florent Guillaume wrote a low-level storage engine for Nuxeo Core

3

www.devoxx.com

Store information

Attached file (binary stream)

Metadata

Retrieve information

Search

Security

Be visible and editable

Out of scope for a repository

4

What is a document?

www.devoxx.com

What is a “rich” document?Depends on your definition of “rich”

5

www.devoxx.com

What is a “rich” document?Depends on your definition of “rich”

5

www.devoxx.com

What is a “rich” document?Depends on your definition of “rich”

Associated binary streams

Multiple attached files

Vignettes

Renditions

Complex metadata

Lists of records

Sub-records (XML-like)

6

www.devoxx.com

What storage APIs?Filesystem

Relational database

JCR (JSR-170, JSR-283)

Nuxeo Core

CMIS

7

www.devoxx.com

FilesystemDecide where to store files

Decide how to uniquely identify files

Use java.io.FileOutputStream for binaries

Decide how to serialize metadata

All by hand

java.io.ObjectOutputStream, Serializable

etc.

8

www.devoxx.com

Read/write

Filesystem example

9

public void createDocument(Long id, String title) throws IOException { File file = new File(ROOT_DIR, id.toString()); OutputStream out = new FileOutputStream(file); try { out.write(title.getBytes("UTF-8")); } finally { out.close(); } }

public MyDocument getDocument(Long id) throws IOException { File file = new File(ROOT_DIR, id.toString()); InputStream in = new FileInputStream(file); try { byte[] bytes = new byte[100]; int n = in.read(bytes); String title = new String(bytes, "UTF-8"); MyDocument doc = new MyDocument(); doc.setId(id); doc.setTitle(title); return doc; } finally { in.close(); } }

www.devoxx.com

Filesystem drawbacksSimplistic, no actual model

Everything has to be done manually

No search

10

www.devoxx.com

Filesystem using JAXBMap Java objects to/from XML representations

Define a schema (model)

Marshall/Unmarshall using JAXB APIs

11

www.devoxx.com

Relational databaseJDBC

Hibernate

...other ORMs

JPA

12

www.devoxx.com

JDBCDefine a SQL model for your data

Tables, Columns, Data types

Decide where to store BLOBs

Column or filesystem

Emit SQL statements to do all read/write operations

13

www.devoxx.com

JDBC exampleClass defining the model

14

class MyDocument {

private Long id;

private String title;

public Long getId() { return id; } public void setId(Long id) { this.id = id; }

public String getTitle() { return title; } public void setTitle(String title) { this.title = title; }}

www.devoxx.com

Establish a connection, Write

JDBC example

15

public void init() throws ClassNotFoundException { Class.forName("com.myvendor.TheDriverClass"); } public Connection getConnection() throws SQLException { return DriverManager.getConnection("jdbc:myvendor:/my/database/info", "myLogin", "myPassword"); }

public void createDocument(Long id, String title) throws SQLException { PreparedStatement ps = null; Connection conn = getConnection(); try { ps = conn.prepareStatement("INSERT INTO MyDocuments (id, title) VALUES (?, ?)"); ps.setLong(1, id); ps.setString(2, title); ps.execute(); } finally { if (ps != null) ps.close(); conn.close(); } }

www.devoxx.com

Read

JDBC example

16

public MyDocument getDocument(Long id) throws SQLException { PreparedStatement ps = null; Connection conn = getConnection(); try { ps = conn.prepareStatement("SELECT title FROM MyDocuments WHERE id = ?"); ps.setLong(1, id); ResultSet rs = ps.executeQuery(); if (!rs.next()) { return null; } String title = rs.getString(1); MyDocument doc = new MyDocument(); doc.setId(id); doc.setTitle(title); return doc; } finally { if (ps != null) ps.close(); conn.close(); } }

www.devoxx.com

JDBC drawbacksStill very much manual

No document abstraction

Reads from ResultSets have to know proper types

17

www.devoxx.com

HibernateModel your documents as classes

Define an object-relational mapping in XML

Use Hibernate to automate read/writes

18

www.devoxx.com

Hibernate exampleXML configuration

19

<hibernate-mapping> <class name="example.MyDocument" table="DOCUMENTS"> <id name="id" column="DOC_ID"> <generator class="native"/> </id> <property name="title"/> </class></hibernate-mapping>

www.devoxx.com

Hibernate exampleRead/write

20

class DocumentManager {

public void createDocument(Long id, String title) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); MyDocument doc = new MyDocument(); doc.setId(id); doc.setTitle(title); session.save(doc); session.getTransaction().commit(); session.close(); }

public MyDocument getDocument(Long id) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); Query query = session.createQuery("FROM MyDocument WHERE id = :id"); query.setParameter("id", id); MyDocument doc = (MyDocument) query.uniqueResult(); session.getTransaction().commit(); session.close(); return doc; }}

www.devoxx.com

Hibernate drawbacksDocument classes have to be defined by hand

No standard, just application-defined classes

Object-relational mapping too flexible

Too much choice can be a curse

Binaries are still a problem (no streaming)

Hibernate’s “binary” is a byte[] → Memory hog

Blob support inconsistent

21

www.devoxx.com

JPAModel your documents as classes

Define an object-relational mapping using annotations

Use JPA to automate read/writes

22

www.devoxx.com

JPA exampleClass defining the model and the mapping

23

@Entityclass MyDocument {

private Long id;

private String title;

@Id public Long getId() { return id; } public void setId(Long id) { this.id = id; }

public String getTitle() { return title; } public void setTitle(String title) { this.title = title; }}

www.devoxx.com

JPA exampleRead/write

24

@Statelessclass DocumentManagerBean {

@PersistenceContext EntityManager em;

public void createDocument(Long id, String title) { MyDocument doc = new MyDocument(); doc.setId(id); doc.setTitle(title); em.persist(doc); }

public MyDocument getDocument(Long id) { return em.find(MyDocument.class, id); }

public List<MyDocument> listDocuments() { Query query = em.createQuery("SELECT doc FROM MyDocument doc"); return query.getResultList(); }}

www.devoxx.com

JPA drawbacksSame as Hibernate

Although annotations are very convenient

25

www.devoxx.com

Beyond mere storageStandard document abstraction

Security

Locking

Versioning

Full text search

Types and inheritance

Folders? ordering?

27

www.devoxx.com

JCRContent Repository API for Java™ Technology

JSR-170, released in June 2005

Initiated by Day Software

Also BEA, Documentum, FileNet, IBM, Oracle, Vignette and others

Apache Jackrabbit is the RI

28

www.devoxx.com

JCR goalsJava API

Fine-grained, hierarchical storage model

Be the “SQL” of hierarchical storage

Lots of functionality

29

www.devoxx.com

JCR featuresCRUD

Hierarchy of nodes

Simple properties, Lists, Binaries

Queries

Versioning, Locking, References, ...

30

www.devoxx.com

JCR 2JSR-283

First public review July 2007

Final release expected early 2009

Nuxeo is a contributor to the specification

31

www.devoxx.com

JCR 2 featuresFix JSR-170 inconsistencies

Several compliance levels

New property types

Improved features

Versioning, Access control, Observation

Retention & Hold

Shareable nodes

Java query API

32

www.devoxx.com

JCR – nodes and properties

33

Node Type

foo

Property Type

value

bar

childchild

www.devoxx.com

JCR – node hierarchy

34

(root)

Folder Folder

Document

Document

Folder

foo bar gee

File

docthing

vignette

www.devoxx.com

JCR – properties types

35

String

Binary

Date

Long

Double

Boolean

Name

Path

Reference

JCR 2

Decimal

WeakReference

URI

www.devoxx.com

JCR – hierarchy with properties

36

(root)

Folder Folder

Document

Document

String

my doc

String

...

Folder

foo bar gee

Date

2008-12-11

String

florentFile

String

img.png

Binary

<binary>

docthing

title descriptiondate creatorvignette

filename data

www.devoxx.com

JCR – node hierarchy

37

(root)

Folder Folder

Document

Document

title: my doc

description: ...

date: 2008-12-11

creator: florent

Folder

foo bar gee

File

filename: img.png

date: <binary>

docthing

vignette

www.devoxx.com

JCR – typesDefine the model

38

<my='http://my.example.com/ns'>

[my:document]- my:id (long) mandatory- my:title- my:description- my:creator- my:date (date)+ my:vignette (nt:resource)

www.devoxx.com

JCR – APIEstablish a connection

39

public Repository repository;

public javax.jcr.Session session;

public void init() throws IOException { repository = new TransientRepository(); }

public void open() throws LoginException, RepositoryException { Credentials credentials = new SimpleCredentials("username", "password".toCharArray()); session = repository.login(credentials); }

public void close() { session.logout(); }

www.devoxx.com

JCR – APIRead/write

40

public void createDocument(Long id, String title) throws RepositoryException { Node root = session.getRootNode(); Node doc = root.addNode(id.toString()); doc.setProperty("my:id", id); doc.setProperty("my:title", title); session.save(); }

public Node getDocument(Long id) throws RepositoryException { Node root = session.getRootNode(); Node doc = root.getNode(id.toString()); return doc; }

www.devoxx.com

JCR – APIQuery

41

public List<Node> getDocuments() throws RepositoryException { QueryManager queryManager = session.getWorkspace().getQueryManager(); Query query = queryManager.createQuery( "//element(*, my:document)", Query.XPATH); query = queryManager.createQuery( "SELECT * from my:document", Query.SQL); List<Node> documents = new LinkedList<Node>(); NodeIterator it = query.execute().getNodes(); while (it.hasNext()) { documents.add(it.nextNode()); } return documents; }

www.devoxx.com

NuxeoFounded in 2000

Sustained growth for 8 years

Pioneering Open Source ECM software vendor

International organization, customers, partners, community

40+ employees

Business oriented Open Source

42

www.devoxx.com

Nuxeo ECM3+ years of work

Focus on the platform

Document Core

Nuxeo EP, Nuxeo WebEngine, Nuxeo RCP

Components everywhere (OSGi)

Large feature set

Big deployments

43

www.devoxx.com

Nuxeo CoreHigh-level document-oriented Java API

Complex document abstraction

Independent of actual storage backend

EJB remoting

REST bindings (JAX-RS)

SOAP bindings (JAX-WS)

44

www.devoxx.com

Nuxeo Core basicsCRUD

Hierarchy of document

Complex properties

Binaries

Security

Locking

Versioning

Publishing, Proxies

45

www.devoxx.com

Nuxeo CoreDefine the model

46

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:nxs="http://www.nuxeo.org/ecm/schemas/mydocument" targetNamespace="http://www.nuxeo.org/ecm/schemas/mydocument">

<xs:include schemaLocation="core-types.xsd"/>

<xs:element name="id" type="xs:integer"/> <xs:element name="title" type="xs:string"/> <xs:element name="description" type="xs:string"/> <xs:element name="creator" type="xs:string"/> <xs:element name="date" type="xs:date"/> <xs:element name="vignette" type="nxs:content"/> <xs:element name="fullname" type="nxs:fullname"/>

<xs:complexType name="fullname"> <xs:sequence> <xs:element name="firstname" type="xs:string"/> <xs:element name="lastname" type="xs:string"/> </xs:sequence> </xs:complexType>

</xs:schema>

www.devoxx.com

Nuxeo CoreDefine the model

47

<extension target="org.nuxeo.ecm.core.schema.TypeService" point="schema"> <schema name="mydocument" src="schemas/mydocument.xsd" prefix="mydoc"/></extension>

<extension target="org.nuxeo.ecm.core.schema.TypeService" point="doctype"> <doctype name="MyDocument" extends="Document"> <schema name="common"/> <schema name="mydocument"/> <facet name="Versionable"/> </doctype></extension>

www.devoxx.com

Nuxe Core – APIRead/Write

48

@Scope(ScopeType.STATELESS)@Name("myDocumentActions")public class DocumentActionsBean {

@In(create = true) protected transient NavigationContext navigationContext;

@In(create = true) protected transient CoreSession documentManager;

public void createDocument(Long id, String title) throws ClientException { DocumentModel current = navigationContext.getCurrentDocument(); DocumentModel doc = documentManager.createDocumentModel( current.getPathAsString(), null, "MyDocument"); doc.setProperty("mydocument", "id", id); doc.setPropertyValue("mydoc:title", title); doc.setPropertyValue("mydoc:fullname/firstname", "Florent"); documentManager.createDocument(doc); documentManager.save(); }}

www.devoxx.com

CMISDraft v 0.5 published in September 2008 by EMC, IBM, Microsoft

Alfresco, Open Text, Oracle, SAP also on board from the start

Oasis TC formed in November 2008

Adullact, Booz Allen Hamilton, Day, Ektron, Exalead, Fidelity, Flatirons, Magnolia, Mitre, Nuxeo, Saperion, Sun, Vamosa, Vignette (as of 2008-12-01)

CMIS 1.0 expected mid-2009

49

www.devoxx.com

CMIS goalsSimple document model

Independent of protocol

SOAP, REST (AtomPub) bindings

Not tied to a programming language

Platform, vendor independent

Basic set of ECM functions

“Greatest common denominator”

50

www.devoxx.com

CMIS basicsCRUD

Hierarchy folders, documents

Simple properties, lists

One binary

Policies

Versioning

Relationships

Queries

51

www.devoxx.com

CMIS advancedMulti-filing

Advanced queries

Joins

Full text

... maybe more to come

52

www.devoxx.com

CMIS basic propertiesObjectId

Uri

ObjectTypeId

CreatedBy

CreationDate

LastModifiedBy

LastModificationDate

ChangeToken

Name (doc, folder)

version-related props (doc)

ParentId (folder)

AllowedChildObjectTypeIds (folder)

SourceId (rel)

TargetId (rel)

PolicyName (policy)

PolicyText (policy)53

www.devoxx.com

CMIS objects

54

Folder DocumentRelationship Policy

www.devoxx.com

CMIS folders

55

Folder(root)

Folderfoo

Folderbar

Folderstuff

Foldergee

Folderblah

www.devoxx.com

CMIS documents

56

Folder(root)

Folderfoo

Folderbar

Folderstuff

Foldergee

Folderblah

Doc123

Doc456

Doc789

Doc001

www.devoxx.com

CMIS relationships

57

Folder

(root)

Folder

foo

Folder

bar

Folder

stuff

Folder

blah

Doc

456

Doc

001

555

333

Doc

123

www.devoxx.com

CMIS policies

58

Folder(root)

Folderfoo

Folderbar

Doc123

Doc001

Policy

PolicyPolicy

www.devoxx.com

CMIS policies uses

59

ACLs

Locks

Retention & Hold

Automatic transformations

Repository hints

etc.

www.devoxx.com

Standard SQL-92

Extensions for multi-valued properties

Extensions for hierarchical searches

Extensions for fulltext search

CMIS query example

61

SELECT OBJECT_ID, SCORE() AS SC, DESTINATION, DEPARTURE_DATES FROM TRAVEL_BROCHURE WHERE IN_TREE( , ‘ID00093854763’) AND CONTAINS( , 'PARADISE ISLAND CRUISE') AND '2010-01-01' < ANY DEPARTURE_DATES AND CONTINENT <> 'ANTARCTICA'ORDER BY SC DESC

www.devoxx.com

Additional headers for behavior control

MIME types

CMIS AtomPub bindings

62

Service application/atomsvc+xml

Feed application/atom+xml;type=feed

Entry application/atom+xml;type=entry

Query application/cmisquery+xml

AllowableActions application/cmisallowableactions+xml

www.devoxx.com

CMIS Web Services bindings

63

All the WSDL files are provided

Check the spec ;-)

www.devoxx.com

CMIS repository servicesgetRepositories

getRepositoryInfo

getTypes

getTypeDefinition

64

www.devoxx.com

CMIS navigation servicesgetDescendants

getChildren

getFolderParent

getObjectParents

getCheckedoutDocuments

65

www.devoxx.com

CMIS object servicescreateDocument

createFolder

createRelationship

createPolicy

getAllowableActions

getProperties, updateProperties

getContentStream, setContentStream, deleteContentStream

moveObject, deleteObject, deleteTree66

www.devoxx.com

CMIS multi-filing servicesaddObjectToFolder

removeObjectFromFolder

67

www.devoxx.com

CMIS discovery servicequery

68

www.devoxx.com

CMIS relationships servicesgetRelationships

69

www.devoxx.com

CMIS policy servicesapplyPolicy

removePolicy

getAppliedPolicies

70

www.devoxx.com

CMIS versioning servicecheckOut

cancelCheckOut

checkIn

getPropertiesOfLatestVersion

getAllVersions

deleteAllVersions

71

www.devoxx.com

Mapping documents to JCRDocument → Node

Schema → Mixin type

Simple & Array properties → Properties

Complex type → Sub-node

Lists of complex types → Ordered sub-nodes

72

www.devoxx.com

Mapping documents to SQLParent-child relationships → Dedicated “hierarchy” table

Schema → Table

Simple property → Column

Array property → “Collection” table

Complex type → Sub-document

Lists of complex types → Ordered sub-documents

74

www.devoxx.com

Nuxeo Core 2 and CMISNext-generation storage based on CMIS model

No “impedance mismatch” in models

Nuxeo extensions if needed

Leverage the Visible SQL Storage backend

Distributed and clusterable

Faster remote access and caching

True clusters

Facilitate cloud-based backends

77

www.devoxx.com

SummaryMany storage choices

Define your model, choose the right API

JCR is very capable

CMIS is coming fast

Nuxeo gives the best of both

78

www.devoxx.com

Concluding statement

Look for CMIS soon, and check out Nuxeo now!