Nuxeo Document Management - Version 5.3 The Reference guide

5.3

Copyright © 2000-2010, Nuxeo SA.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2; with Invariant Section “Commercial Support”, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is available at the URL: http://www.gnu.org/copyleft/fdl.html Table of Contents I. Introduction ...... 1 1. Preface ...... 2 1.1. What this Book Covers ...... 2 1.2. What this book doesn't cover ...... 2 1.3. Target Audience ...... 2 1.4. About Nuxeo ...... 3 1.5. About Open Source ...... 3 2. Introduction ...... 4 2.1. Enterprise Content Management ...... 4 2.1.1. Why ECM? ...... 4 2.2. The Nuxeo ECM platform ...... 4 2.3. Introduction FAQ ...... 4 2.3.1. What are Nuxeo EP 5, Nuxeo EP and Nuxeo RCP? ...... 4 2.4. Intended audience ...... 4 2.5. What this book covers ...... 4 3. Getting Started ...... 6 3.1. Overview ...... 6 3.2. Prerequisites ...... 6 3.3. Eclipse Plugins v Command Line ...... 7 3.4. Learning from the project sample ...... 7 3.5. Setting up the sample project ...... 7 3.5.1. Some handy environment settings ...... 7 3.5.2. Checking the sample project out of mercurial ...... 8 3.5.3. Initialize the Eclipse workspace ...... 8 3.5.4. Setting up your project for importing into Eclipse ...... 8 3.5.5. Importing the sample project into Eclipse ...... 9 3.5.6. Running JUnit tests on the sample code ...... 9 3.5.7. Building the jar file from the sample project ...... 9 3.5.8. Deploying the jar file to the Nuxeo server ...... 9 3.5.9. Starting the nuxeo server ...... 9 3.5.10. Viewing your changes via the UI ...... 10 3.5.11. Using Ant ...... 11 3.6. Understanding the sample code ...... 12 3.6.1. Two types of changes ...... 12 3.6.2. The layout of our sample project ...... 12 3.6.3. A bit about extension points ...... 13 3.6.4. Declaring the 'Book' document type ...... 14 3.6.5. Displaying book documents ...... 17 3.6.6. Actions, tabs and behavior ...... 22 3.6.7. Making book documents indexable and searchable ...... 24 3.6.8. Enabling drag&drop creation (plus creating our own extension points) ...... 26 3.6.9. Regulating book states ...... 29 3.6.10. Workflow ...... 30 3.6.11. Listening for events ...... 30 3.7. Starting a new project ...... 32 3.8. Using Documentation ...... 33 3.9. Other IDEs: IntelliJ IDEA and NetBeans ...... 33 3.9.1. IDEA ...... 33 3.9.2. NetBeans ...... 33 4. General Overview ...... 34 4.1. Introduction ...... 34 4.1.1. Architecture Goals ...... 34 4.1.2. Main concepts and design ...... 37 4.2. Nuxeo 5 Architecture Overview ...... 39 4.3. Nuxeo Runtime: the Nuxeo EP component model ...... 40 4.3.1. The motivations for the runtime layer ...... 40 4.3.2. Extensible component model ...... 41

Nuxeo EP 5.3 ii Nuxeo Document Management - Version 5.3

4.3.3. Flexible deployment system ...... 44 4.4. Nuxeo EP layered architecture ...... 45 4.4.1. Layers in Nuxeo EP ...... 45 4.4.2. API and Packaging impacts ...... 47 4.5. Core Layer overview ...... 47 4.5.1. Features of Nuxeo Core ...... 48 4.5.2. Nuxeo Core main modules ...... 49 4.5.3. Schemas and document types ...... 49 4.5.4. The life cycle associated with documents ...... 50 4.5.5. Security model ...... 51 4.5.6. Core events system ...... 51 4.5.7. Query system ...... 52 4.5.8. Versioning system ...... 52 4.5.9. Repository and SPI Model ...... 52 4.5.10. DocumentModel ...... 52 4.5.11. Proxies ...... 53 4.5.12. Core API ...... 54 4.6. Service Layer overview ...... 54 4.6.1. Role of services in Nuxeo EP architecture ...... 54 4.6.2. Services implementation patterns ...... 54 4.6.3. Platform API ...... 55 4.6.4. Adapters ...... 56 4.6.5. Some examples of Nuxeo EP services ...... 56 4.7. Web presentation layer overview ...... 56 4.7.1. Technology choices ...... 56 4.7.2. Componentized web application ...... 57 5. Schemas and Documents ...... 60 5.1. Introduction ...... 60 5.1.1. Concepts ...... 60 5.2. Schemas ...... 60 5.3. Core Document Types ...... 61 5.4. ECM Document Types ...... 61 5.4.1. Label and Icon ...... 62 5.4.2. Default view ...... 62 5.4.3. Layout ...... 62 5.4.4. Containment rules ...... 63 5.4.5. Hidden cases ...... 63 5.4.6. Summary ...... 63 II. Platform Services ...... 65 6. Exception Handling ...... 66 6.1. Introduction ...... 66 6.2. Extension Points ...... 66 6.2.1. requestdump ...... 66 6.2.2. listener ...... 66 6.2.3. errorhandlers ...... 66 7. Actions, Views, Navigation URLs and JSF tags ...... 68 7.1. Introduction ...... 68 7.2. Actions ...... 68 7.2.1. Concepts ...... 68 7.2.2. Manage actions ...... 68 7.3. Views ...... 71 7.3.1. UI Views ...... 71 7.3.2. Manage views ...... 71 7.4. Navigation URLs ...... 72 7.4.1. Document view codec service ...... 72 7.4.2. URL policy service ...... 73 7.4.3. Additional configuration ...... 74 7.4.4. URL JSF tags ...... 74 7.5. Nuxeo Document Lists Manager ...... 75 7.6. Nuxeo File Manager ...... 76 7.7. Nuxeo JSF tags ...... 76 8. Layouts ...... 78

Nuxeo EP 5.3 iii Nuxeo Document Management - Version 5.3

8.1. Introduction ...... 78 8.1.1. Layouts ...... 78 8.1.2. Widgets ...... 78 8.1.3. Widget types ...... 78 8.1.4. Modes ...... 78 8.2. Manage layouts ...... 78 8.2.1. Layout registration ...... 79 8.2.2. Layout definition ...... 79 8.2.3. Widget definition ...... 80 8.2.4. Listing layout definition ...... 81 8.2.5. EL expressions in layouts and widgets ...... 83 8.3. Document layouts ...... 84 8.4. Layout display ...... 84 8.5. Standard widget types ...... 85 8.5.1. text ...... 85 8.5.2. int ...... 85 8.5.3. secret ...... 85 8.5.4. textarea ...... 85 8.5.5. datetime ...... 85 8.5.6. template ...... 86 8.5.7. file ...... 86 8.5.8. htmltext ...... 86 8.5.9. selectOneDirectory ...... 86 8.5.10. selectManyDirectory ...... 86 8.5.11. list ...... 86 8.5.12. checkbox ...... 86 8.6. Custom templates ...... 86 8.6.1. Custom layout template ...... 86 8.6.2. Listing template ...... 88 8.6.3. Custom widget template ...... 89 8.6.4. Builtin templates to handle complex properties ...... 90 8.7. Custom widget types ...... 92 8.8. Generic layout usage ...... 93 9. Event Listeners and Scheduling ...... 94 9.1. Introduction ...... 94 9.2. Concepts ...... 94 9.3. Adding an event listener ...... 94 9.4. Upgrading an event listener ...... 95 9.5. Adding an event ...... 95 9.6. From CoreEvents to JMS Messages ...... 95 9.7. Adding a JMS message listener ...... 96 9.8. Scheduling ...... 97 10. User Notification Service ...... 98 10.1. Introduction ...... 98 10.2. Notification concept ...... 98 10.3. Notification channels ...... 98 10.4. E-mail notifications ...... 98 11. Indexing & Searching ...... 100 11.1. Introduction ...... 100 11.2. Configuration ...... 100 11.2.1. Concepts ...... 100 11.2.2. The indexableDocType extension point ...... 100 11.2.3. The resource extension point ...... 100 11.2.4. Field configuration ...... 101 11.2.5. Text fields and analyzers ...... 101 11.2.6. Boolean attributes ...... 102 11.2.7. Schema resources and fields without configuration ...... 102 11.2.8. Schema resources ...... 102 11.2.9. Automatic fields configuration ...... 102 11.3. Programmatic Searching ...... 103 11.3.1. Fields and literals ...... 103 11.3.2. WHERE statements ...... 103

Nuxeo EP 5.3 iv Nuxeo Document Management - Version 5.3

11.4. The Compass plugin ...... 105 11.4.1. Configuring Compass ...... 105 11.4.2. Global configuration ...... 105 11.4.3. Mappings for Nuxeo ...... 106 11.4.4. Text fields behavior ...... 107 11.5. Building a search UI with QueryModel ...... 108 12. Look and feel ...... 109 12.1. Introduction ...... 109 12.2. Principle ...... 109 12.3. Mechanism ...... 109 12.3.1. The Elements ...... 110 12.3.2. The format ...... 110 12.3.3. The negotiation ...... 111 12.3.4. The engine ...... 112 12.3.5. Resource management ...... 112 12.3.6. Application ...... 113 12.4. Customizing the theme ...... 113 12.4.1. Modifying the current theme using theme-default.xml ...... 113 12.4.2. Modifying the current theme ...... 116 12.4.3. Adding a new theme and its pages ...... 117 13. Authentication, Users & Groups Management ...... 120 13.1. Introduction ...... 120 13.2. Users and Groups configuration ...... 120 13.2.1. Schemas ...... 120 13.2.2. Directories ...... 121 13.2.3. UserManager ...... 121 13.2.4. User Management Interface ...... 123 13.3. Authentication ...... 127 13.3.1. Authentication Framework Overview ...... 127 13.3.2. Pluggable JAAS Login Module ...... 127 13.3.3. Pluggable Web Authentication Filter ...... 129 14. Security Policy Service ...... 136 14.1. Introduction ...... 136 14.2. Architecture ...... 136 14.3. Policy contributions ...... 136 14.3.1. Core policy contribution ...... 136 14.3.2. Search policy contribution ...... 137 15. Workflow & jBPM ...... 139 15.1. Workflow in Nuxeo 5.1 ...... 139 15.1.1. Deploying process definitions ...... 139 15.2. Workflow from Nuxeo 5.2: the jBPM Service ...... 140 15.2.1. Introduction ...... 140 15.2.2. jBPM service configuration ...... 140 15.2.3. Document management ...... 143 15.2.4. Default processes ...... 143 15.2.5. Nuxeo jBPM How-to ...... 146 16. Document Versioning ...... 148 16.1. Setting the version of a document ...... 148 16.2. Modifying automatically the version of a document ...... 148 16.3. Accessing document from previous version ...... 149 16.4. The versioning service implementation ...... 149 17. Audit Service ...... 150 17.1. Introduction ...... 150 17.2. Features ...... 150 17.3. Architecture ...... 150 17.4. Retrieving entries ...... 150 17.5. Contributing the audit service ...... 151 17.5.1. Recording new events types ...... 151 17.5.2. Recording additional informations ...... 151 18. Tag Service ...... 152 18.1. Introduction ...... 152 18.2. Features ...... 152

Nuxeo EP 5.3 v Nuxeo Document Management - Version 5.3

18.3. Architecture ...... 152 19. Directories and Vocabularies ...... 154 19.1. Introduction ...... 154 19.2. Directory with a Relational Database Management System (SQL) server as backend 154 19.3. Directory with an LDAP server as backend ...... 155 19.3.1. Server definition ...... 155 19.3.2. Directory declaration ...... 155 19.4. Handling references between directory entries ...... 156 19.4.1. References defined by a many-to-many SQL table ...... 156 19.4.2. Static reference as a dn-valued LDAP attribute ...... 156 19.4.3. Dynamic reference as a ldapUrl-valued LDAP attribute ...... 157 19.4.4. LDAP tree reference ...... 157 19.4.5. Defining inverse references ...... 157 19.5. Combining multiple directories into a single virtual directory ...... 157 19.5.1. Multi-directory sources ...... 157 19.5.2. Sub-directories ...... 158 19.6. The Directory API ...... 158 19.7...... 158 19.7.1. Building custom option lists in forms with directories ...... 158 19.7.2. Vocabularies/Directories management ...... 160 20. Binary content ...... 162 20.1. Introduction ...... 162 20.2. Standard blob management ...... 162 20.3. External blob management ...... 162 20.4. About BlobHolder ...... 164 21. Mimetype detection ...... 165 21.1. Introduction ...... 165 21.2. MimetypeRegistry ...... 165 21.3. Mimetype sniffing ...... 166 21.4. Invoking the mimetype detection ...... 168 22. Content Transformation ...... 169 22.1. Introduction ...... 169 22.2. Plugins module ...... 169 22.2.1. Creating a plugin ...... 169 22.2.2. Declaring a plugin module ...... 169 22.2.3. Using a transform plugin ...... 170 22.3. Available transforms ...... 171 22.3.1. Document conversion ...... 171 22.3.2. Pdfbox ...... 173 22.3.3. OLE objects extraction ...... 173 22.3.4. Office files merger ...... 175 22.3.5. XSL Transformation ...... 176 23. Nuxeo Conversion Service ...... 177 23.1. Conversion Service vs Transformation Service ...... 177 23.1.1. Motivations for this API changes ...... 177 23.1.2. What has been improved ...... 177 23.1.3. About compatibility ...... 177 23.2. Using Conversion Service ...... 178 23.2.1. built-in converters ...... 178 23.2.2. Conversion Service API ...... 178 23.2.3. Configuring the Convertion Service ...... 179 23.2.4. Contributing converters ...... 179 23.2.5. Converters based on external command line tools ...... 180 24. Relations ...... 182 24.1. Introduction ...... 182 24.2. Concepts ...... 182 24.3. Configuration ...... 182 24.3.1. Graph instances ...... 182 24.3.2. Resource adapters ...... 183 24.4. Manage relations ...... 183 24.5. Display relations ...... 183 24.6. Architecture overview ...... 184

Nuxeo EP 5.3 vi Nuxeo Document Management - Version 5.3

25. Placeful Configuration ...... 185 25.1. Introduction ...... 185 25.2. Using Placeful Configuration ...... 185 25.3. Contributing a placeful configuration ...... 185 25.4. Available storage ...... 186 25.4.1. In memory storage ...... 187 25.4.2. Directory storage ...... 187 25.5. Exemple of extension definition ...... 187 26. Content Template Service ...... 189 26.1. Introduction ...... 189 26.2. Contributing a content factory ...... 189 26.2.1. Factory Binding ...... 189 26.2.2. Template ...... 189 26.2.3. ACL ...... 190 26.3. How to Register your own Factory ...... 190 27. Nuxeo's Management Service ...... 192 27.1. Integrating Nuxeo monitoring in your management system ...... 192 27.1.1. Inventory (nx:*,management=inventory) ...... 192 27.1.2. Metric (nx:*,metric=*,management=metric) ...... 192 27.1.3. Quality (nx:*,usecase=*,management=usecase) ...... 192 27.2. Integrating management in nuxeo server ...... 192 27.2.1. nuxeo-runtime-management ...... 192 27.2.2. nuxeo-platform-management ...... 192 27.2.3. nuxeo-webengine-management ...... 193 27.3. Contributing management ...... 193 27.3.1. Publishing ...... 193 27.3.2. Providing shortcuts ...... 194 27.3.3. Reporting quality ...... 195 28. Publisher Service ...... 196 28.1. Overview ...... 196 28.2. Local sections ...... 196 28.3. Remote sections ...... 197 28.3.1. Server configuration ...... 197 28.3.2. Client configuration ...... 197 28.4. File system ...... 198 III. Core Services ...... 200 29. Nuxeo Runtime ...... 201 29.1. Overview ...... 201 29.1.1. Main Goals ...... 201 29.1.2. Main Features ...... 201 29.2. What is OSGi? ...... 201 29.3. OSGi Support ...... 202 29.3.1. Supported Features ...... 202 29.3.2. Unsupported Features ...... 203 29.3.3. Planned Features ...... 203 29.4. Component Model ...... 203 29.4.1. What are components? ...... 203 29.4.2. Main Features ...... 204 29.4.3. Planned Features ...... 204 29.4.4. Adapting Components ...... 204 29.4.5. Flexible Model ...... 204 29.4.6. Component Life Cycle ...... 205 29.4.7. Component Extensibility ...... 205 29.5. Supported Host Platforms ...... 207 29.5.1. JBoss Integration ...... 207 29.5.2. Eclipse Integration ...... 208 29.6. Using Nuxeo Runtime ...... 208 29.6.1. Creating Components ...... 208 29.6.2. Using components ...... 211 29.6.3. XML Component Descriptors ...... 215 29.7. Integration tests for Nuxeo Runtime applications ...... 216 29.7.1. The NXRuntimeTestCase base class ...... 216

Nuxeo EP 5.3 vii Nuxeo Document Management - Version 5.3

29.7.2. Frequent patterns ...... 217 29.8. Detailed Architecture ...... 217 29.9. References ...... 218 30. Nuxeo Core Documentation ...... 219 30.1. TODO: BS ...... 219 30.2. Overview ...... 219 30.2.1. Main goals ...... 219 30.2.2. Nuxeo Core Components ...... 219 30.3. Nuxeo Core Architecture ...... 220 30.3.1. Model Layer (or Internal API) ...... 220 30.3.2. Implementation Layer ...... 220 30.3.3. Facade Layer (or Public API) ...... 220 30.3.4. Deployment ...... 220 30.3.5. Client Session ...... 221 30.4. The Repository Model ...... 221 30.4.1. Document and Schemas ...... 221 30.4.2. Document Facets ...... 222 30.4.3. Document Annotations ...... 222 30.4.4. Document Access Control ...... 223 30.4.5. Life Cycle ...... 225 30.4.6. Query Engine ...... 227 30.4.7. The Public API ...... 227 30.4.8. Integration with Applications Servers ...... 228 30.5. Extension Points ...... 229 30.5.1. Session Factories ...... 229 30.5.2. LifeCycle Managers ...... 229 31. Nuxeo Core Import / Export API ...... 230 31.1. Export Format ...... 230 31.1.1. document.xml format ...... 230 31.1.2. Inlining Blobs ...... 231 31.2. Document Pipe ...... 232 31.3. Document Reader ...... 232 31.4. Document Writer ...... 233 31.5. Document Transformer ...... 234 31.6. API Examples ...... 234 31.6.1. Exporting data from a Nuxeo repository to a Zip archive ...... 235 31.6.2. Importing data from a Zip archive to a Nuxeo repository ...... 235 31.6.3. Export a single document as an XML with blobs inlined...... 236 32. Nuxeo Event Service ...... 237 32.1. Nuxeo event model ...... 237 32.1.1. Event ...... 237 32.1.2. EventContext ...... 237 32.1.3. EventListener ...... 238 32.1.4. Transactions and Events ...... 238 32.1.5. EventBundle ...... 238 32.1.6. PostCommitEventListener ...... 238 32.2. Using Events ...... 239 32.2.1. Firing Events ...... 239 32.2.2. Contributing an EventListener ...... 239 32.2.3. Contributing a PostCommitEventListener ...... 240 32.3. JMS and Nuxeo Events ...... 241 32.3.1. JMS integration ...... 241 32.3.2. Enabling JMS bridge ...... 241 32.3.3. From 5.1 event model to 5.2 ...... 241 33. Experimental Topics ...... 243 33.1. Introduction ...... 243 33.2. Runtime Support for Scripting Languages ...... 243 33.2.1. Introduction ...... 243 33.2.2. Supported languages ...... 243 33.2.3. Running a Script ...... 244 IV. SOA, Web Services and various integration solutions ...... 246 34. The Nuxeo Restlet API ...... 247

Nuxeo EP 5.3 viii Nuxeo Document Management - Version 5.3

34.1. Restlet Integration ...... 247 34.1.1. Restlet types in Nuxeo 5 ...... 247 34.1.2. Restlet URL and parameters mapping ...... 247 34.1.3. Contributing a new restlet ...... 248 34.2. Nuxeo default restlets ...... 248 34.2.1. Browse restlet ...... 248 34.2.2. Export restlet ...... 249 34.2.3. Lock restlet ...... 249 34.2.4. Plugin upload restlet ...... 250 34.3. Nuxeo RestPack ...... 251 34.3.1. Installing the RestPack ...... 251 34.3.2. Restlets included in the RestPack ...... 251 34.4. Nuxeo WebEngine Restlets ...... 255 35. Nuxeo HTTP client ...... 256 35.1. HTTP Client Library ...... 256 35.2. HTTP client authentication ...... 256 36. Web services ...... 258 36.1. Audit web service ...... 258 36.2. Remoting web service ...... 258 36.3. Indexing gateway service ...... 258 36.4. Metro web services ...... 258 37. Nuxeo JSR 168 Integration ...... 260 37.1. Overview ...... 260 37.2. Testing Nuxeo Portlets ...... 260 37.2.1. Prerequisites ...... 260 37.2.2. Generate a sample project with nuxeo-archetype-portlet archetype ...... 261 37.2.3. Test the newly created portlet ...... 262 37.3. Developping Nuxeo Portlets ...... 262 37.3.1. NuxeoPortlet class ...... 262 37.3.2. Project from nuxeo-archetype-portlet archetype ...... 262 37.3.3. portlet.xml ...... 263 37.3.4. Restlets ...... 263 37.4. Available portlets ...... 263 37.4.1. Nuxeo Search Portlet ...... 263 38. Desktop integration tools ...... 265 38.1. Drag and drop browser extensions ...... 265 38.1.1. Server side import service: the FileManagerService ...... 265 38.1.2. Microsoft Internet Explorer plugin ...... 265 38.1.3. Mozilla Firefox plugin ...... 265 38.2. Online document editing with LiveEdit ...... 265 38.2.1. Functional overview ...... 265 38.2.2. Functional use cases ...... 266 38.2.3. Architectural overview ...... 267 38.2.4. The Web Service component ...... 270 38.2.5. More on editor launch ...... 270 38.2.6. More on pre- and post-editing actions ...... 271 38.3. Configuring LiveEdit links ...... 271 38.3.1. Configuration policies ...... 271 38.3.2. Changing the configuration policy ...... 272 39. Nuxeo WebDAV interface ...... 273 39.1. WebDAV clients ...... 273 39.1.1. Path vs displayName ...... 273 39.1.2. Filesystem resource vs Nuxeo DocumentModel artifact ...... 273 39.1.3. MS Web Folder client ...... 273 39.2. Fooling WebDAV clients ...... 273 39.2.1. Available hacks ...... 274 39.2.2. Configuring Nuxeo WebDAV connector for each client...... 274 39.3. Nuxeo EP WebDAV implementation ...... 274 39.3.1. Nuxeo EP WebDAV-specific features ...... 275 39.3.2. Known limitations ...... 275 39.4. Using the Nuxeo WebDAV connector ...... 276 39.4.1. Installing the WebDAV connector ...... 276

Nuxeo EP 5.3 ix Nuxeo Document Management - Version 5.3

39.4.2. Connecting a client to Nuxeo WebDAV connector ...... 276 40. Reporting: Eclipse BIRT Driver ...... 277 40.1. Overview ...... 277 40.2. How to use it ...... 277 40.3. Tomcat integration HOWTO ...... 282 41. Nuxeo Flex Connector ...... 284 41.1. Overview ...... 284 41.2. Development environment ...... 284 41.3. Build and Deploy ...... 284 41.3.1. Sample Overview ...... 284 41.4. Dive In ...... 285 41.4.1. Data Services Configuration ...... 285 41.4.2. Your First Flex application ...... 286 41.4.3. Granite DS configuration ...... 287 V. Administration overview ...... 288 42. OS requirements, existing and recommended configuration ...... 289 42.1. Required software ...... 289 42.2. Recommended configuration ...... 289 42.2.1. Hardware configuration ...... 289 42.2.2. Default configuration ...... 289 42.2.3. For optimal performances ...... 289 42.3. Known working configurations ...... 290 42.3.1. OS ...... 290 42.3.2. JVM ...... 290 42.3.3. Storage backends ...... 290 42.3.4. LDAP ...... 291 43. SMTP Server configuration ...... 292 44. RDBMS Storage and Database Configuration ...... 293 44.1. Storages in Nuxeo EP ...... 293 44.2. Installing the JDBC driver ...... 293 44.3. Configuring Nuxeo Core Storage ...... 293 44.3.1. Visible Content Store configuration ...... 293 44.3.2. JCR backend configuration ...... 294 44.3.3. Set up your RDBMS ...... 297 44.3.4. Start Nuxeo EP ...... 297 44.4. Configuring Storage for other Nuxeo Services ...... 297 44.4.1. Configuring datasources ...... 298 44.4.2. Relation service configuration ...... 299 44.4.3. Tag service configuration ...... 300 44.4.4. Compass search engine dialect configuration ...... 300 44.5. Setting up a new repository configuration ...... 300 44.5.1. Add the new repository configuration ...... 300 44.5.2. Declare the new repository to the platform ...... 302 45. LDAP Integration ...... 303 45.1. For users/groups storage backend ...... 303 46. OpenOffice.org server installation ...... 304 46.1. Installation ...... 304 46.1.1. Start server ...... 304 46.1.2. Parameters ...... 304 46.1.3. Installing an extension ...... 305 46.1.4. Notes ...... 305 46.2. Running OpenOffice as a Daemon ...... 305 46.2.1. Nuxeo OOo Daemon ...... 305 46.2.2. Configuring Nuxeo OOo Daemon ...... 306 47. Run Nuxeo EP with a specific IP binding ...... 307 48. Backup, restore and reset ...... 308 48.1. Backup ...... 308 48.2. Backup before an upgrade ...... 309 48.3. Restore ...... 309 48.4. Reset ...... 309 49. Offline client synchronization ...... 310 49.1. Working environment ...... 310

Nuxeo EP 5.3 x Nuxeo Document Management - Version 5.3

49.2. Use case ...... 310 49.3. User guide ...... 310 49.4. How does it work? ...... 310 50. Replication tool ...... 312 50.1. Functional Objective ...... 312 50.2. Use cases ...... 312 50.3. User guide ...... 313 50.4. How does it work? ...... 313 50.5. Customizing the import code ...... 316 51. Monitoring Nuxeo ...... 317 51.1. Configure Nuxeo to use a single JMX server...... 317 51.1.1. Configuration from Nuxeo 5.3.0 ...... 317 51.1.2. Configuration for Nuxeo 5.2.0 ...... 317 51.1.3. Configuration for Nuxeo before 5.2.0 ...... 318 51.2. Interesting data to monitor...... 318 51.3. Persisting and analysing data...... 318 51.4. Querying the JMX server remotely ...... 318 52. The Nuxeo Shell ...... 320 52.1. Overview ...... 320 52.2. User Manual ...... 320 52.2.1. Command Options ...... 322 52.2.2. Commands ...... 323 52.3. Troubleshooting ...... 327 52.3.1. Check listened IP ...... 327 52.3.2. Check connected server ...... 327 52.3.3. Multi-machine case ...... 327 52.4. Extending the shell ...... 327 52.4.1. Registering New Custom Commands ...... 328 52.4.2. Java Code for the new commands ...... 328 52.4.3. Building the shell plugin ...... 328 52.4.4. Deploying the shell plugin ...... 329 53. Build Nuxeo distributions from sources ...... 330 53.1. Requirements ...... 330 53.2. Limitations ...... 330 53.3. Download Nuxeo distribution sources ...... 330 53.3.1. Download archive ...... 330 53.3.2. Download sources with Mercurial ...... 330 53.4. Build from sources ...... 330 53.4.1. Available packages ...... 330 53.4.2. Usage ...... 331 VI. Core developer guide ...... 332 54. Coding and Design Guidelines ...... 333 54.1. Introduction ...... 333 54.2. External Coding Standards ...... 333 54.3. Some points that need attention ...... 333 54.3.1. Java code formating ...... 333 54.3.2. XML code formatting ...... 334 54.3.3. Design ...... 334 54.3.4. Unit tests ...... 335 54.3.5. Security ...... 335 54.3.6. Naming convention ...... 336 54.3.7. Information hiding ...... 336 54.3.8. Use modern Java features ...... 336 54.3.9. Logging ...... 336 54.3.10. Documentation: Comments and Javadoc ...... 337 54.3.11. Deprecation ...... 338 54.4. Methodology tips ...... 339 54.4.1. Use the power of your IDE (and its plugins) ...... 339 54.4.2. Refactor ...... 340 54.5. Important references ...... 340 55. Development Tools and Process ...... 341 55.1. Mercurial usage ...... 341

Nuxeo EP 5.3 xi Nuxeo Document Management - Version 5.3

55.1.1. Overview and online documentation ...... 341 55.1.2. Nuxeo common usage ...... 341 55.1.3. Best practices ...... 344 55.1.4. Useful scripts, commands and tips ...... 344 55.1.5. Advanced usage and specific use cases ...... 347 55.2. Maven usage ...... 348 55.2.1. Overview and online documentation ...... 348 55.2.2. Generate a new project with the nuxeo-archetype-start archetype ...... 349 55.3. Code Quality with Eclipse Plugins ...... 350 55.3.1. Using Checkstyle ...... 350 55.3.2. Using TPTP ...... 350 55.3.3. Using FindBugs ...... 350 55.4. Profiling with NetBeans Profiler ...... 350 55.5. NXPointDoc Documentation tool ...... 350 55.5.1. Documenting a component ...... 351 55.5.2. Creating the NxPointDoc site ...... 353 55.5.3. Browsing NxPointDoc ...... 353 55.6. Quality Assurance with continuous integration ...... 353 55.6.1. Rules and means ...... 354 55.6.2. Quality directives for Nuxeo developers ...... 355 55.7. Release process ...... 357 55.7.1. Overview ...... 357 55.7.2. Continuous integration coverage ...... 357 55.7.3. Help testing release candidates ...... 358 56. Packaging Nuxeo EAR ...... 359 56.1. Introduction ...... 359 56.2. Basic project structure ...... 359 56.3. The EAR module ...... 360 56.3.1. Assembly descriptor ...... 360 56.3.2. Add some resources ...... 363 56.4. Improve usability ...... 363 56.4.1. Thanks to Maven ...... 363 56.4.2. Thanks to Ant ...... 364 56.5. Recommended multi-machine packagings ...... 367 56.5.1. Bi-machine: stateful/stateless ...... 367 57. Release Management ...... 372 57.1. Introduction ...... 372 57.2. Let's release! ...... 372 57.2.1. Remove all dependencies on SNAPSHOT versions ...... 372 57.2.2. Checkout the code and clean your repository ...... 373 57.2.3. Test the release ...... 373 57.2.4. Perform the release ...... 373 57.2.5. You're done ...... 374 VII. Add-ons ...... 375 58. Add-ons ...... 376 58.1. Introduction ...... 376 59. Nuxeo Annotation Service ...... 377 59.1. Introduction ...... 377 59.1.1. W3C Annotea ...... 377 59.1.2. Logical architecture overview ...... 377 59.1.3. XPointer integration and extension...... 377 59.2. Annotation Service Core ...... 378 59.2.1. Overview ...... 378 59.2.2. Implementation ...... 378 59.2.3. Storage ...... 378 59.2.4. uriResolver ...... 379 59.2.5. urlPatternFilter ...... 379 59.2.6. metadata ...... 379 59.2.7. permissionManager and permissionMapper ...... 379 59.2.8. annotabilityManager ...... 380 59.2.9. UID Generation ...... 380 59.2.10. Event management ...... 380

Nuxeo EP 5.3 xii Nuxeo Document Management - Version 5.3

59.3. NXAS Repository Plugin ...... 380 59.3.1. Overview ...... 381 59.3.2. Default contribution ...... 381 59.3.3. Extension Point ...... 382 59.3.4. documentEventListener ...... 382 59.3.5. securityManager ...... 382 59.3.6. jcrLifecycleEventId and graphManagerEventListener ...... 382 59.4. NXAS Web ...... 382 59.4.1. Overview ...... 382 59.4.2. Extension Point ...... 382 59.4.3. Configuration ...... 383 59.5. Annotation Service Facade ...... 383 59.6. Annotation Service HTTP Gateway ...... 383 59.6.1. Overview ...... 383 59.7. References ...... 384 60. Virtual Navigation ...... 385 60.1. Virtual Navigation ...... 385 60.1.1. Virtual Navigation presentation ...... 385 60.1.2. Virtual Navigation configuration ...... 385 61. Metadata Extraction Service ...... 389 61.1. Introduction ...... 389 61.2. Metadata extraction module ...... 389 61.2.1. Defining a contribution for metadata extraction ...... 389 61.2.2. Specifying input parameters ...... 390 61.2.3. Chaining extractions ...... 390 61.2.4. Creating a plugin for metadata extraction ...... 390 61.2.5. Using a metadata extraction plugin ...... 390 62. Unicity Service ...... 392 62.1. How does it works ? ...... 392 62.2. What you need: ...... 392 62.3. Configuration ...... 392 62.4. Snippets ...... 392 63. Nuxeo Mail Service ...... 394 63.1. Presentation ...... 394 63.2. Basic Use ...... 394 63.2.1. Configuration ...... 394 63.3. Advanced Use ...... 395 64. Imaging ...... 396 64.1. Introduction ...... 396 64.2. Imaging API ...... 396 64.3. Imaging transform ...... 396 64.4. Imaging web ...... 396 64.5. Imaging core ...... 396 65. Nuxeo Preview Addon ...... 397 65.1. Overview ...... 397 65.2. Installing the Preview Addon ...... 397 65.2.1. Deploy the Addon ...... 397 65.2.2. Configure Transformers ...... 397 65.3. Extensions and Pluggability ...... 398 65.3.1. Pluggable Adapters ...... 398 65.3.2. Pluggable HTML Transformers ...... 399 65.4. Previews and URLs ...... 399 66. Nuxeo Tiling service Addon ...... 401 66.1. Overview ...... 401 66.2. How tiles are defined and computed ...... 401 66.3. Installing the picture tiling Addon ...... 402 66.3.1. Requirements ...... 402 66.3.2. Deploy the addon ...... 403 66.3.3. Configuration ...... 403 66.4. Testing the tiling service ...... 403 66.4.1. URL and restAPI ...... 403 66.4.2. simple test client ...... 404

Nuxeo EP 5.3 xiii Nuxeo Document Management - Version 5.3

67. Nuxeo DocumentLink Addon ...... 406 67.1. Overview ...... 406 67.2. How does it work ...... 406 67.3. DocumentLink and Repository ...... 407 67.4. Using DocumentLink ...... 407 67.4.1. Using the adapter ...... 407 67.4.2. Using the DocRepository ...... 408 68. Nuxeo Search Center ...... 409 68.1. Overview ...... 409 68.2. Installing and testing the search center ...... 409 68.2.1. Building from source ...... 409 68.2.2. Deploying on a Nuxeo server ...... 409 68.2.3. Using the Search Center ...... 410 68.3. How does it work ...... 410 68.3.1. The GWT client ...... 410 68.3.2. The JAX-RS server ...... 410 68.3.3. The SearchCenterService ...... 410 68.4. How to customize the list of available filters ...... 411 68.4.1. FilterWidgets ...... 411 68.4.2. FilterSets ...... 411 68.5. How to build new GWT filter widgets ...... 412 68.5.1. Setting up a GWT eclipse development environment ...... 412 68.5.2. Existing filter widgets ...... 412 68.5.3. TODO: layout and extension points ...... 413 VIII. Annexes ...... 414 A. FAQs ...... 415 A.1. Deployment and Operations ...... 415 B. Detailed Development Software Installation Instructions ...... 418 B.1. Installing Java ...... 418 B.1.1. Using the Sun Java Development Kit (Windows and linux) ...... 418 B.1.2. Using a package management systems (Linux) ...... 418 B.1.3. Manual installation (Linux) ...... 419 B.1.4. Setting up JAVA_HOME (Windows, Linux, Mac OS) ...... 419 B.2. Installing Ant ...... 419 B.3. Installing Maven ...... 420 B.3.1. What is Maven? ...... 420 B.3.2. Installing Maven ...... 420 B.4. Installing JBoss AS ...... 421 B.4.1. JBoss documentation ...... 421 B.4.2. Enable EJB3 support ...... 421 B.4.3. JBoss AS listening ports customization ...... 421 B.4.4. Affected JBoss services ...... 424 B.5. Installing a Subversion client ...... 425 B.5.1. Generic subversion clients with linux ...... 425 B.5.2. Windows ...... 425 B.6. Installing mercurial ...... 425 B.6.1. Linux ...... 425 B.6.2. Windows ...... 425 B.6.3. Mac OS ...... 425 B.6.4. Setting a username ...... 426 B.6.5. Activating pre-integrated extensions ...... 426 B.6.6. Using forest ...... 426 B.7. Chapter Key Point ...... 426 C. Commercial Support ...... 428 C.1. About Us ...... 428 C.2. Contact information ...... 428 C.2.1. General ...... 428 C.2.2. Europe ...... 428 C.2.3. USA ...... 428

Nuxeo EP 5.3 xiv Part I. Introduction

Nuxeo EP 5.3 1 Chapter 1. Preface

Nuxeo EP is a comprehensive open source Enterprise Content Management (ECM) platform. It has been designed to be robust, scalable and highly extensible, by using modern open source Java EE technologies, such as JSF, EJB3, JBoss Seam, OSGi, and a Service Oriented Approach. It can be used to develop both web-based server applications and Rich Client applications.

Nuxeo EP provides services that currently cover the following functions of the ECM spectrum: • Document management

• Collaborative Work

• Business process management (workflow)

• Compliance

• Records management

• Digital asset management (DAM)

Thanks to the modular and service oriented nature of Nuxeo EP, it is easy to create specialized applications, vertical or horizontal. Examples of applications that have been successfully created and used include applications for: • Document management

• Digital assets management (DAM)

• Case management

• Correspondence management

• News management systems for press agencies

• Museum collections management

• Etc.

1.1. What this Book Covers

The primary focus of this book it the presentation of Nuxeo EP, from the perspective of its configuration and its architecture.

1.2. What this book doesn't cover

This book is not an end-user manual for Nuxeo DM or other applications based on the Nuxeo EP platform. If you are interested in such a document, we recommend that you get it from http://www.nuxeo.org/.

This book is not a tutorial either. There is also a tutorial on http://www.nuxeo.org/.

1.3. Target Audience

As a reference book for the Nuxeo platform, this book has several intended audiences: • System integrators, who need to understand how to configure and adapt the Nuxeo platform to their customers needs.

Nuxeo EP 5.3 2 Preface

• Third-party application developers, who will typically need both to customize the behavior of some components and to write new components to extend the functionalities of the platform.

• System administrators, who need to understand how to configure the platform for the specific needs of their hosting environment.

• Core developers, who work on the platform and need a reference documentation.

We fully understand that these different people with different concerns, and we plan to create, thanks to the modular structure of this document, more targeted books for these different people.

Readers of this book are presumed familiar with the Java 5 language and with the Java EE and XML technologies.

1.4. About Nuxeo

Founded in 2000, Nuxeo SA is part of the "second wave" of open source companies, and focuses on developing and supporting applications, instead of system software or development tools.

By entering the ECM field early in 2002, Nuxeo has established itself as the leader of open source ECM, with customers for critical projects in the Government, Energy and Finance sectors. Nuxeo currently has 50 employees, about half of them developers.

Nuxeo has customers and partners in Europe, in Northern and Southern America, in the Middle East and in Africa.

1.5. About Open Source

Simply put, Open source is a better way to develop and support software.

Nuxeo fully embraces the open source vision, by fostering collaboration with a community of external contributors.

Nuxeo EP 5.3 3 Chapter 2. Introduction

This chapter will give you an overview of ECM and the motivation for using the Nuxeo platform in your next ECM project.

2.1. Enterprise Content Management

According to the AIIM, the Association for Information and Image Management, ECM is defined as "the technologies used to capture, manage, store, preserve, and deliver content and documents related to organizational processes".

2.1.1. Why ECM?

A March 2005 white paper on “The Hidden Costs of Information Work” by the IDC in the United States found that the average office employee spent approximately one day per week organizing and filing documents that they used. This can equate to a considerable amount of cost and inefficiency. A further twelve hours was spent on managing document approval, managing document routing and publishing to other channels. Nine hours was spent searching for documents.

2.2. The Nuxeo ECM platform

2.3. Introduction FAQ

2.3.1. What are Nuxeo EP 5, Nuxeo EP and Nuxeo RCP?

Nuxeo EP 5 is the 5th version of the open source platforms developed by Nuxeo (the four previous ones where known as "CPS").

Nuxeo EP or "Enterprise Platform" is the server part of Nuxeo EP 5. It is a Java EE application intended to run in a standard Java EE 5 application server like JBoss. It can be accessed by end users from a web browser, from office productivity suites like MS-Office or OpenOffice.org, or from rich client developed using the Nuxeo RCP technology (see below).

Nuxeo RCP or "Rich Client Platform" is a platform for building rich client applications, that usually connect to a Nuxeo EP server.

Nuxeo EP and Nuxeo RCP run on top of a common runtime, "Nuxeo Runtime", and share a common set of core components, called "Nuxeo Core".

2.4. Intended audience

2.5. What this book covers

Part 1: Introduction

Part 2:

Part 3:

Nuxeo EP 5.3 4 Introduction

Part 4:

Nuxeo EP 5.3 5 Chapter 3. Getting Started

3.1. Overview

In this chapter we will show you how to develop with Nuxeo EP. It is recommended that you first read the 'Learning Nuxeo EP5 Guide' before reading this chapter. It will also provide you with a good introduction to developing with Nuxeo EP and give you a better understanding of the additional examples provided by the sample project which are discussed here.

You can think of your development task as using an IDE (such as Eclipse) to create a jar file from your source code, that can then be deployed (ie. copied) to the nuxeo server's 'plugin' directory. This new plugin (jar file) which you will create, adds functionality to the basic 'out of the box' Nuxeo EP Server that you will also download and setup. Here is a diagram that tries to show in simple terms what we would like to do:

It also explains simply what Nuxeo is. The nuxeo server is essentially an application (nuxeo.ear) that runs inside a JBOSS container. It contains an embedded H2 database that acts as the default document repository. The user interface to nuxeo is provided by a web browser or a rich client.

If you encounter any problems don't forget you can share your experience on the ecm mailing list .

3.2. Prerequisites

We assume from now on that you have the following ready-to-use environment set up on your computer:

• Java Development Kit (JDK) 1.5.x or JDK 1.6.x (Sun's JDK, OpenJDK is not yet supported)

• Eclipse 3.5 (aka galileo) (J2EE edition)

• A Nuxeo EP installation from the last release (download the installation wizard). You can also download

Nuxeo EP 5.3 6 Getting Started

a nightly build installer from http://www.nuxeo.org/static/snapshots/ , but keep in mind that this one may be broken, so don't erase your working setup with a nightly build: the result is not guaranteed.

• Maven (for setting up eclipse and builds)

• Mercurial (for checking out the source controlled version(s) of sample project used throughout this chapter)

• A "unix-type" shell: if you are running windows, you can install cygwin Note: The Nuxeo EP installer also installs and sets up the right version of JBoss on your computer, so you don't need to install it on your own.

For detailed instructions on how to set up all of this software, there is a good guide in Chapter 2 of the 'Learning Nuxeo EP5 Guide'.

3.3. Eclipse Plugins v Command Line

We will check out our sample project's source code from a remote repository using Mercurial and then import this source into Eclipse. We will use Eclipse as a development tool only here. The resulting artifact (Nuxeo projects are well described as maven artifacts - which can be thought of as just the output of a given project, for eg. a jar, a war, and ear file etc), will be built from the source we create in Eclipse, via the command line using Maven.

It is possible to configure Eclipse to use plugins that will let you run both Maven and Mercurial from within eclipse. You can set up your Eclipse to do so if you prefer, however in this chapter we will describe how to use these tools from the command line. If you prefer to use the plugins you can download them from: • Maven Integration for eclipse

• Mercurial Integration for eclipse

3.4. Learning from the project sample

Nuxeo provides you a sample project that teaches you the main components used by Nuxeo EP by introducing the 'Book' document type, which equates to a book you'd buy in a bookstore or borrow from a library (complete with ISBN number). By following this chapter, you will learn how to: • declare the book document type;

• display book documents;

• regulate book document states;

• make book documents indexable and searchable;

• enable drag and drop book creation mode;

• handle book document creation events.

3.5. Setting up the sample project

3.5.1. Some handy environment settings

Before we start you may want to set the following in your .bashrc file in your home directory:

Nuxeo EP 5.3 7 Getting Started

export MAVEN_OPTS="-Xmx512M -XX:MaxPermSize=512M"

It sets the amount of memory available to Maven when it is doing its stuff and will help you avoid "out of memory" errors.

3.5.2. Checking the sample project out of mercurial

Create a directory called 'workspace' in your home home directory. Change into this directory and check the sample project out of the remote repository ( http://hg.nuxeo.org/addons/nuxeo-sample-project/) by running mercurial from the command line:

$ mkdir ~/workspace

$ cd ~/workspace

$ hg clone http://hg.nuxeo.org/addons/nuxeo-sample-project/

This will create a directory in your home directory called ~/workspace/nuxeo-sample-project which contains the source code used for this lesson. There are 2 branches in the mercurial repository: 5.1 and 5.2. The 5.1 branch source has been tested against the Nuxeo 5.1.6 server, whilst the 5.2 branch has been tested against the Nuxeo 5.2.0 server.

To see what branch you are using, type "hg branches". To switch between branches you can type "hg update branchName". Eg:

$ hg update 5.1

The accompanying version of JBOSS used with the 5.1 Nuxeo server is jboss 4.0.5 and with the 5.2 Nuxeo server is 4.2.3.

3.5.3. Initialize the Eclipse workspace

From the workspace directory, run the command:

$ mvn -Declipse.workspace=. eclipse:configure-workspace

This command will initialise your Eclipse workspace for you, which basically means it tells Eclipse where to find your local Maven repository by setting a variable called M2_REPO in the file: ~/workspace/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs .Your local Maven repository (which is usually in ~/.m2/repository) will hold all the jar files that our sample project depends on. You will only need to run the Maven 'configure-workspace' command (listed above) once. If you create projects in addition to the sample project later on, they can all use this same workspace (and hence the same local maven repository).

3.5.4. Setting up your project for importing into Eclipse

Next, Maven will help us set up the sample project so that it can be readily imported into eclipse. Change into your sample project directory and run the Maven commands:

$ cd ~/workspace/nuxeo-sample-project

$ mvn eclipse:clean

$ mvn eclipse:eclipse

The 'eclipse:clean' command will clean any previous eclipse setup of your sample project (ie. cleans up all the eclipse related files so that you can start again).

Nuxeo EP 5.3 8 Getting Started

The 'eclipse:eclipse' command will set up eclipse related files for your project and also download any dependencies that your project needs to compile, based on the sample project's (Maven) pom.xml file. It will store these dependencies in your local Maven repository (defined by the M2_REPO variable we described above). So the first time you run this command, it may take a while. Now when you import your project into eclipse, it should have everything it needs to compile the source.

3.5.5. Importing the sample project into Eclipse

Now that your workspace, Eclipse project files, and all the dependencies have been prepared, you can import the sample project into eclipse. Start Eclipse and select File>Import-General-Existing Projects into Workspace, click next and set the root of the workspace as: ~/workspace/nuxeo-sample-project. Hopefully it will be imported with no errors.

3.5.6. Running JUnit tests on the sample code

Our sample project has some JUnit test classes defined that enables you to run tests from within Eclipse. Expand the src/test/java branch to reveal the classes under the org.nuxeo.ecm.sample tree: i. TestBookLifeCycle

ii. TestBookTitleService

iii.TestBookType

iv. TestRepository You can right click on these classes and select: Run As>JUnit Test.

3.5.7. Building the jar file from the sample project

The sample project code contains all the source in a working format that is ready to be built into a jar. Normally, you'd be creating these changes yourself. However, this has already been done for you in the sample project (we will explain what it all means in the sections that follow).

So now we are ready to create a jar file from our source code. To do this run the following Maven command from your ~/workspace/nuxeo-sample-project directory:

$ mvn clean install

If all goes well you should see the "BUILD SUCCESSFUL" message and a new jar file created in the ~/workspace/nuxeo-sample-project/target subdirectory called something like: nuxeo-project-sample-5.1.6-SNAPSHOT.jar

3.5.8. Deploying the jar file to the Nuxeo server

Now that we have created the jar file, deploying it to the nuxeo server is simply a matter of copying it to the 'plugins' directory. Assuming that the nuxeo server is located in the ~/nuxeo directory, then copy the jar as follows:

$ cp ~/workspace/nuxeo-sample-project/nuxeo-project-sample-5.1.6-SNAPSHOT.jar /nuxeo/server/default/deploy/nuxeo.ear/plugins

3.5.9. Starting the nuxeo server

We can now start the nuxeo server. After it has started, we will open up a web browser to see what our sample project has produced ((Section 3.5.10, “Viewing your changes via the UI” ).

There are 2 ways to run the nuxeo server:

Nuxeo EP 5.3 9 Getting Started

3.5.9.1. Running the nuxeo server from the command line

To start the nuxeo server from the command line (assuming it is installed in ~/nuxeo):

$ cd ~/nuxeo

$ bin/run.sh

Note: you can shutdown the server from the command line by entering ^C (control-C) or by running the script "~/nuxeo/bin/shutdown.sh -S" from another shell session.

3.5.9.2. Running the nuxeo server from within Eclipse

You can also set up an instance of the nuxeo server to run within Eclipse. You do this by pointing your eclipse server to the installation of the nuxeo server on your filesystem. Defining a server configuration for the Nuxeo runtime within eclipse enables you to start and stop Nuxeo directly from within eclipse.

This can be achieved by launching the new server wizard from the servers tab (make sure you are in the J2EE view in Eclipse): Right click inside the server pane, and select New>Server. You should select a Jboss v4.0 server type, click 'Next' and provide the Nuxeo EP home directory as server home (eg. ~/nuxeo) on the next screen. Select the defaults for the remainder and then click 'Finish'.

Now double click your server so you can see the server configuration we just created. We need to change the default timeout value on the server startup, because it is likely that starting the nuxeo server will exceed the default value. You should configure a starting timeout value suitable for your computer.

Expand the 'Timeouts' section and change the default to 300 seconds for example. Don't forget to save your changes.

You may also want to click the 'open launch configuration' link in the server settings view. On the arguments tab you can change the amount of memory available to the VM to avoid PermGen out of memory errors:

-XX:MaxPermSize=512M

Now right click on the server and select 'Start' to start the server from within eclipse.

3.5.9.3. Server Logs

You can look at your server logs to look for any errors which may occur on server startup in the following directory:

~/nuxeo/server/default/log/server.log

For example: One common error is when an instance of the server has failed to stop correctly and you try to start the server again, you will get an error like:

Port 8083 already in use

In this case you will have to kill the java process from the command line before re-starting the server:

[nuxeo ~/nuxeo] ps aux | grep java nuxeo 9919 2.4 10.5 777428 297292 ? Sl 15:44 3:37 /usr/lib/jvm/java-6-sun-1.6.0.16/bin/java -Dprogram.name=run.bat -Djava.endorsed.dirs=/home/nuxeo/nuxeo/bin/../lib/endorsed -Xms128m -Xmx512m -Dfile.encoding=UTF-8 -classpath /home/nuxeo/nuxeo/bin/run.jar org.jboss.Main -c default [nuxeo ~/nuxeo] kill -9 9919

3.5.10. Viewing your changes via the UI

Nuxeo EP 5.3 10 Getting Started

3.5.10.1. Logging in

Now that your server is running, open up your web browser and go to the url: http://localhost:8080/nuxeo/

Log in nuxeo with Administrator/Administrator.

3.5.10.2. Viewing your changes

In order to see what results our new jar plugin for the 'Book' document type has produced, we first need to create a Workspace (Note: A Nuxeo workspace is different from an Eclipse workspace. To understand more about the basic Nuxeo EP user concepts, see the Nuxeo User Guide). Once you have logged in, click on 'Workspaces' and select 'Create New Workspace'. Give it a title and click 'Create'.

Now click on the workspace you have created, and select 'New Document'. The list of available document types should now contain 'Book' as one of its types. Select 'Book', and Enter a title, description and ISBN, and upload a file if you want. Click 'create'.

Congratulations, you have successfully created a new Book type ! You should now see this in your Nuxeo workspace.

3.5.11. Using Ant

Although we said above that we would use Eclipse purely for development, the sample project does come with a build.xml file that can be conveniently used within the default installation of eclipse to perform the functions of building and deploying the jar file. We have already accomplished these two tasks using Maven for the build, and a unix cp for the deploy, however we will show you how this can also be automated from within eclipse using Ant.

In order to take advantage of our Ant build.xml file, we first need to tell Ant where to find our server. We will do this by creating a build.properties file which will be used by Ant to find it. The sample project comes with a file called 'build.properties.sample' in the ~/workspace/nuxeo-sample-project root directory. We will copy this file an rename it to 'build.properties' in the same directory:

$ cp build.properties.sample build.properties

Now edit the file and change the line which contains the property: jboss.dir to point to your jboss path. Note that when using the Nuxeo EP installer, the JBOSS home directory is the same as the Nuxeo EP home directory. You should use an absolute path for safety. For example if your home is /home/nuxeo and your server is installed in ~/nuxeo: jboss.dir=/home/nuxeo/nuxeo

Now within eclipse, select 'build.xml' in the left hand pane, then right click it and choose:

Run>External Tools>External Tools Configuration.

In the pop up window, right click on 'Ant Build' in the left hand pane, then select 'New'. This should result in the nuxeo-project-sample build.xml task appearing in the configuration. If you click on the 'Targets' tab you'll see all the tasks defined ('deploy' should be the default, which includes a 'build and copy to jboss' description). We are going to copy this configuration to make a new configuration that lets us just run the copy task which will copy our built jar file (which we've already built using Maven) into the nuxeo server plugins directory (ie. this will automate our 'deploy' which we carried out manually above by using the unix cp command).

Right click on nuxeo-project-sample build.xml in the left hand pane and choose 'Duplicate'. In the "Name" field type "nuxeo-project-sample build.xml copy jar file to plugins directory" and in the "Arguments" field, type "copy". Click 'Apply':

Nuxeo EP 5.3 11 Getting Started

Now when you right click on build.xml and choose Run As> External tools configuration and select your new 'copy' configuration to Run (click the 'Run' Button), you should see the following output in your eclipse console:

Buildfile: ~/workspace/nuxeo-sample-project/build.xml copy: [copy] Copying 1 file to ~/nuxeo/server/default/deploy/nuxeo.ear/plugins BUILD SUCCESSFUL Total time: 204 milliseconds

When developing, you will also find it useful not to have to restart jboss when performing changes in xhtml pages. Since releases 5.1.5 and 5.2-M2, you can add the line facelets.REFRESH_PERIOD=2 to the nuxeo.properties file in the nuxeo.ear/config folder in your server installation (eg. ~/nuxeo/server/default/deploy/nuxeo.ear/config): pages will be refreshed within 2 seconds.

For hot deploying web sample resources in this same manner from within Eclipse, you should create a new Ant configuration like we did above for the 'copy' configuration, but use the ant target 'web' as the argument to your ant task.

3.6. Understanding the sample code

3.6.1. Two types of changes

We can distinguish between 2 types of changes in the section that follow: i. Configuration-only changes

ii. Configuration plus Java Code changes Sometimes enhancing Nuxeo simply requires some configuration file changes or additions. In other words, you can do a lot with Nuxeo by simply changing or adding some configuration. This is one of the nice things about it. However there are other times we will also need to do a bit more work and add some Java Code to make some enhancements.

It's just nice to know this from the outset.

3.6.2. The layout of our sample project

Here is the project source layout:

Nuxeo EP 5.3 12 Getting Started

nuxeo-project-sample `-- src |-- main | |-- java ❶ | | `-- org | | `-- nuxeo | | `-- project | | `-- sample | `-- resources | |-- META-INF -- MANIFEST.MF ❷ | |-- OSGI-INF ❸ | | `-- l10n | |-- directories | |-- nuxeo.war ❹ | | |-- icons | | |-- img | | `-- incl | | `-- tabs | |-- schemas | |-- themes | '-- workflows | `-- test ❺ |-- java | `-- org | `-- nuxeo | `-- ecm | `-- sample `-- resources `-- META-INF `-- OSGI-INF

❷ The main entry point is the MANIFEST.MF file. It defines variables like Provide-Package, Require-Bundle, Nuxeo-Require and Nuxeo-Component that tell the Nuxeo EP runtime where everything is and what they depend on. They define where to load component definitions (our xml configuration files) with their associated classes and resources. Essentially when the nuxeo runtime is loading up our new jar file plugin, it looks here first to see where to find everything. ❸ Component definition (xml config) files are by convention located in the OSGI-INF folder. These Nuxeo EP components mainly consist of extension point configuration (see: Section 3.6.3, “A bit about extension points”). which add the functionality we want to Nuxeo. Note

The sample project makes an architectural choice to keep multiple xml configuration files rather than having all our configuration in a single xml file. We have chosen to group together like functions (for eg. "UI configuration, "Document type configuration") into separate xml config files. We could have chosen to put these all together in a single file. It's an architectural choice for the user in the end.

❶ The extension points (configured in our xml files) may reference one or more of the sample project's specific classes. They are all defined in the src/main/java folder. ❹ Any dedicated web templates or resources (such as icons etc) that our sample project needs to use, are defined in the nuxeo.war folder.Note that these resources will be written into the nuxeo.war folder at deployment time. ❺ Starting and stopping the Nuxeo EP server for testing the features our sample project implements is time consuming. JUnit test classes can be found in the src/test folder.

3.6.3. A bit about extension points

In much of what follows we will be talking about extension points. A good discussion of extension points is to be found in the Learning Nuxeo EP5 Guide. But it might help to just briefly qualify what we mean here when we talk about 'extension points'.

An 'extension point' can be thought of as a point in a class where it asks for information (we also say that the class 'exposes' extension point) which will allow it then to perform some function. In a sense, the class that is exposing the extension point is a helper class that allows us to add new functionality just by giving it some extra information.

A 'contribution' to an extension point is the information that is provided to that class' extension point, that then

Nuxeo EP 5.3 13 Getting Started enables the class to do its work. Contributions are usually provided by us in an xml configuration file when we want to get a Nuxeo class that exposes an extension point to do something for us with the information we give it. Below is a diagram that may help you visualize extension points:

A Bundle is equivalent to a java package like "org.nuxeo.sample" and a Component which exposes an extension point is like a Java Class (eg. "BookTitleService") or one which contributes to an extension point is like an xml file "booktitle-contrib.xml" which defines the contribution. The best way to understand this is to actually see an extension point in action. If you cant wait you can skip ahead to Section 3.6.8, “Enabling drag&drop creation (plus creating our own extension points)” in which we show how to create a class with its own extension point exposed, and then how to use it (provide a contribution to it). In any case, in every example that follows, we will be providing contributions to existing nuxeo class' exposed extension points to get them to do things for us.

3.6.4. Declaring the 'Book' document type

3.6.4.1. Objective

So away we go. To start with, we would like to declare a new Document type which represents a book (a book you can buy in a bookshop, a library book etc), that you can select and manage via our 'New Document' button on our UI:

When you click the 'New Document' button you should see our new 'Book' document type:

Nuxeo EP 5.3 14 Getting Started

This new document type wasn't there before (ie. it doesn't appear in the default out-of-the-box Nuxeo installation). Our sample project created it. We can split the task of creating our new 'Book' type into 2 parts: 1. Declaring the 'Book' type and creating the schema for this type

2. Displaying it on the UI In this section we will describe how to declare it and define the schema for it. In the next, we will show how to display it on the UI. A good reference document for this section, is chapter 5 of the Nuxeo Book: Schemas and Documents.

3.6.4.2. Creating the 'Book' document type

Declaring the book type and creating its schema, requires only configuration changes (ie. no Java code). The changes we will need to make are: 1. Create our book schema (book.xsd file)

2. Declare our new 'Book' type in core-types-contrib.xml

3. Tell the container/Nuxeo runtime how to find it (MANIFEST.MF)

3.6.4.3. Declaring the 'Book' schema

We want our 'Book' to be composed of four fields isbn, rating, publicationDate and literals. This is the schema which defines our 'Book' type. We will declare this schema in a file called src/main/resources/books.xsd. Here is a snippet from it:

... ...

We should note however, that a Document in Nuxeo is generally a composite of many schemas. If you look at the full source of the 'doctype' extension point contribution in the core-types-contrib.xml file of the next section, you'll see that the book.xsd schema we defined above, is simply one of many schemas that contribute to making up our new 'Book' document type. But we don't need to define fields like 'Title' or 'Author' in our schema, because these fields are considered standard fields that have been already well defined in already existing schemas that are available to us like the dublincore schema.

3.6.4.4. core-types-contrib.xml

Next we will create a file called src/main/resources/OSGI-INF/core-types-contrib.xml which will declare our

Nuxeo EP 5.3 15 Getting Started new 'Book' type and then link it to the schema which we have just created for it. But more importantly, this core-types-contrib.xml file provides an 'extension point contribution' to the Nuxeo org.nuxeo.ecm.core.schema.TypeService. This core Nuxeo class (TypeService) exposes a number of extension points which is like the Nuxeo class saying "You can add new customized functionality at this point, by providing this Nuxeo class with the information it needs to add this functionality in for you". For example the TypeService class exposes the following extension points, for which we can provide contributions:

org.nuxeo.ecm.core.schema.TypeService |-- doctype (declare a new Document Type) |-- schema (declare your new Document Type's schema) |-- type (show your new Document Type on the UI) |-- ... |-- etc |-- ...

Contributions to the doctype and schema extension points, only require the addition of the configuration files we are defining here (core-types-contrib.xml and book.xsd). Once defined, the TypeService class knows how to use them to create our new 'Book' type in Nuxeo. All we have to worry about is giving the TypeService the information it needs.

Here is the corresponding XML snipset extracted from the core-types-contrib.xml file

... ... ... ... ...

How do we know what information the TypeService needs ? Fortunately all this is documented here: Extension Points Documentation (5.1) and here: Extension Points Documentation (5.2) . For example if you click on the org.nuxeo.ecm.core.schema.TypeService link, you will see all the extension points that it exposes, and how to configure these in your xml.

3.6.4.5. Adding a reference to our Manifest file

Adding a reference to our core-types-contrib.xml to our manifest tells the container and nuxeo where to find our changes to add a new 'Book' document type. Here is the relevant snippet:

.... Nuxeo-Component: OSGI-INF/core-types-contrib.xml, ....

3.6.4.6. JUnit Tests

So far we have declared the 'Book' type and schema, but all that means is that Nuxeo knows about it. As it stands, the user wont be able to see our new 'Book' type unless we explicitly add it to the UI (That's where the next section comes in). However we can still test what we have done, and in fact it is important to do so. We do this by writing some junit tests.

There are differences in the way Nuxeo version 5.1 and 5.2 handles new Document types, based on the fact that changes were made in the repository between the 2 versions.

Nuxeo EP 5.3 16 Getting Started

The TestBookType.java test inherits from RepositoryOSGITestCase in 5.1 and SQLRepositoryTestCase in 5.2, which both inherit from NXRuntimeTestCase which in turn eventually inherits from JUnitTestCase.

junit.framework.TestCase |-- .... |--NXRuntimeTestCase |--RepositoryOSGITestCase (5.1) |--SQLRepositoryTestCase (5.2)

The NXRuntimeTestCase is the "raw" testcase which does a lot of OSGI related test setup, and is primarily concerned with the startup and shutdown of the nuxeo runtime in our tests. The RepositoryOSGITestCase is used for 5.1, as it handles the JCR implementation of the repository, whereas the SQLRepositoryTestCase is used for 5.2 as it handles the VCS implementation of the repository (See Nuxeo Book chapter xxxx)

The test for our declaration of the new 'Book' type and its associated schema, is inside the testBookCreation() method within TestBookType.java, which has inline documentation to explain what each step does.

A useful thing to know is that the RepositoryOSGITestCase methods: 1. coreSession.saveDocument(DocumentModel): saves our Book document to the session in memory

2. coreSession.save(): saves all the session changes to the repository on disk The session can be thought of as a series of changes that are written to it. Each change written to a session (like the coreSession.saveDocument() one) is very cheap because it is done in memory. At the end, calling the coreSession.save() writes all these changes to disk in one hit, which again helps with performance.

3.6.5. Displaying book documents

3.6.5.1. Objective

In this section we want to get our new Book document type to appear on the UI. Again, this involves only configuration changes (ie. no java coding is necessary). We will end up adding or changing the following files: 1. ui-contrib.xml

2. book.png

3. layout-contrib.xml

4. deployment_fragment.xml

5. MANIFEST.MF

3.6.5.2. Label and Icon

Books are displayed on the screen using a specific icon and label. You can see in second figure in the Section 3.6.4.1, “Objective” above, the little 16x16 image of a book, followed by the label "Book". This is achieved by providing an extension point contribution to the TypeService's exposed extension point called "type" which is responsible for displaying both of these on the UI (see section Section 3.6.4.4, “core-types-contrib.xml” above for the listing of exposed extension points of TypeService). Note however, that instead of adding our contribution to the core-types-contrib.xml file as we did when we were declaring our Book document type, we will instead add this contribution to the ui-types-contrib.xml file. This is so that all the contributions to do with UI changes can be grouped together separately. Here is the corresponding XML snipset extracted from the ui-types-contrib.xml file

... ... ...

Nuxeo EP 5.3 17 Getting Started

/icons/book.png ... ... ...

The attribute id="Book" must match the "doctype name" declared in the core-types-contrib.xml declared above. The coretype="Book" attribute is now optional in 5.2, but if it is present, its value must match the id attribute's value.

Note

Test it: if you want to see the effect of the

Also, we need to put our little 16x16 icon "book.png" in the src/main/resources/nuxeo/icons directory for it to be deployed correctly to the server (where it will ultimately end up in the ~/nuxeo/server/default/deploy/nuxeo.ear/nuxeo.war/icons directory).

In order to ensure that it does indeed end up there, we need to make sure we have the following line in the OSGI_INF/deployment_fragment.xml file:

nuxeo.war/**

3.6.5.3. Adding a reference to our Manifest file

Adding a reference to our ui-contrib.xml to our manifest tells the container and nuxeo where to find our new additions. Here is the relevant snippet:

.... Nuxeo-Component: OSGI-INF/core-types-contrib.xml, .... OSGI-INF/ui-contrib.xml, ....

Note that the order of these components matters, because our ui-contrib.xml depends on the core-types-contrib.xml.

3.6.5.4. How to display our Book's fields on our UI

Remember above ( Section 3.5.10.2, “Viewing your changes”) we had to create a new Nuxeo Workspace in which to create our new Book document. The rules that determine where we can display our new Book document on the UI are actually defined in our ui-types-contrib.xml file as well.

We will make a rule that Book documents can be displayed under Nuxeo folders or workspaces. These containment rules are declared to the exposed extension point called "types" in the org.nuxeo.ecm.platform.types.TypeService class. Note that this is a different "TypeService" class than the one above (check the fully qualified path name !). Documentation for the extension points exposed by this class can be found here: org.nuxeo.ecm.platform.types.TypeService

We will define this extension point contribution in the ui-types-contrib.xml file as well because our contribution relates to UI changes. Here is the XML snipset extracted from the ui-types-contrib.xml that defines them.

...

Nuxeo EP 5.3 18 Getting Started

... Book Book ... ...

Again, the "coretype" attribute must contain a value that relates to one of the Nuxeo Core Types or a Type that we have created ourselves like 'Book'.

3.6.5.5. The Layout of our Book document UI

3.6.5.5.1. Defining which layout(s) to use

Aside from displaying the little book icon and "Book" label on the screen where our Book types are accessible, we can now proceed to the more magnanimous task of defining how the UI for creating/editing or viewing a Book document looks like. For eg: Creating a new Book:

Viewing an existing Book:

Nuxeo EP 5.3 19 Getting Started

We do this by defining the template(s) to use in our ui-contrib.xml file. This is an additional contribution to the same "types" exposed extension point in the same org.nuxeo.ecm.platform.types.TypeService class as above:

... ... ... heading book file ... ... ...

The "layouts" section defines what templates Nuxeo will use to display your Book document type on the UI. The individual s (which we will see in the next section) define what fields are shown and how they are shown. The snippet above shows that we are using 3 layouts which Nuxeo will combine in order from top to bottom on the screen. For example in the first picture in Section 3.6.5.5, “The Layout of our Book document UI” above, the "header" is responsible for displaying the fields in the top part of the UI. You will note that these include "Title" and "Description" fields which are part of the dublincore schema of our book. The "book" , displays our "ISBN" field from our book schema. Lastly the "file" displays the "Content" section where the user can choose to upload a file.

Note

Test it: remove the two lines:

heading file

then rebuild your jar, redeploy to the plugins directory and restart your server.

Nuxeo EP 5.3 20 Getting Started

We will define the "book" in the next section, but the "header" and "file" s come standard with Nuxeo. 3.6.5.5.2. Defining our custom "book" layout

In the section above we told Nuxeo that we would define a called "book" which would describe what Book fields we wanted to see on the UI. In this section we will show you what that definition looks like. We want the ISBN book field to be displayed onto our UI when the user is creating a new book or editing or viewing it content. This is achieved by defining a layout in a new file we will create called layouts-contrib.xml which will group together all our layouts. Indeed, all we are doing is contributing to the "layouts" extension point of the WebLayoutManager class. Each particular layout is defined inside this extension point. Here is the XML extracted from the layouts-contrib.xml file that registers our layout with the WebLayoutManager:

isbn false bk:isbn edit view ...

In a layout we define rows of widgets (elements that are seen on the UI). We have one row with the "isbn" widget.

Each widget definition (in our case we only have one widget - the isbn widget) is then provided in the section of our xml file. A widget definition contains:

A "type": (eg. "text") which defines how the widget is displayed on the UI (eg. a text entry box in edit mode or a text string in view mode).

The section defines what labels you would like to appear next to the widget. You can define a different label for each "mode". For eg. in 'edit' mode you could have 'Please enter an isbn number:' and in 'view' mode you could have 'ISBN number entered:'. In our case we have a "mode" of 'any' which means display the same label in all modes.

The "fields" section describes which fields in our schema to map the widget to. In our case we are mapping to our "book" schema's isbn field.

Lastly the "widgetMode" node tells us which modes our widget will appear in on our UI (in our case the 'edit' and 'view' modes).

Nuxeo EP 5.3 21 Getting Started

3.6.5.6. MANIFEST.MF

Don't forget to add entries into your MANIFEST.MF file to reference the new files you have created:

.... Nuxeo-Component: OSGI-INF/core-types-contrib.xml, OSGI-INF/ui-contrib.xml, OSGI-INF/layouts-contrib.xml, ....

3.6.5.7. Unit Tests

It is possible to install Selenium to test our new UI changes as it is difficult to write JUnit tests to do so. For now, we suggest just starting up the Nuxeo server and going in and verifying that your changes work by creating a new Book document and seeing if you can view it.

3.6.5.8. Summary

In this section we described how to get the our Book document's fields to be displayed on the screen, and how to display them.

3.6.6. Actions, tabs and behavior

3.6.6.1. Objective

We can add tabs to the different views a user has in the Nuxeo UI and associate different behaviors with each tab.

In this section we will describe how to add 2 tabs: 1. A "Books" tab to the workspace view: When you click on a workspace, you will see a number of tabs. We will insert a "Books" tab that lets you do certain book associated tasks, like viewing all the books in the folder and searching for all books with a particular keyword (see: Section 3.6.7, “Making book documents indexable and searchable” ). Note

Searching on a keyword assumes these keywords have been setup somewhere and somehow. We will just assume this in this section. We show you how to set up the keywords in Section 3.6.11.5, “Directories and Vocabularies”

2. A "Book" tab to the book view: When you click on a book item that you have already created, you will also see another tab called 'Book' which allows you to edit some of the Book's properties and attach Keywords to the book (these are the keywords we can search on in the "Books" tab above).

Nuxeo EP 5.3 22 Getting Started

It is the first time also that we will be using some Java code in addition to configuration changes/additions. The java code will help us implement some of the custom behavior we want. However we will not focus on this, as it is important to understand that you can do a lot with just the configuration changes that we will explain.

A good reference for this section is Section 7.1, “Introduction”

3.6.6.2. Configuration

Our configuration happens in a file called actions-contrib.xml. In this file we provide a contribution to the extension points called "actions" and "filters" on the ActionService class. Here is the actions-contrib.xml file:

VIEW_ACTION_LIST VIEW_ACTION_LIST Folder Workspace Book

The first thing to note are the 2 extension point contributions "actions" and "filters".

The "filters" extension point: is where you can add a "filter". Filters are generally are used to change the access rights to a tab. We name and create filters in this section when our filter is particularly complex (and we then want to separate it, define it, and call it by name from the "actions" extension point), or when we just want to re-use a particular filter, and therefore we can again reference it by its name.

Our example filter in actions-contrib.xml called "book_filter", is saying that if a Document is a child of the "Book" type, then grant access (visibility) to this tab. This example shows how filters can be used to manage access rights to tabs. It is convenient, as the user does not have to write Java code to deal with permissions.

The "actions" extension point: is used to configure what action to take when it is selected. The action id names the action. If you hover your mouse over the "Book" tab in the Book view (select a book that you have already

Nuxeo EP 5.3 23 Getting Started created and then hover your mouse over the "Book" tab on the next screen), you'll see that the url contains the action id.

The "link" attribute identifies which action to call when your tab is selected. The link here specifies a JSF page called book_view.xhtml. We will describe this JSF page in brief in a following section. For now, all we need to know is that clicking the "Book" tab will request this action. The "enabled" attribute is also important, because it defines whether or not a tab will be visible to the user or not. So we can turn the visibility of tabs on and off with this attribute which is quite useful. The "label" is the text that will appear on the tab, and the "icon" is the icon associated with the tab.

The "category" node defines a pre-defined place on the page on which to display your tab. Common values are: 1. VIEW_ACTION_LIST: used for tabs

2. USER_SERVICES: used to display actions in the top right corner of every page

3. SUBVIEW_UPPER_LIST: used to display actions just below a document tabs listing See Section 7.2.2.2, “Manage category to display an action at the right place” for more information.

The "filter" node is also important. You can define either an inline filter (as has been done with the "tab_folder_books_list" action), or you can just call a named filter (which is what the "tab_book_view" action does). The "filter" nodes define what filters to associated with this action. For the "tab_book_view" action, our filter allows the user access to the tab only if the document is a child of the Book type.

3.6.6.3. JSF/Java

The actions-contrib.xml file above, calls the book_view.xhtml and folder_books_view.xhtml jsf pages as its actions. (Note that tab's templates are defined into the folder nuxeo.war/inc/tabs.) Without going into detail, you can see from the snippet below that the jsf looks a lot like html, but with the use of jsf tags like instead of html.

Note also that these templates get their model using the BookManagerBean which implements book behaviours. You'll see that anything with the "#{}" around it is a call to the BookManager.java class.

3.6.6.4. Summary

In this section we saw how to add tabs with access permissions and behaviors using contributions to the "actions" and "filters" extension points on the ActionService class. Don't forget to add a line to your MANIFEST.MF to include the actions-contrib.xml file. The next section includes details of how the "Books" tab page is used.

3.6.7. Making book documents indexable and searchable

3.6.7.1. Objective

We want to allow our book to be searchable via the Nuxeo UI. There is a little 'search box' in the top left corner of our Nuxeo UI. You don't need to do anything specific to have this search, search any of your book documents.

However, in the section below, we will show how to do a customized search that you can set up 'programatically'. To do this we need to do 4 things: 1. Tell Nuxeo which fields from our Book schema to index. Indexing means that these fields can be searched when a user does a search. Note however, that this first step is only necessary in Nuxeo 5.1. In Nuxeo 5.2 you no longer have to tell Nuxeo which fields to index in your Document schema, because it will index all fields by default.

2. We also need to tell Nuxeo how to search. For example, should we search with 'Starts With' or 'Contains' and which fields should we search.

Nuxeo EP 5.3 24 Getting Started

3. Then we need to tell Nuxeo what Java class will be doing the searching for us.

4. Finally we will need a page on the UI to show our search options and display our search results. A good reference for this section is Section 11.1, “Introduction”.

3.6.7.2. Indexing

Our first step is to tell Nuxeo which fields in our Book schema we want indexed. These indexed fields will be the ones that can be searched. This step is only necessary in Nuxeo 5.1. In 5.2, all fields from our Book schema will be searchable by default.

To tell Nuxeo which fields to index, we register an extension point contribution to the extension point called "indexableDocType" on the SearchServiceImpl class. We do this in a file called the search-contrib.xml file. Don't forget that we need a reference to this in our MANIFEST.MF as it is a new file. Here is the contents of the search-contrib.xml:

As you can see we are telling the SearchServiceImpl class to index all fields on all schemas that make up our Book document. So all fields of our book will be searchable.

3.6.7.3. Query Model

Next we need to tell Nuxeo how we want to search. This is called our 'Query Model'. The query model lets us define our search in an 'SQL-like' way so that we can specify our search parameters. An example in pseudo-code might be:

"select all Book documents where the user's input string matches one of the book's keywords.".

To do this, we register a 'Query Model' with the "model" extension point of the QueryModelService. We can do this by creating a new file called querymodel-contrib.xml and specifying the search "pattern":

SELECT * FROM Document WHERE ecm:primaryType = 'Book' AND ecm:path STARTSWITH ? AND bk:keywords = ?

The query language that we use in the "pattern" attribute is called NXQL and more documentation about it can be found here: Section 11.3.1, “Fields and literals” .

3.6.7.4. Tell nuxeo about our search class

After we have setup our query model, we need to register the Java Class that will be invoking this query model

Nuxeo EP 5.3 25 Getting Started

(and dealing with the results of the query), with the "model" extension point of the ResultsProviderService. Again we do this in a new file called: resultsprovider-contrib.xml. Here are the contents of that file:

Notice that the "farm" attribute points to the src/main/java/BookResultsProvider.java class that we have written. This class will be the class that retrieves the query model we setup above and uses it to perform our customized search.

3.6.7.5. Displaying our Search Results

Finally having set up our search, we need a page to display the search options and show the results of our search on the UI. We do both these things on the same page: Books are both searched for, and listed, in the book's tab using the resultsProviderCache which we can access in the folder_books_view.xhtml JSF page we setup above: Section 3.6.6.2, “Configuration”

... ...

The following screen shot shows the results of our handiwork:

Note: you can setup your books to appear in this screen like this by selecting a book that you have already created, going to the "Book" tab and entering in Keyword and Note for your book. Then clicking on a Keyword searches for all the books that contain that keyword if it was entered against them on the "Book" tab.

3.6.7.6. JUnit Tests

3.6.8. Enabling drag&drop creation (plus creating our own extension points)

Nuxeo EP 5.3 26 Getting Started

3.6.8.1. Objective

Nuxeo makes it easy to enable drag and drop so that dragging a file onto a workspace will automatically create a Book document. In this section we will show you how to enable drag and drop in Nuxeo. Note

You will need to install the nuxeo drag and drop plugins for Firefox or Internet Explorer for drag and drop to work. You can download these at: • Firefox Extension

• Internet Explorer Extension

As by-product of explaining how to enable drag and drop in Nuxeo in this section, we will see how to create our own Service and create an extension point on that service. So far we have been only providing contributions to existing extension points in services within Nuxeo. But this section gives us the opportunity to 1. Create our own service with its own exposed extension point

2. Provide a contribution to our own exposed extension point

3.6.8.2. Notification for drag and drop events

But first, before we create our own service with its own extension point, let us again begin by providing an extension point contribution to an existing Nuxeo service. By providing an extension point contribution to the "plugins" extension point on the FileManagerService class, we can have this class notify us when a drag and drop event occurs. We will put this contribution in the filemanager-contrib.xml file:

image/gif image/jpeg

The BookFileManagerPlugin has requested that the FileManagerService call the BookFileManagerPlugin class whenever a gif or jpeg upload (drag and drop) occurs. The notification takes the form of calling the BookFileManagerPlugin's create() method.

3.6.8.3. Registering our own Service

Now we get to register our own service with its very own extension point exposed. This service is called by our BookFileManagerPlugin when it has been notified by the Nuxeo FileManagerService that a ".gif" or ".jpeg" has been dragged and dropped onto the UI. The BookFileManagerPlugin will use this Service to help it create a new Book document from the uploaded file.

We will register the service in the booktitle-service-contrib.xml file as follows:

Nuxeo EP 5.3 27 Getting Started

In creating this xml configuration, we are defining a new nuxeo called org.nuxeo.project.sample.BookTitleService which defines a new service called BookTitleService whose class is the org.nuxeo.project.sample.BookTitleServiceImpl class. Furthermore, we define an point on our component called "title", which we will map to a java class called BookTitleDescriptor.

Ok. Now when we define our extension point contribution, which we will do in the booktitle-contrib.xml file, the fields in this xml file should map to the annotations in our BookTitleDescriptor. This is essentially how you find out what information your extension point requires:

Table 3.1. Extension Point

booktitle-contrib.xml BookTitleDescriptor.java

package org.nuxeo.project.sample; @XObject("configuration") true public class BookTitleDescriptor { true (automatic) @XNode("addInitialCapital") protected boolean addInitialCap; @XNode("addComment") private String addComment; public String getAddComment() { return addComment; } private boolean remove; @XNode("removeExtension") protected void setRemoveExtension(boolean remove) { this.remove = remove; } public boolean getRemoveExtension() { return remove; } }

So the flow of events when a ".gif" or ".jpeg" document is dragged onto the Nuxeo UI is as follows:

The FileManagerService notifies the BookFileManagerPlugin by calling its create() method. To do its work of creating a new Book document, the BookFileManagerPlugin class calls the BookTitleService's correctTitle(title) method, passing it the name of the file that was uploaded. The BookTitleService then retrieves the values provided by the "title" extension point which are set in the booktitle-contrib.xml file, and uses these to correct the title (ie. Change the first letter to a capital, removes the file extension - eg. ".gif"), and adds a comment, before creating a new Book document with this title and saving it to the repository.

FileManagerService |-- BookFileManagerPlugin.create() |--BookTitleServiceImpl.correctTitle(title) |-- BookTitleDescriptor (get values from booktitle-contrib.xml config) |-- create the title base on the values |-- create the new Book with this title in the repository

3.6.8.4. JUnit Tests

Nuxeo EP 5.3 28 Getting Started

The Sample Project contains a class called TestBookTitleService which tests whether our new configuration and java changes for creating our new BookTitleService service works.

3.6.8.5. Differences between 5.1 and 5.2

If you look at the source code of the BookFileManagerPlugin in the 5.1 vs 5.2 branch, you will notice that in 5.1 it extends AbstractPlugin whereas in 5.2 it extends AbstractFileImporter. The AbstractPlugin is deprecated in 5.2.

The BookManager and BookMangerBean classes have import(s) changed from 5.1 to 5.2:

import org.jboss.seam.annotations.WebRemote; (5.1) import org.jboss.seam.annotations.remoting.WebRemote; (5.2) and

import org.jboss.seam.core.FacesMessages; (5.1) import org.jboss.seam.faces.FacesMessages; (5.2)

As these have changed packages between the jboss versions used between 5.1 (4.0.5) and 5.2 (4.2.3).

The BookManager interface has been changed to return a DocumentModelList instead of a ResultSet

public ResultSet getSearchResults() throws Exception; // (5.1) public DocumentModelList getSearchResults() throws Exception; //(5.2) and the BookManagerBean which implements the BookManager interface, has had its code updated accordingly, and also been made Serializable. The reason is that SearchService is not used anymore. Now queries are executed with the method query() from the CoreSession, and this new method returns a DocumentModelList instead of a ResultSet.

The BookResultsProviderFarm has also been made Serializable in 5.2, and had its call to getResultsProvider() updated.

3.6.9. Regulating book states

3.6.9.1. Objective

We want to make Books be regulated by the standard life cycle ( project, approved, obsolete, deleted states). As defined in the Chapter 4 of the Nuxeo User's Guide "The evolution of a document, each time contributors edit it, constitutes its life cycle ... To change the life cycle state of a document, you need to submit it to a workflow.". You can find out more about life cycles and workflows from the user's perspective by reading Chapter 4 of the Nuxeo User's Guide .

In this section we will show you just how to register a document to the default life cycle states. To get it to actually transition between these states will be discussed in a separate section on Section 3.6.10, “Workflow” .

3.6.9.2. How to

We can get a Book to follow the Nuxeo standard lifecycle by declaring to the "types" extension point of the LifeCycle Service that Books follow the "default" life cycle. Here is the lifecycle-contrib.xml file

default

Nuxeo EP 5.3 29 Getting Started

Getting your new Book document type to follow the standard Nuxeo lifecycle is as simple as that. Don't forget that a reference to the lifecycle-contrib.xml file also needs to go in the MANIFEST.MF file.

3.6.9.3. JUnit Tests

We can also write a JUnit Test to test our life cycle contribution. If you look in the sample project's src/test/java directory you'll see a test class called TestBookLifeCycle.java. It is self documented for you to follow the steps.

3.6.10. Workflow

3.6.10.1. Objective

3.6.10.2. Workflow in 5.1

TO DO (code not yet implemented in 5.1 branch either)

3.6.10.3. Workflow in 5.2

TO DO (code exists in 5.2 branch)

3.6.11. Listening for events

3.6.11.1. Objective

Event Listeners are java classes that get notified by nuxeo when a particular type of event (that they are "listening" for) occurs. In this section we will show you how to create your own Event Listener java classes to listen for particular events and then to do something useful when the event occurs.

3.6.11.2. Registering event listeners

Event Listeners are registered as contributions to the extension point "listener" on the EventServiceComponent class (in 5.2) or on the CoreEventListenerService class (in 5.1). In the sample project we have registered these event listeners in the event-listener-contrib.xml file. These contributions are basically registering a java class that you will write (our "EventListener" classes), that will get notified when a particular event occurs. The event or events that your customized class listens for can be specified by the tag in the xml. Here is the listing of event-listener-contrib.xml:

emptyDocumentModelCreated documentCreated documentModified

As we can see above are 2 event listeners in the sample project: 1. BookEventListener: which listens for an 'emptyDocumentModelCreated' event

Nuxeo EP 5.3 30 Getting Started

2. BookISBNEventListener: which listens for both documentCreated and documentModified events

3.6.11.3. BookEventListener

Our BookEventListener class will get notified whenever a emptyDocumentModelCreated event occurs. In other words, when the user clicks the 'New Document' button, it will get notified. The class itself is very simple. It implements the EventListener interface, which means that we must implement a handleEvent(Event event) method in our event listener, which is passed the event that has occurred:

public void handleEvent(Event event) throws ClientException { EventContext ctx = event.getContext(); if (ctx instanceof DocumentEventContext) { DocumentEventContext docCtx = (DocumentEventContext) ctx; DocumentModel doc = docCtx.getSourceDocument(); if (doc != null) { String type = doc.getType(); if ("Book".equals(type)) { process(doc); } } }

This method checks to see if our Document type is a 'Book' and if it is, it calls the process(doc) method (not shown), passing it the Book document, which does all the work of creating some default values for the Book's 'Title' and 'Description' fields. The user sees these as 'Sample Book' and the '(Created on 2009-01-01)' in the editable Title and Description fields respectively on the screen where a new Book is being created. The user can overwrite these values if they wish.

3.6.11.4. BookISBNEventListener

The BookISBNEventListener class listens for documentCreated and documentModified events. When it is notified that one of these events has occurred, once again its handleEvent() method is called. After checking that the event applies only to Book document types, it calls its process() method do deal with these events.

It is at this point that we can see that it that we need to digress a little, to explain what is happening next. That is because it starts doing things with a DirectoryService and a Vocabulary.

3.6.11.5. Directories and Vocabularies

The sample project defines an extension contribution to the SQLDirectoryFactory class called "directories" in the file directories-contrib.xml whose contents are listed below:

book_keywords
on_missing_columns directories/book_keywords.csv

In Nuxeo, a Directory is a programmatic abstraction that let's us deal with any relational database, regardless of the actual underlying implementation (some examples might be certain implementations of ldap, databases, csv files etc). The chapter on Directories and Vocabularies in the nuxeo book, contains a convenient diagram in the Introduction section which diagrams this abstraction. A The "directories" extension contribution contained in the directories-contrib.xml file shown above, defines a new directory called "book_keywords". This directory is based on the schema, which is a core nuxeo schema and can be found in the vocabulary.xsd file in the ~/nuxeo/server/default/data/NXRuntime/schemas/ directory under your server installation. If you look at this schema you'll see it contains 4 fields: id, label, obsolete and ordering. The

Nuxeo EP 5.3 31 Getting Started xml node in the directories-contrib.xml defines which of these 4 fields is the key field.

The other xml nodes define the other aspects of the book_keywords directory that we are defining. The node defines that we will keep the initial data that will populate this directory in the book_keywords.csv file. If you browse to that file in the sample project you'll see its contents:

id, label, obsolete "1","Novel",0 "2","Bestseller",0 "3","Academic",0

The node points to the actual implementation of our directory and where our data will be really stored. In our case we are using the default nuxeo sql data source and naming the table that holds our data in this dataSource

book_keywords
. Finally the node, takes a value of on_missing_columns, which means that nuxeo will load the contents of your book_keywords if your book_keywords schema is updated. Thus when the server is first started, and no data exists in the table, the book keywords will be loaded in. Then if the server is restarted, no changes will be made to the database unless the schema has been changed.

So we have defined a Directory that will hold our book keywords that we get from our book_keywords.csv file. What do we then do with this Directory ? We can see what happens when we look at the process() method of BookISBNEventListener. Whenever a document is created or modified, our process() method gets a DirectoryService to our "book_keywords" directory. It then matches the value of the ISBN field of our book against the value of the id column of our book_keywords data (the call to dir.getEntry() will use the value of the key field 'id' defined in our book_keywords directory to match against).

dir = dirService.open("book_keywords"); DocumentModel entry = dir.getEntry(isbn);

If there is no match (the entry returned is null), it will create a new entry in our directory with the isbn as the "id" and the title as the "label". The mapping between our Book and our book_keywords fields is shown in the table below:

Table 3.2. Book v Book Keywords mapping

Book (Document) field book_keywords (Directory) field isbn id title label

If you look at the rest of the code in the process() method of BookISBNEventListener, you'll see that if there is a match between the isbn of the book and the id of the book_keywords, it will update the label of the matching book_keyword entry with the title of the matching book.

So that explains what BookISBNEventListener does, and what all the Directory/Vocabulary code in the sample project is about. The page that actually uses this code is the search facility of the 'Books' tab described in the Section 3.6.6, “Actions, tabs and behavior ” section above.

3.6.11.6. JUnit Tests

TO DO

3.7. Starting a new project

The goal of the nuxeo-archetype-start template is to setup a Nuxeo EP plugin development environment. The template provides: a maven layout for sources, tests and dependencies, an Ant target for deployment. It also customizes the web application a litte bit.

Start the “new maven project” wizard from the menu File > New > Maven project. Enable your eclipse for

Nuxeo EP 5.3 32 Getting Started using Nuxeo EP's by addind a remote archetypes catalog using the configure dialog. The URL to be used is as follow http://maven.nuxeo.org/nuxeo-release/. Select the archetype type nuxeo-archetype-start and the nuxeo's version you want your project based. Set the artifact parameters according to your organisation rules.

3.8. Using Documentation

• The Nuxeo Book is getting to be the most complete source of information around Nuxeo EP, both for beginners and advanced developer. It is a good start.

• The extension point documentation is also very useful: although you may find it rough, it is the best way to evaluate the Nuxeo extensibility potential, and one should always start with a quick look around all the extension points, to "think Nuxeo" before starting a new project, and not reinventing the wheel.

• The wiki: we try to reference all the documentation from the wiki welcome page, and you will find tricks, howtos, etc. If you want to have a writer account to help update the content, ask on the Nuxeo's mailing list.

3.9. Other IDEs: IntelliJ IDEA and NetBeans

3.9.1. IDEA

IntelliJ IDEA from Jetbrains is a very lovable IDE for Java that has many fans in the Java developers community. It is unfortunately not open source.

To start using IDEA for coding on the Nuxeo project, you just need to type mvn idea:idea from your top-level source directory: Maven will download all the dependencies, then generate the configuration files needed by IDEA and you will be able open nuxeo-ecm.ipr from IDEA.

Note

At the time of this writing, IDEA will report some (spurious) compilation failures and you won't be able to compile the whole application from IDEA. You can still use IDEA with the current configuration to write Java code ("with pleasure"), and use Ant and/or Maven to build/deploy the application.

3.9.2. NetBeans

NetBeans is an open source IDE from Sun.

If you're using NetBeans 6 or later, you will be able to download a Maven 2 support plugin from NetBean's "Update Center", and with it, start coding on Nuxeo EP very quickly.

Nuxeo EP 5.3 33 Chapter 4. General Overview

4.1. Introduction

4.1.1. Architecture Goals

When we started building Nuxeo EP, we defined several goals to achieve. Because these goals have a structural impact on Nuxeo EP platform it is important to understand them: it helps understanding the logic behind the platform.

4.1.1.1. Flexible deployment on multiple targets

An ECM platform like Nuxeo EP can be used in a lot of different cases.

The deployment of Nuxeo EP must be adapted to all these different cases: • Standard ECM web application

This is the most standard use case. The web browser is used to navigate in content repositories.

• All services are deployed on an Application server

• In order to be easily hostable, the platform needs to be compatible with several application servers

• Complex edition or rich media manipulation

In this case having a rich client that seamlessly communicates with other desktop applications and offers a rich GUI is more comfortable than a simple web browser.

• Interface is deployed on a rich client on the user desktop

• Services and storage are handled on the server

• Offline usage

In some cases, it is useful to be able to manipulate and contribute content without needing a network connection.

• GUI and some services (like a local repository) need to be deployed on the client side

• Server hosts the collaborative services (like the workflow) and the central repository

• Distributed architecture

In order to be able to address the needs of large decentralized organizations, Nuxeo EP must provide a way to be deployed on several servers on several locations

• Scale out on several servers

• Dedicate servers to some specific services

• Have one unique Web application accessing several decentralized repositories

• Use Nuxeo EP components from another application

When building a business application, it can be useful to integrate services from Nuxeo EP in order to address all content oriented needs of the application.

• Provide web service API to access generic ECM services (including repository)

Nuxeo EP 5.3 34 General Overview

• Provide EJB3 remoting API to access generic ECM services (including repository)

• Provide POJO API to generic ECM services

There are certainly a lot of other use cases, but mainly the constraints are: • Be able to choose the deployment platform: POJO vs Java EE

As first deployment targets we choose

• Eclipse RCP: a rich client solution that uses a POJO (OSGi) component model

• JBoss Application Server: a Java EE 5 compliant application server

• Be able to choose the deployment location of each component: client side vs server side

The idea is to be able to deploy a component on the server side or on the client side without having to change its code or its packaging

4.1.1.2. Leverage CPS experience

Before building Nuxeo EP we worked during several years on the Zope platform with the CPS solution. CPS was deployed for a lot different use cases and we learned a lot of good practices and design patterns. Although Nuxeo EP is a full rewrite of our ECM platform, we wanted to keep as many of the good CPS concepts as possible. • Concept of schemas and documents

Inside CPS most of the data manipulated was represented by a document object with a structure based on schemas.

This concept is very interesting:

• Schemas enforce structure constraints and data integrity but also permit some flexibility.

When defining a schema you can specify what fields are compulsory, their data types etc, but you can also define some flexible parts of the schema.

• Share API and UI components for Documents, Users, Records ...

Because the Document/Schema model is very flexible it can be used to manipulate different types of data: like Users, Records and standards documents.

From the developer's perspective this permits using the same API and be able to reuse some UI components

From the users' perspective it gives the application some consistency: because the same features and GUI can be used for all the data they manipulate.

• Actions and Views

Because CPS was very pluggable, it was possible to easily define different views for each document type and also to let additional components contribute new actions or views on existing documents.

Nuxeo EP has a similar concept of views and actions, even if technically speaking the technologies are different.

• Lazy fetching and caching

Because ECM applications make a very intensive use of the repository and often need to fetch a lot of different documents to construct each page, the way the document retrieval is handled if very important

Nuxeo EP 5.3 35 General Overview

to have a scalable application.

With CPS we worked a lot on caching and lazy fetching.

With Nuxeo EP we incorporated this requirement from the beginning:

• Distributed caching

• Lazy fetching on schemas and fields

4.1.1.3. Extensible platform based on components

CPS was constructed as a set of pluggable components relying on a common platform. This modularity has been maintained in the new platform. Deploying a new feature or component on the new platform is as simple as it was on the old one.

This requirement has a huge impact on the platform because the Java packaging model and the Java EE constraints are not directly compatible with it.

Adding a new component should be as simple as dropping a file or an archive in some directory without having to rebuild nor repackage the application.

This is important from the administrator point of view: be able to easily deploy new features.

This is also very important from the support point of view: to be able to deploy customized components without taking the risk of forking the platform, and maintaining the possibility to upgrade the standard components.

4.1.1.4. Easily accessible development framework

The CPS framework was powerful but we know it was very complex to use. Not only because of the unusual CMF/Zope/Python programming model, but also because there was a lot of different concepts and you had to understand them all to be able to leverage the platform when building a new application on top of it.

Nuxeo EP aims at simplifying the task of the developer • Clearly separate each layer

The idea is to clearly separate presentation, processing and storage so that developers can concentrate on their task.

• Offer plugin API and SPI

Nuxeo EP is constructed as a set of plugins so you can modify the behavior of the application by just contributing a new plugin. This is simpler because for common tasks we will offer a simple plugin API and the developer just has to implement the given interface without having to understand each part of the platform.

• Rely on JAVA standards

We try to follow as much as possible all the Java standards when they are applicable. This will allow experienced Java developers to quickly contribute to the Nuxeo EP platform.

4.1.1.5. Leverage Java open source community

We know what it's like to have to build and maintain an entire framework starting from the application server. With the switch to the Java technology, we will use as many existing open source components as possible and focus on integrating them seamlessly into the ECM platform. Nuxeo EP is a complete integrated solution for building an ECM application, but Nuxeo won't write all infrastructure components. This approach will also make the platform more standards compliant.

Nuxeo EP 5.3 36 General Overview

Thus developers can optimize their Java/JEE and open source experience to use Nuxeo EP.

4.1.1.6. Make the platform ready for SI integration

Because ECM applications often need to be deeply integrated into the existing SI, Nuxeo EP will be easily integrable • API for each reusable service or component

Depending on the components, this API could be POJO, EJB3, or WebService, and in most cases it will be available in the three formats.

• Pluggable hooks into Nuxeo EP

This mainly means synchronous or asynchronous events listener that are a great place to handle communication and synchronization between applications.

4.1.1.7. Future-proof design

The Nuxeo EP platform was rewritten from the ground up with the switch to Java. But we don't plan to do this kind of work every couple of years, it won't be efficient neither for us, nor for the users of the platform. For that reason, we choose innovative Java technologies like OSGi, EJB3, JSF, Seam ....

4.1.2. Main concepts and design

All the design goals explained just before have a huge impact on the Nuxeo EP architecture. Before going into more details, here are the main concepts of Nuxeo EP architecture.

4.1.2.1. Layered architecture

Nuxeo EP is built of several layers, following at least the 3 tiers standard architecture • Presentation layer

Handles GUI interactions (in HTML, SWT ...)

• Service layer

Service stack that offers all generic ECM services like workflow, relations, annotations, record management...

• Storage layer

Handles all storage-oriented services like document storage, versioning, life cycle ....

Depending on the components, their complexity and the needed pluggability, there can be more than 3 layers.

This layering of all the components brings Nuxeo EP the following advantages • The ability to choose the deployment target for each part of a component

By separating clearly the different parts of a feature, you can choose what part to deploy on the client and what part to deploy on a server.

• Clear API separation

Each layer will provide its own API stack

• Components are easier to reuse

Nuxeo EP 5.3 37 General Overview

Because the service and storage layers are not bound to a GUI, they are more generic and then more reusable

Thanks to this separation in component families you can easily extract from Nuxeo EP the components you need for your application.

If you need to include Document storage facilities into your application you can just use Nuxeo EP Core: It will offer you all the needed features to store, version and retrieve documents (or any structured but flexible dataset). If you also need process management and workflow you can also use Nuxeo EP Workflow service. And finally, if you want to have a Web application to browse and manage your data, you can reuse the Nuxeo EP Web layer.

4.1.2.2. Deployment services

The targeted platform does not provide the same mechanism to handle all the deployment tasks: • Packaging (Java EE vs OSGi)

• Dependency management

• Extension management

Because of these differences, Nuxeo EP provides a unified deployment service that hides the specificity of the target platform. This is also a way to add a pluggable component deployment system to some platforms that don't handle this (like Java EE).

This is one of the motivating factors for the Nuxeo Runtime that will be briefly introduced later in this document.

4.1.2.3. Extensible component model

In Nuxeo EP, an ECM application is seen as an assembly of components.

This assembly will include: • Existing generic Nuxeo EP Components

• Extensions or configurations contributing to generic Nuxeo EP components

• Specific components and configuration

Inside Nuxeo EP each feature is implemented by one or several reusable components and services. A feature may be implemented completely at storage level, or may require a dedicated service and a dedicated GUI.

Nuxeo EP Web application is a default distribution of a set of ECM components. This can be used "as is" or can be the base for making a business ECM application. • If you need to remove a feature

Just remove the component or deploy a configuration for disabling it.

• If you need to change the default behavior of one component

You can deploy a new configuration for the component .

• Declare a new Schema or define a document type

• Configure the versioning policy

• Deploy new workflow

Nuxeo EP 5.3 38 General Overview

• ...

This configuration may use an extension point to contribute to the new behavior (see Section 4.3.2, “Extensible component model”, Section 4.3.2.2, “Extension points” and the chapter on extension points in the Learning Nuxeo EP5 Guide. ) .

• Contribute a new security policy

• Contribute a new event handler

• Deploy a new View on a document

• ...

• If you need to add a completely new feature you can make your own component.

First check that there is no generic Nuxeo EP component available that could help you in your task (all components are not deployed in the default webapp).

4.1.2.4. Use of innovative Java EE technology

Here is a quick list of the Java technology we use inside Nuxeo EP platform: • Java 5

• Java EE 5: JSF and EJB3

• OSGi component model

• A lot a innovative open source projects

• JBoss Seam, Trinidad and Ajax4JSF on the web layer

• jBPM for the default workflow engine implementation

• Lucene for the default search engine implementation

• Jackrabbit JSR-170 repository for the default storage back end implementation

• JenaRDF for the relation framework

• ...

4.2. Nuxeo 5 Architecture Overview

The figure below shows a high level overview of the Nuxeo 5 Architecture that will be discussed in the sections below. The sections that follow will discuss: i. The Nuxeo Runtime (Section 4.3, “Nuxeo Runtime: the Nuxeo EP component model”)

ii. The Nuxeo Core Layer (Section 4.5, “Core Layer overview”)

iii.The Nuxeo Service/Platform Layer (Section 4.6, “Service Layer overview”)

iv. The Web Presentation Layer ( Section 4.7, “Web presentation layer overview”) - shown in the figure as either a web interface or rich client interface implementation

Nuxeo EP 5.3 39 General Overview

4.3. Nuxeo Runtime: the Nuxeo EP component model

4.3.1. The motivations for the runtime layer

Building the Nuxeo Runtime was one of the first tasks we started. This is one of the main infrastructure components of the Nuxeo EP architecture.

This section will give you a quick overview of the Nuxeo Runtime. A more detailed technical presentation can be found in Section 29.1, “Overview” of this book.

4.3.1.1. Host platform transparency

Because most Nuxeo EP components are shared by Nuxeo RCP (OSGI/RCP) and Nuxeo EP (Java EE), an abstraction layer is required so the components can transparently use the components services independently from the underlying infrastructure.

Nuxeo Runtime provides an abstraction layer on top of the target host platform. Depending on the target host platform, this Runtime layer may be very thin.

Nuxeo Runtime already supports Equinox (Eclipse RCP OSGi layer) and JBoss 4.x (JMX). The port of Nuxeo Runtime to other Java EE application servers is in progress, we already have a part of Nuxeo EP components that can be deployed on top of SUN Glassfish application server. Technically speaking, the port of Nuxeo Runtime could be done on any JEE5 compliant platform and will be almost straightforward for any platform that supports natively the OSGi component model.

4.3.1.2. Overcome Java EE model limitations

Java EE is a great standard, but it was not designed for a component based framework: it is not modular at all.

Nuxeo EP 5.3 40 General Overview

• Java EE deployment model limitations

• Most Java EE deployment descriptors are monolithic

For example, the web.xml descriptor is a unique XML file. If you want to deploy an additional component that needs to declare a new Java module you are stuck. You have to make one version of the web.xml for your custom configuration. For the Nuxeo EP platform, this constraint is not possible:

• Components don't know each other

Because there are a lot of optional components, we can't have a fixed configuration that fits all.

• We can make a version of the web.xml for each possible distribution

There are too many optional components to build one static web.xml for each possible combination.

This problem with the web.xml is of course also true for a lot of standard descriptors (application.xml, faces-config.xml, persistence.xml, ejb-jar.xml ....)

• One archive for one web application

We have here the exact same problem as with the web.xml. additional components can contribute new web pages, new web components ... We can have a monolithic web archive.

• No dependency declaration

Inside Java EE there is no standard way to declare the dependency between components.

Because Nuxeo EP is extensible and has a plugin model, we need that feature. A contribution is dependent on the component it contributes to:

• Contribution is only activated if/when the target component is activated

• The contribution must be deployed after the target component as it may override some configuration

• Java EE component model limitations

• Unable to deploy a new component without rebuilding the whole package

If you take a .ear archive and want to add a new component, you have to rebuild a new ear.

• No support for versioned components

Nuxeo Runtime provides an extensible component model that supports all these features. It also handles the deployment of these components on the target host platform.

4.3.2. Extensible component model

Nuxeo Runtime provides the component model for the platform.

This component model is heavily based on OSGi and provides the following features: • Platform diagnostic component model

Can be deployed on POJO and Java EE platforms

• Supports dependencies management

Components explicitly declare their requirements and are deployed and activated by respecting the inferred dependency chain.

• Includes a plugin model

Nuxeo EP 5.3 41 General Overview

To let you easily configure and contribute to deployed components

• A POJO test environment

Nuxeo Runtime components can be unit tested using JUnit without the need of a specific container.

4.3.2.1. The OSGi component model

OSGi (Open Services Gateway initiative) is a great standard for components based Java architecture.

OSGi provides out of the box the following features: • Dependencies declaration and management

A component gets activated only when the needed requirements are fulfilled

• Modular deployment system

• Manage bundles

• Manage fragments (sub parts of a master bundle)

• an OSGi bundle can define one or several services

• A system to identify and lookup a component

For Nuxeo EP, the OSGi standard provides a lot of the needed features. This is the reason why Nuxeo Runtime is based on OSGi. In fact Nuxeo Runtime component model is a subset of the OSGi specification.

To ensure platform transparency, Nuxeo Runtime provides adapters for each target platform to help it support OSGi components. • This adapter layer is very thin on Equinox (Eclipse RCP) since the underlying platform is already OSGi compliant.

• This adapter may be more complex for platforms that are not aware of OSGi (JBoss 4.x or Glassfish)

In this case, the runtime adapter will handle all OSGi logic and deploy the components as native platform components. For example, on JBoss 4.x, Runtime components are deployed as JMX MBeans.

4.3.2.2. Extension points

OSGi does not define a plugin model, but the Eclipse implementation (Equinox) does provide an extension point system.

Because we found many benefits in the Eclipse Extension Point system, Nuxeo Runtime also includes an Extension Point system. In other words, the underlying mechanism which allows extension points to be implemented in Nuxeo EP, has been built into the Nuxeo EP runtime and core.

An extension point is a way to declare that your component can be customized from the outside: • Contribute configuration

Activate or deactivate a component. Define resources for a given service.

• Contribute code and behavior

Extension points also give you the possibility to register plugins

Nuxeo EP 5.3 42 General Overview

Basically every Nuxeo Component can: • declare its dependencies

The component will also be activated after all needed components have been activated

• declare exposed extension points

Each component can define extension points that other components can use to contribute configuration or code.

• declare contribution to other components

Extension points and contributions to extension points are defined using a XML descriptor that has to be referenced in the MANIFEST.MF. For a more detailed understanding of extension points in Nuxeo EP, we recommend reading the Learning Nuxeo EP5 guide. 4.3.2.2.1. Some examples of extension point usage

Inside Nuxeo 5, extension points are used each time a behavior or a component needs to be configurable or pluggable.

Here are some examples of extension points used inside the Nuxeo 5 platform. • Schemas and document types

Inside Nuxeo 5 a document structure is defined by a set of XSD schemas. Schemas and Document Types are defined using an extension point.

• Storage repository

Nuxeo core stores documents according to their type but independently of the low level storage back-end. The default back-end is Jackrabbit JCR implementation. Nuxeo Core exposes an extension point to define the storage back-end. We are working on another repository implementation that will be purely SQL based.

• Security Management

Nuxeo include a security manager that checks access rights on each single operation. The extension point system allow to have different implementation of the security manager depending on the project requirements:

• Enforce data integrity: store security descriptors directly inside the document

• Performance: store security descriptors in an externalized index

• Corporate security policy: implement a specific security manager that will enforce business rules

• Event handlers

Nuxeo platform lets you define custom Event handler for a very large variety of events related to content or processes. The event handler extension mechanism gives a powerful way to add new behavior to an existing application

• You can modify the behavior of the application without changing its code

• The development model is easy because you have a very simple Interface to implement and you can use Nuxeo Core API to manipulate the data

• Event handlers can be synchronous or asynchronous

Nuxeo 5 itself uses the Event Handler system for a lot of generic and configurable services

Nuxeo EP 5.3 43 General Overview

• Automatic versioning: create a new version when a document is modified according to business rules

• Meta-data automatic update: update contributor lists, last modification date ...

• Meta-data extraction / synchronization: extract Meta-Data from MS-Office file, Picture ....

4.3.2.2.2. Nuxeo 5 Platform development model

Nuxeo 5 development model is heavily based on the usage of extension points. When a project requires specific features we try as much of possible to include it as an extension of the existing framework rather than writing separated specific component. This means make existing services more generic and more configurable and implement the project specific needs as a configuration or a plugin of a generic component using Extension Points.

4.3.3. Flexible deployment system

Nuxeo Runtime also provides deployment services to manage how components are deployed and contribute to each other • Dependencies management

The dependencies are declared in the MANIFEST.MF and can also be defined in XML descriptors that hold contributions.

The Nuxeo Runtime orders the component deployment in order to be sure the dependencies are respected. Components that have unresolved dependencies are simply not deployed

• Extension point contributions

XML descriptors are referenced in the MANIFEST.MF. These descriptors make contributions to existing extension points or declare new extension points.

• Each component has its own deployment-fragment

The deployment fragment defines

• Contribution to configuration files

For example contribute a navigation rule to faces-config.xml or a module declaration to web.xml.

Nuxeo Runtime lets you declare template files (like web.xml, persistence.xml) and lets other components contribute to these files.

• Installation instructions

Some resources contributions (like i18n files or web pages) need more complex installation instructions because they need archives and file manipulations. Nuxeo Runtime provide basic commands to define how your components should be deployed

Here is a simple example of a deployment-fragment.

${bundle.fileName} dueDateValidator org.nuxeo.ecm.platform.workflow.web.ui.jsf.DueDateValidator nuxeo.war/**

Nuxeo EP 5.3 44 General Overview

OSGI-INF/l10n/**

4.4. Nuxeo EP layered architecture

4.4.1. Layers in Nuxeo EP

Nuxeo EP components are separated in 3 main layers: Core / Service / UI

From the logical point of view each layer is a group of components that provide the same nature of service: • Storage oriented services: Nuxeo Core

Nuxeo core provides all the storage services for managing documents

• Repository service

• Versioning service

• Security service

• Lifecycle service

• Records storage (directories)

• ...

• Content and process oriented services: Nuxeo Platform

Nuxeo provides a stack of generic services that handle documents and provide content and process management features. Depending on the project requirement only a part of the existing services can be deployed.

Typical Nuxeo EP platform services are:

• Workflow management service

• Relation management service

• Archive management service

• Notification service

• ...

• Presentation service: UI Layer

The UI layer is responsible for providing presentation services like

Nuxeo EP 5.3 45 General Overview

• Displaying a view of a document

• Displaying available actions according to context

• Managing page flow on a process driven operation

These services can be very generic (like the action manager) but can also be directly tied to a type of client (like the View generation can be bound to JSF/facelets for the web implementation)

The layer organization can also be seen as a deployment strategy

Thanks to the Nuxeo Runtime remoting features it is very easy to split the components on several JVMs. But splitting some services can have a very bad effect on the global system performance.

Because of this, all the storage oriented services are inside the core. All components that have extensive usage of the repository and need multiple synchronous interaction with it are located in the core. This is especially true for all synchronous event handlers.

The services layer can itself be split in multiple deployment units on multiple JVMs.

On the UI side all the services are logically deployed inside the same JVM. At least each JVM must have the minimum set of services to handle user interaction for the given application.

The components are also grouped by layers according to their dependencies.

Core Modules can depend on Core Internal API.

Generic ECM services can depend on Core external API and can depend on external optional library (like jBPM, Jena, OpenOffice.org ...).

UI services can rely on a client side API (like Servlet API) and share a common state associated to the user session.

Layers are also organized according to deployment target.

The Core layer is a POJO Layer with an optional EJB facade. The core can be embedded in a client application.

The services are mostly implemented as POJO services so that they can be used as an embedded library. But some of them can depend on typical Application Server infrastructure (like JMS or EJB).

Inside the UI Layer most services are dedicated to a target platform: web (JSF/Seam), Eclipse RCP or other.

Because the layer organization has several constraints, the implementation of a unique feature is spread across several layers.

Typically a lot of these "transverse services" are split into several sub-components in each layer in order to comply with deployment constraints and also to provide better reusability. For example, the Audit service is made of 3 main parts which are split across 3 layers: • Core Event <=> JMS bridge (Core Layer)

Forwards core events to JMS Bridge according to configuration.

• JMS Listener and JPA Logger (Service Layer)

Message driven bean that writes logs in DB via JPA.

• Audit View (UI Layer)

Nuxeo EP 5.3 46 General Overview

Generates HTML fragment that displays all events that occurred on a document.

4.4.2. API and Packaging impacts

The layer organization can also be seen in the API.

4.4.2.1. Core API

Most of the components forming the core are exposed via the DocumentManager / CoreSession interface. The interfaces and dependencies needed to access the Core services are packaged in an API package: even if there are several Core components, you have only one dependency and API package.

The idea is that for accessing the core, you will only need to use the DocumentManager to manipulate DocumentModels (the document object artifact). Some core services can be directly accessed via the DocumentModel (like the life cycle or security data).

4.4.2.2. Service Stack API

Each service exposes its own API and then has its own API package. Service related data (like process data, relation data) are not directly hosted by the DocumentModel object but can be associated to it via adapters and facets.

4.4.2.3. UI API

The web layer can be very specific to the target application. Nuxeo EP provides a default web application and a set of base classes, utility classes and pluggable services to handle web navigation inside the content repository.

4.4.2.4. Packaging

Most features are made of several Java projects and generate several Maven 2 artifacts.

Nuxeo packaging and deployment system (Nuxeo Runtime, Platform API, Maven ...) leverage this separation to help you distributing the needed deployment unit according to your target physical platform.

4.5. Core Layer overview

Nuxeo EP 5.3 47 General Overview

4.5.1. Features of Nuxeo Core

Nuxeo core provides all the storage services for managing documents.

• Schema service

Lets you register XSD schemas and document types based on schemas.

• Repository service

Lets you define one or more repository for storing your documents.

• Versioning service

Nuxeo EP 5.3 48 General Overview

Lets you configure how to store versions.

• Security service

Manages data level security checks

• Lifecycle service

Manages life cycle state of each document

4.5.2. Nuxeo Core main modules

4.5.2.1. Nuxeo Repository Service

The repository service lets you define new document repositories. Defining separate repositories for your documents is pretty much like defining separate Databases for your records.

Because Nuxeo Core defines an SPI on repository, you can configure how you want the repository to be implemented. For now, the default implementation uses JSR-170 (Java Content Repository) reference implementation: Apache Jack Rabbit. In the future, we may provide other implementations of the Repository SPI (like native SQL DB or Object Oriented DB).

Even if for now there is only one Repository implementation available, using JCR implementation, you can configure how your data will be persisted: filesystem, xml or SQL Database. Please see "How to"s about repository configuration (Chapter 44, RDBMS Storage and Database Configuration).

When defining a new repository, you can configure: • The name.

• The configuration file

For JCR, it lets you define persistence manager.

• The security manager

Defines how security descriptors are stored in the repository (for now: org.nuxeo.ecm.core.repository.jcr.JCRSecurityManager)

• The repository factory

Defines how the repository is created (for now: org.nuxeo.ecm.core.repository.jcr.JCRRepositoryFactory)

4.5.3. Schemas and document types

The repository enforces data integrity and consistency based on Document types definition.

Each document type is defined by: • A name.

• An optional super document type (inheritance)

• A list of XSD schemas

Defines storage structure

Nuxeo EP 5.3 49 General Overview

• A list of facets

Simple markers used to define document behavior.

Here is a simple DocumentType declaration:

The core document types

For further explanation on Schemas and Document types, please see Chapter 5, Schemas and Documents.

4.5.4. The life cycle associated with documents

Inside the Nuxeo repository each document may be associated with a life-cycle. The life-cycle defines the states a document may have and the possible transitions between these states. Here we are not talking about workflow or process, rather we are just defining the possible states of a document inside the system.

The Nuxeo Core contains a LifeCycleManager service that exposes several extension points: • one for contribution to the Life-Cycle management engine

(the default one is called JCRLifeCycleManager and stores life-cycle related information directly inside the JSR 170 repository)

• one for contributing life-cycle definition

This includes states and transitions. On 5.2, since 5.2.0, it is possible to define additional initial states to the default state, by adding a keyword to the state definition, for instance: . The desired initial state can be passed in the document model context data used for creation: document.putContextData("initialLifecycleState", "approved").

• one for binding life-cycle to document-types

Here is an example

Approve the content Content becomes obsolete Move document to trash (temporary delete) Recover the document from trash Recover the document from trash approve obsolete delete delete backToProject

Nuxeo EP 5.3 50 General Overview

delete backToProject undelete

Life-Cycle service is detailed later in this document (Section 30.4.5, “Life Cycle” and Section 30.5.2, “LifeCycle Managers”).

4.5.5. Security model

Note: You may also want to read the chapter on "Access Control and Security" in the Learning Nuxeo EP5 Guide.

Inside the Nuxeo Repository security is always checked when accessing a document.

The Nuxeo security model includes : • Permissions

(Read, Write, AddChildren, ...).

Permissions management is hierarchical (there are groups of permissions)

• ACE: Access Control Entry

An ACE grants or denies a permission to a user or a group of users.

• ACL: Access Control List

An ACL is a list of ACEs.

• ACP: Access Control Policy

An ACP is a stack of ACLs. We use ACP because security can be bound to multiples rules: there can be a static ACL, an ACL that is driven by the workflow, and another one that is driven by business rules.

Separating ACLs allows us to easily reset the ACP when a process or a rules does not apply any more.

Inside the repository each single document can have an ACP. By default security descriptors are inherited from their parent, but inheritance can be blocked when needed.

The security engine also lets you contribute custom policy services so that security management can include business rules.

The security model and policy service are described in detail later in this document.

4.5.6. Core events system

When an event occurs inside the repository (document creation, document modification, etc...), an event is sent to the event service that dispatches the notification to its listeners. Listeners can perform any number of actions when receiving an event, which may include modifying the document on the fly.

Nuxeo EP 5.3 51 General Overview

As an example, part of the dublincore management logic is implemented as a CoreEvent listener: whenever a document is created or modified, the "creation date", "modification date", "author" and "contributors" fields are automatically updated by a CoreEvent Listener.

The Core Events system is explained in more detail later in this document (see Chapter 32, Nuxeo Event Service and Chapter 9, Event Listeners and Scheduling) and in the Learning Nuxeo EP5 guide.

4.5.7. Query system

The Repository supports a Query API to extract Documents using SQL like queries.

NXQL (the associated Query Language) is presented later in this document (see Example 11.2, “Sample NXQL queries”).

4.5.8. Versioning system

The documents in the repository can be versioned.

Nuxeo Core provides: • A pluggable version storage manager

This lets you define how versions are stored and what operations can be done on versions

• A pluggable versioning policy

This lets you define rules and logic that drive when new versions must be created and how version numbers are incremented.

The versioning system is explained in details later in this document (see Chapter 16, Document Versioning).

4.5.9. Repository and SPI Model

Nuxeo Core exposes a repository API on top of Jackrabbit JSR170 repository.

Nuxeo repository is implemented using an SPI and extension point model: this basically means that a non JCR based repository plugin can be contributed. In fact, we have already started a native SQL repository implementation (that is not yet finished because we have no direct requirement for such a repository).

Nuxeo core can server several repository: it provides a extension point to declare an additional repository: this means a single web application can use several document repositories.

4.5.10. DocumentModel

Inside Nuxeo EP and especially inside the Core API the main data object is a Document.

Inside Nuxeo Core API, the object artifact used to represent a Document is called a DocumentModel.

The DocumentModel artifact encapsulates several useful features: • Data Access over the network

the DocumentModel encapsulates all access to a Document's internal fields, and the DocumentModel can be sent over the network

• DocumentModel supports lazy loading

When fetched from the Core, a DocumentModel does not carry all document related information. Some data (called prefetch data) are always present, other data will be loaded (locally or remotely) from the

Nuxeo EP 5.3 52 General Overview

core when needed.

This feature is very important to reduce network and disk I/O when manipulating a Document that contains a lot of big blob files (like video, music, images ...) .

• DocumentModel uses Core Streaming Service

For files above 1 MB the DocumentModel uses the Core Streaming service.

• DocumentModel carries the security descriptors

ACE/ACL/ACP are embedded inside the DocumentModel

• DocumentModels support an adapter service

In addition to the data oriented interface, a DocumentModel can be associated with one or more Adapters that will expose a business oriented interface.

• DocumentModels embed lifecycle service access

• DocumentModels can have facets

Facets are used to declare a behavior (Versionnable, HiddenInNavigation, Commentable...)

A DocumentModel can be located inside the repository using a DocumentRef. DocumentRef can be an IdRef (UUID in the case of the JCR Repository Implementation) or PathRef (absolute path).

DocumentModels also hold information about the Type of the Document and a set of flags to define some useful characteristics of the Document: • isFolder

Defines if the targeted document is a container

• isVersion

Defines if the targeted document is an historic version

• isProxy

Defines if the targeted document is a Proxy (see below)

4.5.11. Proxies

A Proxy is a DocumentModel that points to a another one: very much like a symbolic link between 2 files.

Proxies are used when the same document must be accessible from several locations (paths) in the repository. This is typically the case when doing publishing: the same document can be visible in several sections (note: 'section' here has a special meaning as defined in the Nuxeo User Guide). In order to avoid duplicating the data, we use proxies that point to same document.

A proxy can point to a checked out document (not yet associated to a version label) or to a versioned version (typical use-case of publishing).

The proxy does not store document data: all data access are forwarded to the source document. But the Proxy does holds: • its own security descriptors

• its own DocumentRef

Nuxeo EP 5.3 53 General Overview

4.5.12. Core API

TO DO

4.6. Service Layer overview

4.6.1. Role of services in Nuxeo EP architecture

The service layer is an ECM services stack on top of the Nuxeo Repository. In a sense, the Repository itself is very much like any service of this layer, it just plays a central role.

This service layer is used for : • adding new generic ECM services (Workflow, Relations, Audit ...)

• adding connectors to existing external services

• adding dedicated project-specific components when the requirements can not be integrated into a generic component

This service layer provides the API used by client applications (Webapp or RCP based applications) to do their work.

This means that in this layer, services don't care about UI, navigation or pageflows: they simply explore an API to achieve document oriented tasks.

4.6.2. Services implementation patterns

Nuxeo platform provides a lot of different services, but they all fellow the same implementation pattern. This basically means that once you understand how works one service, you almost know how they all work.

As with everything in the Nuxeo Platform the services use the Nuxeo Runtime component model.

A generic service will be composed of the following packages : • An API package (usually called nuxeo-platform-XXX-api)

Contains all interfaces and remotable objects.

This package is required to be able to call the service from the same JVM or from a remote JVM.

You can view these in your Nuxeo server installation directory if you are curious (/nuxeo/server/default/deploy/nuxeo.ear/system/ - assuming you have your server installed in /nuxeo).

• A POJO Runtime component (usually called nuxeo-platform-XXX-core)

The Runtime component will implement the service business logic (ie: implement the API) and also expose Extensions Points.

All the extensibility and pluggability is handled at runtime component level. This for example means that the API can be partially implemented via plugins.

• A EJB3 Facade (usually called nuxeo-platform-XXX-facade)

The facade exposes the same API as the POJO component.

The target of this facade is to:

• provide EJB3 remoting access to the API

Nuxeo EP 5.3 54 General Overview

• integrate the service into JEE managed environment (JTA and JAAS)

• leverage some additional features of the application server like JMS and Message Driven Bean

• provide state management via Stateful Session Beans when needed

Typically, the POJO module will be a Nuxeo Runtime Component that inherits from DefaultComponent, provides extension points and implements a Service Interface.

public class RelationService extends DefaultComponent implements RelationManager { ...}

The deployment descriptor associated with the component will register the component, declare it as service provider and it may also declare extension points

The facade will declare an EJB that implements the same service interface. In simple cases, the implementation simply delegates calls to the POJO component.

The facade package will also contain a contribution to the Runtime Service management to declare the service implementation.

Define the Relation bean as a platform service. %RelationManagerBean

Thanks to this declaration the POJO and the EJB Facade can now be used for providing the same interface based on a configuration of the framework and not on the client code.

This configuration is used when deploying Nuxeo components on several servers: platform configuration provides a way to define service groups and to bind them together on physical servers.

4.6.3. Platform API

Each service provides its own API composed of a main interface and of the other interfaces and types that can be accessed.

The API package is unique for a given service, and access to a remote EJB3 based service is the same as accessing the POJO service.

From the client point of view, accessing a service is very simple and independent from service location and implementation: this means a manual JNDI call is not required. Everything that is needed is encapsulated in the Framework.getService runtime API.

RelationManager rm = Framework.getService(RelationManager.class);

The framework.getService will return the interface of the required service:

Nuxeo EP 5.3 55 General Overview

• This can be the POJO service (ie: Runtime Component based Service)

• This can be the local interface of the EJB3 service (using call by ref in JBoss)

• This can be the remote interface of the EJB3 service (using full network marshalling)

The choice of the implementation to return is left to the Nuxeo Runtime that will take the decision based on the platform configuration.

The client can explicitly ask for the POJO service via the Framework.getLocalService() API: this is typically used in the EJB Facade to delegate calls to the POJO implementation.

4.6.4. Adapters

DocumentModel adapters are a way to adapt the DocumentModel interface (that is purely data oriented) to a more business logic oriented interface.

In the pure Service logic, adding a comment to a document would look like this:

CommentManager cm = Framework.getService(CommentManager.class); cm.createComment(doc,"my comment"); List comments = cm.getComments(doc);

DocumentModel adapters give the possibility to have a more object oriented API:

CommentableDoc cDoc = doc.getAdapter(CommentableDoc); cDoc.addComment("my comment"); List comments = cDoc.getComments();

The difference may seem small, but DocumentModel adapter can be very handy • to have cleaner and clearer code

• to handle caching at the DocumentModel level

• to implement behavior and logic associating a Document with a Service

DocumenModelAdapters are declared using an extension point that defines the interface provided by the adapter and the factory class. DocumentModelAdapters can be associated to a Facet of the DocumentModel.

4.6.5. Some examples of Nuxeo EP services

TO DO

4.7. Web presentation layer overview

4.7.1. Technology choices

4.7.1.1. Requirements

The requirements for the Nuxeo Web Framework are : • A Powerful templating system that supports composition

• A modern MVC model that provides Widgets, Validators and Controllers

Nuxeo EP 5.3 56 General Overview

• A standard framework

• A set of Widget libraries that allow reusing existing components

• Support for AJAX integration

4.7.1.2. The JSF/Facelets/Seam choice

Nuxeo Web Layer uses JSF (SUN RI 1.2) and Facelets as presentation layer: JSF is standard and very pluggable, Facelets is much more flexible and adapted to JSF than JSP.

NXThemes provides a flexible Theme and composition engine based on JSF and Facelets.

In the 5.1 version of the platform, Nuxeo Web Layer uses Apache Tomahawk and trinidad as a components library and AJAX4JSF for Ajax integration. In the 5.2 version we will move to Rich Faces.

Nuxeo Web Layer also uses Seam Web Framework to handle all the ActionListeners.

Using Seam provides : • Simplification and help with JSF usage

• A context management framework

• Dependency injection

• Remoting to access ActionsListeners from JavaScript

• A built-in event system

4.7.2. Componentized web application

4.7.2.1. Requirements

Nuxeo Web Layer comes on top of a set of pluggable services.

Because this stack of services is very modular, the web layer must also be modular.

This basically means that depending on the set of deployed services and on the configuration, the web framework must provide a way • to add, remove or customize views

for example, if you don't need relations, you may want to remove the relations tab that is available on document by default

• to add or remove an action button or link

the typical use case is removing actions that are bound to non-deployed services or to add new actions that are specific to your project

• to override an action listener

you may want to change how some actions are handled by just overriding Nuxeo defaults

• to add or customize forms

Adding fields or customizing forms used to display documents is very useful

Nuxeo EP 5.3 57 General Overview

In order to fullfill these requirements, the key points of Nuxeo Web Frame fulfill: • Context management to let components share some state

• Event system and dependency injection to let loosely coupled components collaborate

• A deployment system to let several components make one unique WebApp

• A set of pluggable services to configure the web application

4.7.2.2. Context management

Inside the web framework, each component will need to know at least • the current navigation context

This includes current document, current container, current Workspace, current Domain.

This information is necessary because most of the services will display a view on the current document, and can fetch some configuration from the content hierarchy.

• the current user

This includes not only identity and roles, but also its preferences and the set of documents they choose to work on

In some cases, this context information may be huge, and it's time consuming to recompute all this information for each request.

Inside Nuxeo Web Framework, Seam context management is used to store this data. Depending on the lifecycle of the data, Session, Conversation or Event context are used.

4.7.2.3. Loosely coupled component

At some point the components of the web framework need to interact with each other. But because components can be present or not depending on the deployment scenario, they can't call each other directly.

For that matter, the Nuxeo Web Framework uses a lot of Seam features: • Seam's context is used to share some state between the components

• Seam's event system is used to let components notify each other

• Seam's dependency injection and Factory system is used to let components pull some data from each other without having to know each other

In order to facilitate Nuxeo Services integration into the web framework, we use the Seam Unwrap pattern to wrap a Nuxeo Service into Seam Components that can be injected and manipulated as a standard Seam component.

4.7.2.4. Deployment

The Web Layer is composed of several components.

The main components are webapp-core (default webapp base) and ui-web (web framework). On top of these base components, dedicated web components are deployed for each specific service.

For example, the workflow-service has its own web components package, so do relation-service, audit-service, comment-service and so on.

Each package contains a set of views, actions, and ActionsListeners that are dedicated to one service and

Nuxeo EP 5.3 58 General Overview integrate this service into the base webapp.

Because JEE standards require the webapp to be monolithic (ie. it cannot be split up), we use the Nuxeo Runtime deployment service to assemble the target webapp at deployment time.

This deployment framework let you: override resources, contribute XML descriptors like web.xml from several components and manage deployment order.

4.7.2.5. Key web framework services

TO DO

Nuxeo EP 5.3 59 Chapter 5. Schemas and Documents

5.1. Introduction

This chapter presents the concepts of schemas and document types, which are used to define new documents in Nuxeo EP 5.

5.1.1. Concepts

In Nuxeo EP 5, a fundamental entity is the document. A file, a note, a vacation request, an expense report, but also a folder, a forum, can all be thought of as documents. Objects that contain documents, like a folder or a workspace, are also themselves documents.

Any given document has a document type. The document type is specified at creation time, and does not change during the lifetime of the document. When referring to the document type, a short string is often used, for instance “Note” or “Folder”.

A document type is the grouping of several schemas. A schema represents the names and structure (types) of a set of fields in a document. For instance, a commonly-used schema is the Dublin Core schema, which specifies a standard set of fields used for document metadata like the title, description, modification date, etc.

To create a new document type, we start by creating one ore more schemas that the document type will use.

The schema is defined in a .xsd file (which obeys the standard XML Schema syntax) and is registered by a contribution to a schema extension point.

The document type is registered through a contribution to another doctype extension point, and will specify which schemas it uses. We also register the document type as a high-level type used by the EJB and rendering layers. “Core” document types and “ECM” component types should not be confused. The former live in the core Nuxeo EP packages, the latter belong to the high level components. Apart from their definition, most of the uses of "document types" refer to the “ECM” kind.

5.2. Schemas

A schema describes the names and types of some fields. The name is a simple string, like "title", and the type describes what kind of information it stores, like a string, an integer or a date.

First, we create a schema in the resources/schemas/sample.xsd file:

This schema defines two things: • an XML namespace that will be associated with the schema,

• two elements and their type.

The two elements are sample1 and sample2. They are both of type xs:string, which is a standard type defined by the XML Schema specification.

This schema has to be referenced by a configuration file so that the system knows it has to be read. The configuration file will be placed in OSGI-INF/core-types-contrib.xml (the name is just a convention):

Nuxeo EP 5.3 60 Schemas and Documents

We name our schema sample, and the .xsd schema was placed under resources/ which means that at runtime, it will be available directly from the Jar, therefore we reference it through the path schemas/sample.xsd. The schema is registered through an extension point of the Nuxeo component org.nuxeo.ecm.core.schema.TypeService named schema. Our own extension component is given a name, org.nuxeo.project.sample.coreTypes, which is not very important as we only contribute to existing extension points and don't define new ones.

Finally, we tell the system that the OSGI-INF/core-types-contrib.xml file has to be read, by mentioning it in the Nuxeo-Component part of the META-INF/MANIFEST.MF file of our bundle:

Manifest-Version: 1.0 Bundle-ManifestVersion: 1 Bundle-Name: NXSample project Bundle-SymbolicName: org.nuxeo.project.sample;singleton:=true Bundle-Version: 1.0.0 Bundle-Vendor: Nuxeo Require-Bundle: org.nuxeo.runtime, org.nuxeo.ecm.core.api, org.nuxeo.ecm.core Provide-Package: org.nuxeo.project.sample Nuxeo-Component: OSGI-INF/core-types-contrib.xml

5.3. Core Document Types

By itself, the schemas is not very useful. We associate it with a new “core” document type that we will be creating. In the same OSGI-INF/core-types-contrib.xml as above, we add the following:

The document type is defined through a contribution to an other extension point, doctypes, of the same extension component as before, org.nuxeo.ecm.core.schema.TypeService. We specify that our document type, Sample, will be an extension of the standard system type Document, and that it will be composed of three schemas, two standard ones and our specific one.

The Dublin Core schema that we use already contains standard metadata fields, like a title, a description, the modification date, the document contributors, etc. Adding it to our document type ensures that a minimal level of functionality will be present.

5.4. ECM Document Types

After the “core” document type, we need to create the “ECM” document type. This is done through a contribution to another extension point, that we place in the OSGI-INF/ecm-types-contrib.xml, the basic structure of this file is:

...

Nuxeo EP 5.3 61 Schemas and Documents

As of this writing, the document type id has to be the same as the underlying core type; this restriction may be lifted in the future. The type element will contain all the information for this type, this is described below.

This extension file is added to META-INF/MANIFEST.MF so that it will be taken into account by the deployment mechanism:

Nuxeo-Component: OSGI-INF/core-types-contrib.xml, OSGI-INF/ecm-types-contrib.xml

Inside the type element, we provide various information, described below.

5.4.1. Label and Icon

/icons/file.gif

The label and icon are used by the user interface, for instance in the creation page when a list of possible types is displayed. The icon is also used whenever a list of document wants to associate an icon with each.

5.4.2. Default view

view_documents

The default view specifies the name of the Facelet to use for this document if nothing is specified. This corresponds to a file that lives in the webapp, in this case view_documents.xhtml is a standard view defined in the base Nuxeo bundle, that takes care of displaying available tabs, and the document body according to the currently selected type. Changing it is not advised unless extremely nonstandard rendering is needed.

5.4.3. Layout

5.4.3.1. Configuration

Here is the new layout configuration:

heading note

Layouts are defined in a given mode (default modes are "create", "edit" and "view") ; layouts in the "any" mode will be merged with layouts defined for specific modes.

The layout names refer to layouts defined on another extension point. Please see the layouts section for more information.

5.4.3.2. Deprecated configuration

Here is the old layout configuration that has been replaced by the above. If present, it is used instead of the new configuration for compatibility purposes.

Nuxeo EP 5.3 62 Schemas and Documents

This section defines a series of widgets, that describe what the standard layout of this document type will be. A layout is a series of widgets, which make the association between the field of a schema with a JSF component.

The layout is used by the standard Nuxeo modification and summary views, to automatically display the document according to the layout rules. Note that the layout system is still young and is subject to minor changes in the future. Here we define four widgets, displayed as simple input fields or as a text area.

5.4.4. Containment rules

Sample Sample

This contributes a rule to an already existing type, Folder. The subtypes element specifies which types can be created inside the type in which the element is embedded.

Here, we specify that our Sample type can be created in a Folder and a Workspace.

5.4.5. Hidden cases

The goal is to contribute a way to define hidden cases for the subtypes definition. A syntax like the following can be used:

Workspace File Note

If more than one hidden cases needs to be defined, then a syntax like the following can be used:

Workspace File Note

The hidden cases are stored in a list ([create, paste] for the above example), so if a check is needed for a hidden case, then the hidden cases list ought to be verified if contains that particular case.

5.4.6. Summary

The final OSGI-INF/ecm-types-contrib.xml looks like:

Nuxeo EP 5.3 63 Schemas and Documents

/icons/file.gif view_documents Sample Sample

Nuxeo EP 5.3 64 Part II. Platform Services

Nuxeo EP 5.3 65 Chapter 6. Exception Handling

6.1. Introduction

The ExceptionHandlingService handles the exceptions that bubbled outside of Nuxeo. It allows to define handlers to forward to an error page with adequate messages and logs.

It is composed of 3 extension points: the errorHandlers configures the handlers, the requestdump configures the way the request will be written to error log and listener allows to set a listener to the process so state can be restore in case of error.

This service is only available in Nuxeo 5.2

6.2. Extension Points

6.2.1. requestdump

The request dump extension point allows to contribute a RequestDumper class. It takes a request as parameter and output the string that will be written to error log. The default contribution is:

It writes the attributes of the request.

6.2.2. listener

The listener extension point allows to contribute a listener that will be called during the different phase of the exception handling. The default contribution does nothing (this is use by WebEngine):

This contribution is over written in the module nuxeo-platform-webapp-core with:

This listener restore the faces/seam context before to write the attributes (use by NuxeoEP).

6.2.3. errorhandlers

The errorhandlers extension point allows to configure the different handler. General attribute are: errorhandlers attributes

Nuxeo EP 5.3 66 Exception Handling

bundle The message bundle to use. The default bundle used in Nuxeo is messages.

loggerName The name of the logger to use. Default is nuxeo-error-log. If you change this value, you need to update your logging configuration.

defaultpage The page to which you will be forwarded if no page is defined in the handler configuration.

The attributes for each handler are: error A regular expression, if matched the Exception we are handling, this handler will be used. The last handler should use ".*" as a Regular Expression.

message The key, in the message bundle defined in the general attribute, of the message that will be output to the user.

page The error page we should forward to. If not defined we will forward to the default error page as defined in the general attribute.

code The status code set to the response. If none the default code will be set.

The default configuration is:

Nuxeo EP 5.3 67 Chapter 7. Actions, Views, Navigation URLs and JSF tags

7.1. Introduction

The User Interface framework uses different kinds of concepts to make the interface configurable in the same way that the application itself is.

Links and pages that appear on the site can be the result of a "static" template written in the XHTML language, but can also be the result of a configuration change, taken into account thanks to more "generic" XHTML pages.

The following chapters will explain how configuration and templating combine to achieve the UI of the site.

7.2. Actions

7.2.1. Concepts

In this chapter, an action will stand for any kind of command that can be triggered via user interface interaction. In other words, it will describe a link and other information that may be used to manage its display (the link label, an icon, security information for instance).

7.2.2. Manage actions

Custom actions can be contributed to the actions service, using its extension point. Their description is then available through this service to control where and how they will be displayed.

7.2.2.1. Register a new action

An action can be registered using the following example extension:

Example 7.1. Example of an action registration

USER_SERVICES

The above action will be used to display a "logout" link on the site. Here are its properties:

• id: string identifying the action. In the example, the action id is "logout".

• label: the action name that will be used when displaying the link. In the example, the label is "command.logout". This label is a message that will be translated at display.

• link: string representing the command the action will trigger. This string may represent a different action given the template that will display the action. In the example, a JSF command link will be used, so it represents an action method expression. The seam component called "loginLogoutAction" holds a method named "logout" that will perform the logout and return a string for navigation.

• category: a string useful to group actions that will be rendered in the same area of a page. An action can

Nuxeo EP 5.3 68 Actions, Views, Navigation URLs and JSF tags

define several categories. Here, the only category defined is "USER_SERVICES". It is designed to group all the actions that will be displayed on the right top corner of any page of the site.

Other properties can be used to define an action. They are listed here but you can have a look at the main actions contributions file for more examples: nuxeo-platform-webapp-core/srs/main/resources/OSGI-INF/actions-contrib.xml.

• filter-ids: id of a filter that will be used to control the action visibility. An action can have several filters: it is visible if all its filters grant the access.

• filter: a filter definition can be done directly within the action definition. It is a filter like others and can be referred by other actions.

• icon: the optional icon path for this action.

• confirm: an optional Javascript confirmation string that can be triggered when executing the command.

• order: an optional integer used to sort actions within the same category. This attribute may be deprecated in the future.

• enabled: boolean indicating whether the action is currently active. This can be used to hide existing actions when customizing the site behavior. Actions extension point provides merging features: you can change an existing action definition in your custom extension point provided you use the same identifier. Properties holding single values (label, link for instance) will be replaced using the new value. Properties holding multiple values (categories, filters) will be merged with existing values.

7.2.2.2. Manage category to display an action at the right place

Actions in the same category are supposed to be displayed in the same area of a page. Here are listed the main default categories if you want to add an action there:

• USER_SERVICES: used to display actions in the top right corner of every page. The link attribute should look like a JSF action command link. See the example above.

• VIEW_ACTION_LIST: used for tabs displayed on every document. As each tab is not displayed in a different page, but just includes a specific template content in the middle of the page, the link attribute has to be a template path. For instance:

VIEW_ACTION_LIST view VIEW_ACTION_LIST view_content

• SUBVIEW_UPPER_LIST: used to display actions just below a document tabs listing. As USER_SERVICES, these actions will be displayed using a command link, so the link attribute has to be an action method expression. For instance:

SUBVIEW_UPPER_LIST AddChildren SectionRoot

Nuxeo EP 5.3 69 Actions, Views, Navigation URLs and JSF tags

SUBVIEW_UPPER_LIST create

7.2.2.3. Manage filters to control an action visibility

An action visibility can be controlled using filters. An action filter is a set of rules that will apply - or not - given an action and a context.

Filters can be registered using their own extension point, or registered implicitly when defining them inside of an action definition:

Example 7.2. Example of a filter registration

ReadChildren Folderish Root

Example 7.3. Example of a filter registration inside an action registration

SUBVIEW_UPPER_LIST AddChildren SectionRoot

A filter can accept any number of rules. It will grant access to an action if, among its rules, no denying rule (grant=false) is found and at least one granting rule (grant=true) is found. A general rule to remember is that if you would like to add a filter to an action that already has one or more filters, it has to hold constraining rules: a granting filter will be ignored if another filter is already too constraining.

If no rule is set, the filter will grant access by default.

The default filter implementation uses filter rules with the following properties:

• grant: boolean indicating whether this is a granting rule or a denying rule.

• permission: permission like "Write" that will be checked on the context for the given user. A rule can hold several permissions: it applies if user holds at least one of them.

• facet: facet like "Folderish" that can be set on the document type (org.nuxeo.ecm.core.schema.types.Type) to describe the document type general behavior. A rule can hold several facets: it applies if current document in context has at least one of them.

• condition: EL expression that can be evaluated against the context. The Seam context is made available for conditions evaluation. A rule can hold several conditions: it applies if at least one of the conditions is verified.

• type: document type to check against current document in context. A rule can hold several types: it

Nuxeo EP 5.3 70 Actions, Views, Navigation URLs and JSF tags

applies if current document is one of them. The fake 'Server' type is used to check the server context.

• schema: document schema to check against current document in context. A rule can hold several schemas: it applies if current document has one of them.

• group: group like "members" to check against current user in context. A rule can hold several groups: it applies if current user is in one of them.

Filters do not support merging, so if you define a filter with an id that is already used in another contribution, only the first contribution will be taken into account.

7.2.2.4. Adapt templates to display an action

It is important to understand that an action does *not* define the way it will be rendered: This is left to pages, templates and other components displaying it. Most of the time, actions will be rendered as command links or command buttons.

For instance, actions using the USER_SERVICES category will be rendered as action links:

The nxu:methodResult tag is only used to retrieve the list of actions declared for the USER_SERVICES category. The nxh:commandLink is used instead of a simple h:commandLink so that it executes commands that where described as action expression methods.

Another use case is the document tabs: actions using the VIEW_ACTION_LIST category will be rendered as action links too, but actions are managed by a specific seam component that will hold the information about the selected tab. When clicking on an action, this selected tab will be changed and the link it points to will be displayed.

7.3. Views

7.3.1. UI Views

First of all, we have to make the difference between a view in a standard JSF way (navigation case view id, navigation case output) and views in Nuxeo 5 (document type view, creation view)

7.3.2. Manage views

7.3.2.1. Standard JSF navigation concepts

A standard JSF navigation rule can be defined in the OSGI-INF/deployment-fragment.xml files, inside the faces-config#NAVIGATION directive.

Example 7.4. Example of a navigation rule case definitions

create_document /create_document.xhtml

Nuxeo EP 5.3 71 Actions, Views, Navigation URLs and JSF tags

view_documents /view_documents.xhtml

7.3.2.2. Nuxeo 5 views

A certain Nuxeo document type, can have defined a default view (used to view/edit the document) and a create view (used to create the document). These views are specified in the OSGI-INF/ecm-types-contrib.xml file, as in the following example.

Example 7.5. Example of view definitions for a document type

/icons/workspace.gif /icons/workspace_open.gif view_documents create_workspace

The default view of a document is rendered as a list of tabs. As mentioned before, the document tabs are defined as actions in the OSGI-INF/actions-contrib file, having as category VIEW_ACTION_LIST. A tab can be added to a document default view as shown in the following example.

Example 7.6. Example of tab definition for a default view of a document type

VIEW_ACTION_LIST edit mutable_document

7.4. Navigation URLs

There are two services that help building GET URLs to restore a Nuxeo context. The default configuration handle restoring the current document, the view, current tab and current sub tab.

7.4.1. Document view codec service

The service handling document views allows registration of codecs. Codecs manage coding of a document view (holding a document reference, repository name as well as key-named string parameters) in to a URL, and decoding of this URL into a document view.

Example 7.7. Example of a document view codec registration

Nuxeo EP 5.3 72 Actions, Views, Navigation URLs and JSF tags

target="org.nuxeo.ecm.platform.url.service.DocumentViewCodecService" point="codecs">

In this example, the docid codec uses the document uid to resolve the context. Urls are of the form http://site/nuxeo/nxdoc/demo/docuid/view. The docpath codec uses the document path to resolve the context. Urls are of the form http://site/nuxeo/nxpath/demo/path/to/my/doc@view.

Additional parameters are coded/decoded as usual request parameters.

Note that when building a document view, the url service will require a view id. The other information (document location and parameters) are optional, as long as they're not required for your context to be initialized correctly.

7.4.2. URL policy service

The service handling URLs allows registration of patterns. These patterns help saving the document context and restoring it thanks to information provided by codecs. The URL service will iterate through its patterns, and use the first one that returns an answer (proving decoding was possible).

Example 7.8. Example of a url pattern registration

true true true true docid #{restHelper.initContextFromRestRequest} #{restHelper.documentView} #{restHelper.newDocumentView} #{webActions.currentTabId} #{webActions.currentSubTabId}

In this example, the "default" pattern uses the above "docid" codec. Its is set as the default URL policy, so that it's used by default when caller does not specify a pattern to use. It needs the base URL: the docid codec only handles the second part if the URL. It needs redirect filter: it will be used to provide the context information to store. It needs filter preprocessing: it will be used to provide the context information to restore. It's using the docid codec.

The action binding method handles restoring of the context in the Seam context. It takes a document view as parameter. It requires special attention: if you're using conversations (as Nuxeo does by default), you need to annotate this method with a "@Begin" tag so that it uses the conversation identifier passed as a parameter if it's still valid, or initiates a new conversation in other cases. The method also needs to make sure it initializes all the seam components it needs (documentManager for instance) if they have not be in intialized yet.

The additional document view bindings are used to pass document view information through requests. The document view binding maps to corresponding getters and setters. The new document view binding is used to redirect to build GET URL in case request is a POST: it won't have the information in the URL so it needs to rebuild it.

Nuxeo EP 5.3 73 Actions, Views, Navigation URLs and JSF tags

Other bindings handle additional request parameters. In this example, they're used to store and restore tab and sub tab information (getters and setters have to be defined accordingly).

7.4.3. Additional configuration

The URL patterns used need to be registered on the authentication service so that they're considered as valid urls. Valid urls will be stored in the request, so that if authentication is required, user is redirected to the url after login.

Example 7.9. Example of a start url pattern registration

nxdoc/

Just the start of the url is required in this configuration. Contributions are merged: it is not possible to remove an existing start pattern.

The URL patterns used also need to be handled by the default nuxeo authentication service so that login mechanism (even for anonymous) applies for them.

Example 7.10. Example authentication filter configuration

NuxeoAuthenticationFilter /nxdoc/* REQUEST FORWARD

This is a standard filter mapping configuration.

7.4.4. URL JSF tags

There are some JSF tags and functions helping you to define what kind of GET URL should be displayed on the interface.

Example 7.11. Example of nxd:restDocumentLink use

In this example, the tag will print a simple link, using the default pattern, and build the document view using given document model, using its default view.

Please refer to the tag library documentation available at http://doc.nuxeo.org/5.1/tlddoc/nxd/restDocumentLink.html for additional parameters: it's possible to set the

Nuxeo EP 5.3 74 Actions, Views, Navigation URLs and JSF tags tab, sub tab, and use a specific URL pattern.

Note that you can also use JSF functions to build the GET URL. This is what's done for file links: the function queries the URL policy service to build the URL.

Example 7.12. Example of a jsf function use

Example 7.13. fileUrl method code

public static String fileUrl(String patternName, DocumentModel doc, String blobPropertyName, String filename) { try { DocumentLocation docLoc = new DocumentLocationImpl(doc); Map params = new HashMap(); params.put(DocumentFileCodec.FILE_PROPERTY_PATH_KEY, blobPropertyName); params.put(DocumentFileCodec.FILENAME_KEY, filename); DocumentView docView = new DocumentViewImpl(docLoc, null, params); // generate url URLPolicyService service = Framework.getService(URLPolicyService.class); if (patternName == null) { patternName = service.getDefaultPatternName(); } return service.getUrlFromDocumentView(patternName, docView, BaseURL.getBaseURL()); } catch (Exception e) { log.error("Could not generate url for document file", e); } return null; }

Similar methods exist for more complex urls, when handling files in list for instance. Please refer to the list at http://doc.nuxeo.org/5.1/tlddoc/nxd/tld-summary.html.

7.5. Nuxeo Document Lists Manager

The Document List Manager provides a service to manage lists of Nuxeo documents.

These lists of documents can have properties such as:

• a name, defined by name attribute.

• a scope (session or conversation), defined by tag - it defines if the memory storage occurs in the Seam session context or in the Seam conversation context.

• a persistence (SQL directory or not present), defined by tag - the service persists only the list of the document references, not the real documents; the lists of document references is persisted in a SQL directory, which is generic and does not need any configuration.

The lists of documents can be invalidated when Seam events are raised. This is usefull, for example, for resetting CURRENT_SELECTION lists when the user change the current folder or when a new search is performed.

Documents lists can be defined like in the following example (OSGI-INF/documentslists-contrib.xml):

Nuxeo EP 5.3 75 Actions, Views, Navigation URLs and JSF tags

Example 7.14. Example of documents lists definition

CLIPBOARD /img/clipboard.gif workingList.clipboard false false folderishDocumentSelectionChanged searchPerformed false

7.6. Nuxeo File Manager

The File Manager provides a service which exposes a simple API in order to create a Nuxeo document model from a passed blob file. Also, this service exposes as extension point which can be used to define plugins.

When the File Manager service is called, it will detect the mime-type of the passed blob, and will try to find a plugin to hadle the creation of a Nuxeo document model based on the detected mime-type.

Typical usages:

• txt/html/xml files - a Note document is created.

• image files - a Picture document is created (if nuxeo-platform-imaging addon is deployed).

• folder - a Folder document is created.

• other files - a File document is created.

Pugins can be defined like in the following example (OSGI-INF/nxfilemanager-plugins-contrib.xml):

Example 7.15. Example of File Manager plugins definition

text/plain text/html application/xhtml+xml application/xml text/xml

As a client of the File Manager service can be used the browser plugins (for Firefox and Internet Explorer) which can be be downloaded through the links from the default Nuxeo 5 login page. These plugins enable the user to create Nuxeo documents just by dragging & dropping folders/files to the browser. The plugins use a restlet (HTTP API) to send files/folders to the Nuxeo 5 Platform. The restlets use the File Manager serivce in order to create a Nuxeo document from the passed file.

7.7. Nuxeo JSF tags

Nuxeo EP 5.3 76 Actions, Views, Navigation URLs and JSF tags

Please refer to the tag library documentation available at http://doc.nuxeo.org/5.1/tlddoc/.

Nuxeo EP 5.3 77 Chapter 8. Layouts

Let our artists go wild on imaginative page layouts.

-- Grant Morrison

8.1. Introduction

Layouts are used to generate pages rendering from an xml configuration.

In a document oriented perspective, layouts are mostly used to display a document metadata in different use cases: present a form to set its schemas fields when creating or editing the document, and present these fields values when simply displaying the document. A single layout definition can be used to address these use cases as it will be rendered for a given document and in a given mode.

In this chapter we will see how to define a layout, link it to a document type, and use it in XHTML pages.

8.1.1. Layouts

A layout is a group of widgets that specifies how widgets are assembled and displayed. It manages widget rows and has global control on the rendering of each of its widgets.

8.1.2. Widgets

It's all the same machine, right? The Pentagon, multinational corporations, the police! You do one little job, you build a widget in Saskatoon and the next thing you know it's two miles under the desert, the essential component of a death machine!

-- Holloway, Cube

A widget defines how one or several fields from a schema will be presented on a page. It can be displayed in several modes and holds additional information like for instance the field label. When it takes user entries, it can perform conversion and validation like usual JSF components.

8.1.3. Widget types

A widget definition includes the mention of its type. Widget types make the association between a widget definition and the jsf component tree that will be used to render it in a given mode.

8.1.4. Modes

The layout modes can be anything although some default modes are included in the application: create, edit, view, listing and search.

The widget modes are more restricted and widget types will usually only handle two modes: edit and view. The widget mode is computed from the layout mode following this rule: if the layout is in mode create, edit or search, the widget will be in edit mode. Otherwise the widget will be in view mode.

It is possible to override this behavior in the widget definition, and state that, for instance, whatever the layout mode, the widget will be in view mode so that it only displays read-only values. The pseudo-mode "hidden" can also be used in a widget definition to exclude this widget from the layout in a given mode.

The pseudo mode "any" is only used in layouts and widgets definitions to set up default values.

8.2. Manage layouts

Nuxeo EP 5.3 78 Layouts

Custom layouts can be contributed to the web layout service, using its extension point. The layout definition is then available through the service to control how it will be displayed in a given mode.

Some jsf tags have been added to the Nuxeo ECM layout tag library to make then easily available from an xhtml page.

8.2.1. Layout registration

Layouts are registered using a regular extension point on the Nuxeo ECM layout service. Here is a sample contribution.

Example 8.1. Sample layout contribution to the layout service.

title description true dc:title true true dc:description

8.2.2. Layout definition

The above layout definition is used to display the title and the description of a document. Here are its properties:

• name: string used as an identifier. In the example, the layout name is "heading".

• templates: list of templates to use for this layout global rendering. In the example, the layout template in any mode is the xhtml file at "/layouts/layout_default_template.xhtml". Please refer to section about custom layout templates for more information.

Nuxeo EP 5.3 79 Layouts

• rows: definition about what widgets will have to be displayed on this row. Each row can hold several widgets, and an empty widget tag can be used to control the alignment. The widget has to match a widget name given in this layout definition. In the example, two rows have been defined, the first one will hold the "title" widget, and the second one will hold the "description" widget.

• widget: a layout definition can hold any number of widget definitions. If the widget is not referenced in the rows definition, it will be ignored. Since 5.1.7 and 5.2.0, it will be searched in the global widget registry before being ignored. This new feature is a convenient way to share widget definitions between layouts. Please refer the widget definition section.

8.2.3. Widget definition

Two widget definitions are presented on the above example. Let's look into the "title" widget and present its properties:

• name: string used as an identifier in the layout context. In the example, the widget name is "title".

• type: the widget type that will manage the rendering of this widget. In this example, the widget type is "text". This widget type is a standard widget types, more information about widget types is available here.

• labels: list of labels to use for this widget in a given mode. If no label is defined in a specific mode, the label defined in the "any" mode will be taken as default. In the example, a single label is defined for any mode to the "label.dublicore.title" message. If no label is defined at all, a default label will be used following the convention: "label.widget.[layoutName].[widgetName]".

• translated: string representing a boolean value ("true" or "false") and defaulting to "false". When set as translated, the widget labels will be treated as messages and displayed translated. In the example, the "label.dublincore.title" message will be translated at rendering time. Default is true.

• fields: list of fields that will be managed by this widget. In the example, we handle the field "dc:title" where "dc" is the prefix for the "dublincore" schema. If the schema you would like to use does not have a prefix, use the schema name instead. Note that most of standard widget types only handle one field. Side note: when dealing with an attribute from the document that is not a metadata, you can use the property name as it will be resolved like a value expression of the form #{document.attribute}.

• properties: list of properties that will apply to the widget in a given mode. Properties listed in the "any" mode will be merged with properties for the specific mode. Depending on the widget type, these properties can be used to control what jsf component will be used and/or what attributes will be set on these components. In standard widget types, only one component is used given the mode, and properties will be set as attributes on the component. For instance, when using the "text" widget type, every property accepted by the "" tag can be set as properties on "edit" and "create" modes, and every property accepted by the "" tag can be set as properties. Properties can also be added in a given widget mode.

Additional properties can be set on a widget:

• helpLabels: list that follows the same pattern as labels, but used to set help labels.

• widgetModes: list of local modes used to override the local mode (from the layout).

• subWidgets: list of widget definitions, as the widget list, used to describe sub widgets use to help the configuration of some complex widget types.

Here is a more complex layout contribution that shows the syntax to use for these additional properties:

Example 8.2. Sample complex layout contribution to the layout service.

Nuxeo EP 5.3 80 Layouts

true dc:description dataInputText identifier description true uid:uid hidden true cssClass

8.2.4. Listing layout definition

Layouts can also be used to render table rows, as long as their mode (or their widgets mode) do not depend on the iteration variable, as the layout is built when building the JSF tree (too early in the JSF construction mechanism for most iteration variables).

For this usage, columns/column aliases have been defined because they are more intuitive when describing a row in the layout. The layout layout_listing_template.xhtml makes it possible to define new properties to take care of when rendering the table header or columns.

Nuxeo EP 5.3 81 Layouts

Example 8.3. Sample complex layout contribution to the layout service.

selected data.ref data data.ref data.type data.folder true data data.ref data.dc.description data.file.content data.file.filename file:content file true data.dc.modified #{nxu:basicDateAndTimeFormater()} true true true false iconColumn listing_selection_box_with_current_document false

Nuxeo EP 5.3 82 Layouts

iconColumn listing_icon_type true dc:title listing_title_link true dc:modified listing_modification_date

Here widgets have been defined globally, as well as their types. New widget types, or simply widget templates, can be made taking example on the existing ones, see http://hg.nuxeo.org/nuxeo/nuxeo-jsf/file/5.3/nuxeo-platform-webapp-base/src/main/resources/OSGI-INF/layouts-listing-contrib.xml.

More information about how to write a listing layout template can be read below.

8.2.5. EL expressions in layouts and widgets

Some variables are made available to the EL context when using layout or widget templates.

• Inside the layout context, the following global variables are available: value (and equivalent document) + levels and changing "value" context

• layoutValue: represents the value (evaluated) passed in a "nxl:layout" or "nxl:documentLayout" tag attributes.

• layoutMode: represents the mode (evaluated) passed in a "nxl:layout" or "nxl:documentLayout" tag attributes.

• value: represents the current value as manipulated by the tag: in a "nxl:layout" tag, it will represent the value resolved from the "value" tag attribute ; in a "nxl:widget" tag, it will represent the value resolved from the "value" tag attribute. This value will work with field information passed in the widget definition to resolve fields and subfields. The variable "document" is available as an alias, although it does not always represent a document model (as layouts can aplly to any kind of object).

• value_n: represents the current value as manipulated by the tag, as above, excepts it includes the widget level (value_0, value_1, etc...). This is useful when needing to use the value as defined in a parent widget, for instance.

• Inside a layout template, the variable "layout" is available, it make its possible to access the generated layout object.

• Inside a "nxl:layoutRow", or equivalent "nxl:layoutColumn" tag, the variables "layoutRow" and "layoutRowIndex" are available to access the generated layout row, and its index within the iteration over rows. The equivalent "layoutColumn" and "layoutColumnIndex" variables are also available.

• Inside a "nxl:layoutRowWidget", or equivalent "nxl:layoutColumn" widget, the variables "widget" and "widgetIndex" are available to access the generated current widget, and its index in the row or column. The variables added the level information are also available: widget_0, widget_1, ... and widgetIndex_0, widgetIndex_1... This is useful when needed to use the widget as defined in a higher level.

Nuxeo EP 5.3 83 Layouts

• Inside a widget template, some "field_n" variables are available: "field_0" represents the resolved first field value, "field_1" the second value, etc... Since 5.3.1, the variable "field" is available as an alias to "field_0". Since 5.3.2, the widget properties are also exposed for easier resolution of EL expressions: for instance, the variable "widgetProperty_onchange" represents the resolved property with name "onchange".

The complete reference is available at http://doc.nuxeo.org/current/tlddoc/nxl/tld-summary.html.

8.3. Document layouts

Layouts can be linked to a document type definition by specifying the layout names:

heading note

Layouts are defined in a given mode; layouts in the "any" mode will be used as default when no layouts are given in specific modes.

Since 5.2.GA, it is possible to merge layouts when redefining the document type, adding a property append="true":

newLayout

Since 5.3.1, a new mode "listing" can used for folderish documents. Their default content will use the given layouts to make it possible to switch between the different presentations.

Some default listing layouts have been defined, the one used by default when no layout is given in this mode is "document_listing". To remove the layouts defined by default on a document type, override it without listing any modes.

document_listing document_listing_compact_2_columns document_icon_2_columns

Layouts with a name that ends with "2_columns" will be displayed on two columns by default. The layout name will be used as a message key for the selector label.

8.4. Layout display

Layouts can be displayed thanks to a series a JSF tags that will query the web layout service to get the layout definition and build it for a given mode.

For instance, we can use the documentLayout tag to display the layouts of a document:

We can also display a specific layout for a document, even if it is not specified in the document type definition:

Nuxeo EP 5.3 84 Layouts

Warning

You can include a layout in a dataTable tag, but cannot make its mode depend on the iteration variable. If you need to do so, recommendation is to use nxu:repeat tag and handle all the

works by yourself.

Please refer to the tag library documentation available at http://doc.nuxeo.org/current/tlddoc/nxl/tld-summary.html.

8.5. Standard widget types

A series of widget types has been defined for the most generic uses cases.

Please refer to the tag library documentation available at http://doc.nuxeo.org/5.1/tlddoc/ for nuxeo jsf tags.

8.5.1. text

The text widget displays an input text in create or edit mode, with additional message tag for errors, and a regular text output in any other mode. Widgets using this type can provide properties accepted on a tag in create or edit mode, and properties accepted on a tag in other modes.

8.5.2. int

The int widget displays an input text in create or edit mode, with additional message tag for errors, and a regular text output in any other mode. It uses a number converter. Widgets using this type can provide properties accepted on a tag in create or edit mode, and properties accepted on a tag in other modes.

8.5.3. secret

The secret widget displays an input secret text in create or edit mode, with additional message tag for errors, and nothing in any other mode. Widgets using this type can provide properties accepted on a tag in create or edit mode.

8.5.4. textarea

The textarea widget displays a textarea in create or edit mode, with additional message tag for errors, and a regular text output in any other mode. Widgets using this type can provide properties accepted on a tag in create or edit mode, and properties accepted on a tag in other modes.

8.5.5. datetime

The datetime widget displays a calendar in create or edit mode, with additional message tag for errors, and a regular text output in any other mode. It uses a date time converter. Widgets using this type can provide properties accepted on a tag in create or edit mode, and properties accepted on a tag in other modes. The converter will also be given these properties.

Nuxeo EP 5.3 85 Layouts

8.5.6. template

The template widget displays a template content whatever the mode. Widgets using this type must provide the path to this template; this template can check the mode to adapt the rendering.

Information about how to write a template is given in the custom widget template section.

8.5.7. file

The file widget displays a file uploader/editor in create or edit mode, with additional message tag for errors, and a link to the file in other modes. Widgets using this type can provide properties accepted on a tag in create or edit mode, and properties accepted on a tag in other modes.

8.5.8. htmltext

The htmltext widget displays an html text editor in create or edit mode, with additional message tag for errors, and a regular text output in other modes (without escaping the text). Widgets using this type can provide properties accepted on a tag in create or edit mode, and properties accepted on a tag in other modes.

8.5.9. selectOneDirectory

The selectOneDirectory widget displays a selection of directory entries in create or edit mode, with additional message tag for errors, and the directory entry label in other modes. Widgets using this type can provide properties accepted on a tag in create or edit mode, and properties accepted on a tag in other modes.

8.5.10. selectManyDirectory

The selectManyDirectory widget displays a multi selection of directory entries in create or edit mode, with additional message tag for errors, and the directory entries labels in other modes. Widgets using this type can provide properties accepted on a tag in create or edit mode, and properties accepted on a tag in other modes.

8.5.11. list

The list widget displays an editable list of items in create or edit mode, with additional message tag for errors, and the same list of items in other modes. Items are defined using sub widgets configuration. This actually a template widget type whose template uses a tag in edit or create mode, and a table iterating over items in other modes.

8.5.12. checkbox

The checkbox widget displays a checkbox in create, edit and any other mode, with additional message tag for errors. Widgets using this type can provide properties accepted on a tag in create, edit mode, and other modes.

8.6. Custom templates

Some templating feature have been made available to make it easier to control the layouts and widgets rendering.

8.6.1. Custom layout template

Nuxeo EP 5.3 86 Layouts

A layout can define an xhtml template to be used in a given mode. Let's take a look at the default template structure.

Example 8.4. Default layout template

Nuxeo EP 5.3 87 Layouts

This template is intended to be unused in any mode, so the layout mode is checked to provide a different rendering in "edit" or "create" modes and other modes.

When this template is included in the page, several variables are made available:

• layout: the computed layout value ; its mode and number of columns can be checked on it.

• value or document: the document model (or whatever item used as value).

The layout system integration using facelets features requires that iterations are performed on the layout rows and widgets. The and trigger these iterations. Inside the layoutRow tag, two more variables are made available: layoutRow and layoutRowIndex. Inside the layoutRowWidget, two more variables are made available: widget and widgetIndex.

These variables can be used to control the layout rendering. For instance, the default template is the one applying the "required" style on widget labels, and translating these labels if the widget must be translated. It also makes sure widgets on the same rows are presented in the same table row.

8.6.2. Listing template

This layout intends to render columns within a table: each line will be filled thanks to a layout configuration. It is only used in view mode. Let's take a look at the default listing template structure.

Example 8.5. Listing layout template

Layout template applying to an item instance of SelectDataModel named "documents" Other needed parameters are: - provider: instance of a ResultProvider to handle sort - layoutListingStatus: iteration status, used to print table header matching widget label.

Nuxeo EP 5.3 88 Layouts

onclick="selectDataTablePage('#{documents.name}', '#{provider.name}', this.checked, '#{listName}')" title="#{messages['tooltip.content.select.all']}" />

As you can see, this layout make it possible to use the first defined widget in a given column to print a label, and maybe translate it. It also relies on properties defined in the layout or layout column properties to handle selectio, column style class, sorting on the provider,...

Any custom template can be defined following this example to handle additional properties to disxplay on the final table header and columns.

8.6.3. Custom widget template

The template widget type makes it possible to set a template to use as an include.

Let's have a look at a sample template used to present contributors to a document.

Example 8.6. Sample template for a widget

Nuxeo EP 5.3 89 Layouts


This widget presents the contributors of a document with specific links on each on these user identifier information.

Having a widget type just to perform this kind of rendering would be overkill, so using a widget with type "template" can be useful here.

When this template is included in the page, the widget variable is made available:

Some rules must be followed when writing xhtml to be included in templates:

• Use the widget id as identifier: the widget id is computed to be unique within the page, so it should be used instead of fixed id attributes so that another widget using the same template will not introduce duplicated ids in the jsf component tree.

• Use the variable with name following the field_n pattern to reference field values. For instance, binding a jsf component value attribute to #{field_0} means binding it to the first field definition.

8.6.4. Builtin templates to handle complex properties

8.6.4.1. List widget template

The standard widget type "list" is actually a widget of type "template" using a static template path: /widgets/list_widget_template.xhtml. If this default behavior does not suit your needs, you can simply copy this template, make your changes, and use a widget of type "template" with the new template path.

This template assumes that each element of the list will be displayed using subwidgets definitions.

For instance, to handle a list of String elements, you can use the definition:

dc:contributors

The empty field definition in the subwidget is used to specify that each element of the list is itself the element to display.

With nuxeo version <= 5.3.0, to handle a list of complex properties (each entry of the list is a map with keys 'name' and 'email' for instance), you can use the definition:

company:employees

Nuxeo EP 5.3 90 Layouts

/widgets/complex_widget_template.xhtml name email

With nuxeo version > 5.3.0, to handle a list of complex properties (each entry of the list is a map with keys 'name' and 'email' for instance), you can use the definition:

company:employees /widgets/complex_list_item_widget_template.xhtml name email

8.6.4.2. Complex widget template

A builtin template has been added to handle complex properties. It is available at /widgets/complex_widget_template.xhtml. It assumes that each element of the complex property will be displayed using subwidgets definitions.

To handle a complex property (the value is a map with keys 'name' and 'email' for instance, you can use the definition:

company:manager /widgets/complex_widget_template.xhtml

Nuxeo EP 5.3 91 Layouts

name email

8.6.4.3. Lists of lists

A builtin template has been added to handle sublists: the original "list" widget is equivalent to a widget of type "template" using the file "/widgets/list_widget_template.xhtml". To handle the sublist, this template needs to be changed. The file "list_subwidget_template.xhtml" is available for it since nuxeo version 5.2 GA.

To handle a sublist property, you can use take example on this definition:

company:employees /widgets/complex_list_item_widget_template.xhtml phoneNumbers /widgets/list_subwidget_template.xhtml

8.7. Custom widget types

Custom widget types can be added to the standard list thanks to another extension point on the web layout service.

Here is a sample widget type registration:

Example 8.7. Sample widget type contribution to the layout service.

Nuxeo EP 5.3 92 Layouts

point="widgettypes"> org.myproject.MyCustomWidgetTypeHandler bar

The custom widget type class must follow the org.nuxeo.ecm.platform.forms.layout.facelets.WidgetTypeHandler interface.

Additional properties can be added to the type registration so that the same class can be reused with a different behavior given the property value.

The widget type handler is used to generate facelet tag handlers dynamically taking into account the mode, and any other properties that can be found on a widget.

The best thing to do before writing a custom widget type handler is to go see how standard widget type handlers are implemented, as some helper methods can be reused to ease implementation of specific behaviors.

8.8. Generic layout usage

Layouts can be used with other kind of objects than documents.

The field definition has to match a document property for which setters and getters will be available, or the "value" property must be passed explicitely for the binding to happen. Depending on the widget, other kinds of bindings can be done.

Nuxeo EP 5.3 93 Chapter 9. Event Listeners and Scheduling

9.1. Introduction

Events and event listeners have been introduced at the Nuxeo core level to allow pluggable behaviors when managing documents (or any kinds of objects of the site).

Whenever an event happens (document creation, document modification, relation creation, etc...), an event is sent to the event service that dispatches the notification to its listeners. Listeners can perform whatever action when receiving an event.

9.2. Concepts

A core event has a source which is usually the document model currently being manipulated. It can also store the event identifier, that gives information about the kind of event that is happening, as well as the principal connected when performing the operation, an attached comment, the event category, etc..

Events sent to the event service have to follow the org.nuxeo.ecm.core.api.event.CoreEvent interface.

A core event listener has a name, an order, and may have a set of event identifiers it is supposed to react to. Its definition also contains the operations it has to execute when receiving an interesting event.

Event listeners have to follow the org.nuxeo.ecm.core.listener.EventListener interface.

Several event listeners exist by default in the nuxeo platform, for instance:

• DublincoreListener: it listens to document creation/modification events and sets some dublincore metadata accordingly (date of creation, date of last modification, document contributors...)

• DocUidGeneratorListener: it listens to document creation events and adds an identifier to the document if an uid pattern has been defined for this document type.

• DocVersioningListener: it listens to document versioning change events and changes the document version numbers accordingly.

9.3. Adding an event listener

Event listeners can be plugged using extension points. Here are some examples of event listeners registration.

Example 9.1. DublincoreListener registration sample

Example 9.2. UIDGenerator listener registration sample with event filtering

Nuxeo EP 5.3 94 Event Listeners and Scheduling

documentCreated

The only thing needed to add an event listener is to declare its name and its class. Sometimes the order in which listeners are called matters so an integer order can be set to control it. A filtering on event ids can be done when registering it too, though the notification method could handle it too.

For instance, the UIDgenerator service will only be notified when the event service receives a document creation event.

9.4. Upgrading an event listener

Since release of Nuxeo EP version 5.0 M3, events involving documents send the document model as source of the event. They used to send the document itself, which was wrong and has been changed in a compatible way.

Old school event listeners should still work ok for now, but should be migrated soon as the compatibility may introduce bugs and will be removed shortly.

To migrate your event listener, make it implement the empty interface org.nuxeo.ecm.core.listener.DocumentModelEventListener, and make it deal with a DocumentModel instead of a Document as event source.

If your event listener does not care about the source, or the event it deals with is not a document, you do not have to do anything.

9.5. Adding an event

To add an event, you have to create it and then notify listeners passing the even to the listener service. Here is a sample code on how to do it:

CoreEvent coreEvent = new CoreEventImpl(eventId, source, options, getPrincipal(), category, comment); CoreEventListenerService service = NXCore.getCoreEventListenerService(); if (service != null) { service.notifyEventListeners(coreEvent); } else { throw new ClientException("Can't get Event Listener Service"); }

9.6. From CoreEvents to JMS Messages

Events that are fired at the core level are forwarded to a JMS topic called NXPMessage.

This forwarding is done by a dedicated CoreEventListener (called JMSEventListener contributed by the nuxeo-platform-events-core bundle).

In order to be sure that when an JMS event is received the associated DocumentModel is available, all document oriented messages that may occur at core level are forwarded to the JMS topic when the session repository is saved (ie: when data is committed).

Nuxeo EP 5.3 95 Event Listeners and Scheduling

In some cases, depending on own the Core API is used, some messages can be duplicated within the same transaction (like modifying several times the same document), the JMSEventListener marks all duplicated messages before sending them to JMS, its JMS messages receiver to choose to process or not the duplicated messages.

During the forwarding on the JMS Topic, the coreEvents are converted to EventMessage. The main difference is that the EventMessage does not contains the DocumentData (ie: all schemas and fields are unloaded), this is done in order to avoid overloading JMS.

9.7. Adding a JMS message listener

The simplest way to add a JMS message listener is simply to define a Message Driven Bean that is bound to the NXPMessage Topic.

Here is a simple example a the definition of such a MDB :

@MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "topic/NXPMessages"), @ActivationConfigProperty(propertyName = "providerAdapterJNDI", propertyValue = "java:/NXCoreEventsProvider"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) @TransactionManagement(TransactionManagementType.CONTAINER) public class NXAuditMessageListener implements MessageListener { private static final Log log = LogFactory.getLog(NXAuditMessageListener.class); @TransactionAttribute(TransactionAttributeType.REQUIRED) public void onMessage(Message message) { try { final Serializable obj = ((ObjectMessage) message).getObject(); if (!(obj instanceof DocumentMessage)) { log.debug("Not a DocumentMessage instance embedded ignoring."); return; } DocumentMessage docMessage = (DocumentMessage) obj; String eventId = docMessage.getEventId(); log.debug("Received a message with eventId: " + eventId); ...

The DocumentMessage is a subclass of the DocumentModel.

An important point to remember is that the MDB is executed asynchronously in a dedicated thread: • there is no JAAS Session established: you can not access the repository without this

• the DocumentMessage is not bound to an existing CoreSession: you can not use the DocumenMessage to do lazy loading (ie: DocumentMessage.getProperty())

So, in order to extract some document oriented properties of the document associated to the event, you must: • Establish a JAAS Session

• get a connected DocumentModel using the DocumentRef provided by the DocumentMessage

Here is a code sample for this:

LoginContext lc; CoreSession session; String repositoryName = docMessage.getRepositoryName(); try { log.debug("trying to connect to ECM platform"); lc = Framework.login(); session = Framework.getService(RepositoryManager.class).getRepository(repositoryName).open(); DocumentModel connectedDoc = session.getDocument(docMessage.getRef()); ... } finally { if (session != null) CoreInstance.getInstance().close(session.getSessionId()) if (lc != null)

Nuxeo EP 5.3 96 Event Listeners and Scheduling

lc.logout(); }

9.8. Scheduling

XXX TODO: FG

Nuxeo EP 5.3 97 Chapter 10. User Notification Service

10.1. Introduction

The notification framework provides a way to notify the users regarding different events as they happen in the system.

10.2. Notification concept

A notification is an alert that is sent to some users when an event takes place in the system (e.g. a document is created or deleted, a document is modified or published, a comment was entered, etc.).

A notification is defined by following attributes: • name: must be unique

• channel: email, SMS, Jabber, etc.

• events: a series of events to which it responds

• template: is a file in which is stored the text that is sent to an user - it may be dynamic

In order to define a notification, one must declare all these attributes in a contribution file.

10.3. Notification channels

The channel is the communication channel used by the notification service to send alerts(notifications) to users.

In order to define a new channel (by default only email channel is used) the ChannelNotificator interface must be implemented.

It has 2 methods:

• isInterestedInNotification(Notification docMessage) usually checks if the channel is right.

• sendNotification(DocumentMessage docMessage) sends the actual notification. For now only email notification channel is implemented.

10.4. E-mail notifications

A notification must be defined in a xml file like the default notification-contrib.xml that is used by default.

Default defined notification may be disabled by setting enabled="false".

In order to define a new notification one must place a definition like this one in his contribution file :

As you may see above a notification must declare a list of events to which it reacts. In our case documentModified contentSubdocumentModified.

Nuxeo EP 5.3 98 User Notification Service

Also a notification must have a name that must be unique within the application. A label must also be specified for i18n.

The attribute enabled is used to enable / disable specific notifications.

The attribute autoSubscribed is set to true when we want that a notification is sent to all concerned users. In this case within the eventInfo map there must be loaded also the users that are concerned. For example if we want that some users (ex: administrators or workflow manager) to get a notification each time a task is assigned to them, we must use autoSubscribed="true" and put the usernames of all users in the eventInfo of the event under the key recipients.

The attribute availableIn is used in order to restrict the scope of a notification. For example if we want to define a notification that is triggered each time the document is modified, then it would not be used inside a section, because sections contain documents that cannot be modified, only published. So in order to hide this notification inside a section, we specify availableIn="workspace". The accepted values are workspace, section and all.

The template attribute specifies the name of a template that will be used for generating the body of the email(notification). This name is associated with a file using another extension point like this: