API Development Course
Copyright (c) 2007 by Alfresco and others.    Information in this document is subject to change without notice. No part of...
Contents   Introduction......................................................................................................
FirstJCRClient Walkthrough.......................................................................................51       ...
Custom Dialog Howto..............................................................................................123      ...
IntroductionIntroduction6 Alfresco Enterprise Edition Version 3.2
IntroductionWelcome    Welcome to Alfresco API development. This course has been designed to provide you with the    knowl...
Introduction                  • Content Transformers                  • Metadata ExtractorsDay 3          • Extending the ...
Getting StartedGetting Started                  API Development Course 9
Getting StartedAlfresco SDKIntroduction     The Alfresco SDK provides support for developers who wish to extend or customi...
Getting Started          For a description of the contents of the Alfresco SDK, see SDK Contents on page 20.Importing the ...
Getting Started              d.   Click OK         2. Importing the Alfresco SDK projects              a.   From the Eclip...
Getting Started           In order to run the samples or to develop your own extension modules, you must           import ...
Getting StartedAssociating Source Code and Javadocs with the Alfresco Libraries     Once the Alfresco SDK projects have be...
Getting Started4. Associating Javadocs   a.   In the Properties for alfresco-repository.jar dialog, select Javadoc Locatio...
Getting Started         5. Click OK, to close the Properties dialog.     Once the source code and Javadocs have been attac...
Getting Started#db.username=alfresco#db.password=alfresco## MySQL connection (This is default and requires mysql-connector...
Getting Started     The other embedded repository samples (SDK FirstJCRClient and SDK JCRSamples) can be     run in the sa...
Getting Started   modules can be developed and tested using unit tests and an embedded Alfresco repository. The   SDK Cust...
Getting StartedSDK ReferenceSDK Contents     bin         Supporting dlls, exes.     doc         Zipped Javadocs for all pr...
Getting StartedSDK CustomDialog  Sample project demonstrating how to develop and configure a custom Dialog for the Alfresc...
Getting StartedBest PracticesCoding StandardsCoding Standards - Formatting          • The core coding standards are the st...
Getting Started    Once the contents of the AMP file has been mapped into an Alfresco WAR using the Module    Management T...
Getting StartedAlfresco Repository ArchitectureOut of the Box     Out-of-the-box, Alfrescos simple installation procedure ...
Getting Started   components may be used in isolation or together to form the basis of many differing Content   Management...
Getting Started     The public interface point is the Alfresco Repository Foundation Services. Each service is     exposed...
Getting Started   encapsulated outside of the core Repository and plugged-in automatically. This means the core   Reposito...
Getting Started     Apart from the strong Object/Relational mapping that Hibernate provides, it also brings pluggable     ...
Getting Started   Once again, the Repository Foundation Services serve as the base. Both the JCR and Web   Services API ev...
Getting Started     CIFS protocol having brought on board the engineers who spent 7 years developing such a     capability...
Getting Started    public static final String PROTOCOL_WORKSPACE = "workspace";    public static final String PROTOCOL_AVM...
Getting Started     Namespace scoped Name Format {URI}localname or prefix:localName     Examples     {http://www.alfresco....
Developing against the Alfresco RepositoryDeveloping against the Alfresco Repository                                      ...
Developing against the Alfresco RepositorySpring FrameworkIntroduction     The Spring Framework is a full-stack Java/JEE a...
Developing against the Alfresco Repository               We retrieve bean1 from the Bean Factory using the getBean() metho...
Developing against the Alfresco Repository                   public void setList(List strings) { m_strings = strings; }   ...
Developing against the Alfresco Repository              public void setInt(int val) { m_intVal = val; }              publi...
Developing against the Alfresco Repository                   public abstract class Bean1                   {              ...
Developing against the Alfresco RepositoryApplication Context    To start using Spring you either instantiate a Spring Bea...
Developing against the Alfresco RepositoryFoundation Services APIIntroduction     The Foundation Services API is a set of ...
Developing against the Alfresco Repository2. Using the TransactionService to run the example in a user transaction   By de...
Developing against the Alfresco Repository             Before making any call to the repository through the public Foundat...
Developing against the Alfresco Repository         For clarity, not all of the available methods are shown. For a complete...
Developing against the Alfresco Repository                     For clarity, not all of the available methods are shown. Fo...
Developing against the Alfresco Repository     qname        QName of the property to set.     value        Value of the pr...
Developing against the Alfresco Repository                   The following example creates a new node of type cm:content, ...
Developing against the Alfresco Repositorythe getTransformer() and getImageTransformer() methods. The transformation canth...
Developing against the Alfresco Repository     Once completed, the newly created node may be viewed via the Web client.   ...
Developing against the Alfresco RepositoryFor clarity, not all of the available methods are shown. For a complete descript...
Developing against the Alfresco RepositoryJCR APIIntroduction     The JCR API (Java Content Repository) specifies a standa...
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
2140 api developer-student-guide
Upcoming SlideShare
Loading in...5
×

2140 api developer-student-guide

1,271

Published on

dsada

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,271
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
73
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

2140 api developer-student-guide

  1. 1. API Development Course
  2. 2. Copyright (c) 2007 by Alfresco and others. Information in this document is subject to change without notice. No part of this document may be reproduced or transmitted in any form or by any means, electronic or mechanical, for any purpose, without the express written permission of Alfresco. The trademarks, service marks, logos or other intellectual property rights of Alfresco and others used in this documentation (“Trademarks”) are the property of Alfresco and their respective owners. The furnishing of this document does not give you license to these patents, trademarks, copyrights or other intellectual property except as expressly provided in any written agreement from Alfresco. The United States export control laws and regulations, including the Export Administration Regulations of the U.S. Department of Commerce, and other applicable laws and regulations apply to this documentation which prohibit the export or re-export of content, products, services, and technology to certain countries and persons. You agree to comply with all export laws, regulations and restrictions of the United States and any foreign agency or authority and assume sole responsibility for any such unauthorized exportation. If you need technical support for this product, contact Customer Support by email at support@alfresco.com. If you have comments or suggestions about this documentation, contact us at documentation@alfresco.com. This edition applies to version 2.1 of the licensed program.2
  3. 3. Contents Introduction................................................................................................................................ 6 Welcome.............................................................................................................................. 7 How this course is delivered....................................................................................... 7 Course Schedule......................................................................................................... 7 How Prepared are You?..............................................................................................8 Topics not Covered..................................................................................................... 8 Introductions.................................................................................................................8 Getting Started...........................................................................................................................9 Alfresco SDK..................................................................................................................... 10 Introduction.................................................................................................................10 Downloading and Unpacking the Alfresco SDK........................................................ 10 Importing the Alfresco SDK projects into Eclipse......................................................11 Associating Source Code and Javadocs with the Alfresco Libraries......................... 14 SDK samples............................................................................................................. 16 SVN Repository......................................................................................................... 19 SDK Reference.......................................................................................................... 20 Best Practices....................................................................................................................22 Coding Standards...................................................................................................... 22 Alfresco Module Packages (AMP).............................................................................22 Alfresco Repository Architecture....................................................................................... 24 Out of the Box........................................................................................................... 24 Service & Component Architecture........................................................................... 25 Repository Foundation Services API.........................................................................27 Repository APIs......................................................................................................... 28 Repository Server Protocols...................................................................................... 29 Terminology................................................................................................................30 Developing against the Alfresco Repository........................................................................33 Spring Framework............................................................................................................. 34 Introduction.................................................................................................................34 Bean Factory..............................................................................................................34 Inversion of Control (IoC).......................................................................................... 35 Application Context.................................................................................................... 39 Foundation Services API................................................................................................... 40 Introduction.................................................................................................................40 Access to Repository Foundation Services...............................................................40 FirstFoundationClient walkthrough............................................................................ 40 Other Foundation Services........................................................................................ 48 JCR API............................................................................................................................. 50 Introduction.................................................................................................................50 JCR Compliance Levels............................................................................................ 50 JCR Repository Model...............................................................................................50 API Development Course 3
  4. 4. FirstJCRClient Walkthrough.......................................................................................51 JCR Transactions...................................................................................................... 53 Web Services API............................................................................................................. 55 Introduction.................................................................................................................55 Available Web Services.............................................................................................55 Access to Web Services in Java...............................................................................55 Web Services Data Types.........................................................................................56 Content Manipulation Language (CML).....................................................................56 FirstWebServiceClient Walkthrough.......................................................................... 57 Separating Concerns using AOP...................................................................................... 61 Public Services and AOP proxies............................................................................. 61 Security Enforcement.................................................................................................61 Transaction Management.......................................................................................... 64 Extending the Alfresco Repository....................................................................................... 69 Repository Policies............................................................................................................ 70 Introduction.................................................................................................................70 Available Policies....................................................................................................... 70 Policy Types...............................................................................................................71 Custom Aspect with Behaviour Howto...................................................................... 71 Repository Actions.............................................................................................................79 Introduction.................................................................................................................79 Repository Action Howto........................................................................................... 79 Repository Action with Parameters Howto................................................................ 85 Content Transformers........................................................................................................91 Introduction.................................................................................................................91 Content Transformer Howto...................................................................................... 91 ContentTransformerRegistry...................................................................................... 95 Further Reading......................................................................................................... 97 Metadata Extractors...........................................................................................................98 Introduction.................................................................................................................98 MetadataExtracterRegistry.........................................................................................98 Metadata Extractor Howto......................................................................................... 99 Further Reading....................................................................................................... 103 Extending the Alfresco Web Client..................................................................................... 105 JavaServer Faces............................................................................................................106 Introduction...............................................................................................................106 Login Page Walkthrough......................................................................................... 106 Actions Framework.......................................................................................................... 116 Introduction...............................................................................................................116 Update UI Action Walkthrough................................................................................ 116 Actions Framework Reference................................................................................ 120 Dialog Framework............................................................................................................123 Introduction...............................................................................................................1234 Alfresco Enterprise Edition Version 3.2
  5. 5. Custom Dialog Howto..............................................................................................123 Further Information.................................................................................................. 128 Dialog Framework Reference.................................................................................. 130 Wizard Framework...........................................................................................................132 Introduction...............................................................................................................132 Custom Wizard Howto.............................................................................................132 Further Reading....................................................................................................... 137 Wizard Framework Reference................................................................................. 139Packaging Extensions.......................................................................................................... 142 Alfresco Module Packages.............................................................................................. 143 Introduction...............................................................................................................143 Basic AMP Howto....................................................................................................143 Further Reading....................................................................................................... 149 Alfresco Module Package Reference...................................................................... 150 API Development Course 5
  6. 6. IntroductionIntroduction6 Alfresco Enterprise Edition Version 3.2
  7. 7. IntroductionWelcome Welcome to Alfresco API development. This course has been designed to provide you with the knowledge and skills necessary to develop against the Alfresco Repository APIs and to develop extensions for the Alfresco enterprise content management system.How this course is delivered This course is delivered in 17 modules, each module focusing on a specific subject. All modules include a combination of introductory materials, an outline of objectives followed by instructor- led discussions and walkthroughs. Each module will close with one or more exercises which will allow students to use and demonstrate what they have learned in each module.Course objectives At the conclusion of this course you should be comfortable with all the concepts and tasks required to competently: • Set up your own development environment and use the Alfresco SDK • Develop against the Alfresco APIs (Foundation Services, JCR, Web Services) • Develop extensions for the Alfresco Repository • Develop extensions for the Alfresco Web Client • Package and deploy extensionsCertification track objectives At the conclusion of this course, you should have also acquired the requisite knowledge and abilities to pass the Alfresco API developer exam in preparation for the Certified Alfresco ECM professional certificate.Course ScheduleDay 1 • Getting Started • Alfresco SDK • Best Practices • Alfresco Repository Architecture • Developing against the Alfresco Repository • The Spring Framework • Foundation Services API • Java Content Repository (JCR) API • Web Services APIDay 2 • Developing against the Alfresco Repository • Separating Concerns using AOP • Extending the Alfresco Repository • Repository Policies • Repository Actions API Development Course 7
  8. 8. Introduction • Content Transformers • Metadata ExtractorsDay 3 • Extending the Web Client • JavaServer Faces • Actions Framework • Dialog Framework • Wizard Framework • Packaging Extensions • Alfresco Module PackagesHow Prepared are You? • Can you program in Java? • Do you have a basic understanding of XML? • Have you followed the Alfresco administration course? • Have you followed the Alfresco customisation course? • Are you familiar with the Eclipse IDE?Topics not Covered • Installing Alfresco • Repository configuration • Web Client configuration • Customising the Data Dictionary • Developing JavaScript extensions • Developing Freemarker templates • Developing Web ScriptsIntroductions • Name • Company • Title, function, job responsibility • Alfresco experience (API development experience) • Courses already taken • Reasons for taking this course • Expectations8 Alfresco Enterprise Edition Version 3.2
  9. 9. Getting StartedGetting Started API Development Course 9
  10. 10. Getting StartedAlfresco SDKIntroduction The Alfresco SDK provides support for developers who wish to extend or customise the Alfresco platform. It has been designed for the developer to get developing with minimal fuss for the following development scenarios: • Developing extensions for the Alfresco Repository and Web Client. • Embedding Alfresco into applications via Alfrescos Java Foundation Services API or standards-compliant JCR API. • Developing applications against a remote Alfresco Repository via Alfrescos Web Services API. Typically, the SDK is used stand-alone, but an Alfresco installation is also required if performing any of the following: • Customising the Alfresco Web Client • Deploying a custom module to a remote Alfresco repository • Testing a custom application that connects to a remote Alfresco repository The SDK is not designed for re-building Alfresco since it does not provide full build scripts and artifacts. If you wish to develop bug fixes or extend the core functionality of the Alfresco platform, you should use the full Alfresco development environment provided in the Alfresco SVN Repository. For more information, see SVN Repository on page 19.Downloading and Unpacking the Alfresco SDK You will need to install the following software and development tools in order to use the SDK correctly: • the Java SE Development Kit (JDK) version 1.5 (5.0) or above; • a supported database of your choice (MySQL is recommended for development purposes); • the Eclipse IDE 3.x (highly recommended). The Alfresco SDK bundle is provided with each release of Alfresco, for both the Enterprise and Community Networks. 1. Downloading the Alfresco SDK The Enterprise SDK is only available to Enterprise clients and partners. The Community SDK is freely available and can be downloaded from the Download Alfresco Community Network page on the Alfresco Developer web site. The SDK is provided in both ZIP and TAR (tar.gz) formats. 2. Unpacking the Alfresco SDK To install the SDK, simply unpack the downloaded ZIP or TAR bundle to a directory of your choice.10 Alfresco Enterprise Edition Version 3.2
  11. 11. Getting Started For a description of the contents of the Alfresco SDK, see SDK Contents on page 20.Importing the Alfresco SDK projects into Eclipse When using the Alfresco SDK, the Eclipse IDE is highly recommended. The SDK contains several pre-configured Eclipse projects that you can import directly into Eclipse with the following procedure. 1. Setting the Eclipse Compiler Compliance Level Alfresco uses Java 1.5 (5.0) language features, therefore Eclipse must be configured appropriately for the Java SE Development Kit (JDK) version 1.5 (5.0) or above. a. From the Eclipse main menu, select Window # Preferences... b. In the Preferences dialog, select Java # Compiler in the tree view. c. In the JDK Compliance panel, set the Compiler compliance level to 5.0 or above: API Development Course 11
  12. 12. Getting Started d. Click OK 2. Importing the Alfresco SDK projects a. From the Eclipse main menu, select File # Import... b. In the Import dialog, select General # Existing Projects into Workspace import source and click Next > c. Choose Select root directory option and click Browse... d. Navigate to the file system directory where you unpacked the Alfresco SDK and click OK. The Alfresco SDK projects are now listed under Projects. Do not navigate to the samples sub-directory, otherwise you will not see the SDK AlfrescoEmbedded and SDK AlfrescoRemote projects in the list.12 Alfresco Enterprise Edition Version 3.2
  13. 13. Getting Started In order to run the samples or to develop your own extension modules, you must import at least the SDK AlfrescoEmbedded and SDK AlfrescoRemote projects. The other SDK projects are samples for common development scenarios that you can study and run to learn more about developing Alfresco extension modules. For more information about the available projects, see SDK Eclipse Projects on page 20. e. Once you have selected the projects you wish to import, click Finish.The imported projects are displayed in the Package Explorer: API Development Course 13
  14. 14. Getting StartedAssociating Source Code and Javadocs with the Alfresco Libraries Once the Alfresco SDK projects have been imported into Eclipse, it is useful to have access to Alfrescos source code and Java documentation. The following procedure explains how to do this by associating the source code and Javadocs with the Alfresco libraries within Eclipse. 1. Expand the SDK AlfrescoEmbedded project in the Project Explorer. 2. Right click on the alfresco-repository.jar and select Properties from the popup menu. The JAR files may not be in alphabetical order. 3. Associating source code a. In the Properties for alfresco-repository.jar dialog, select Java Source Attachment in the tree view. b. In the Java Source Attachment panel, click External File... c. Navigate to src directory within your unpacked Alfresco SDK. d. Select repository-src.zip and click Open.14 Alfresco Enterprise Edition Version 3.2
  15. 15. Getting Started4. Associating Javadocs a. In the Properties for alfresco-repository.jar dialog, select Javadoc Location in the tree view. b. In the Javadoc Location panel, select Javadoc in archive and click Browse... c. Navigate to doc/api directory within your unpacked Alfresco SDK. d. Select repository-doc.zip and click Open. e. Click Validate... to validate the Javadoc location, then click either OK to view the Javadocs in a web browser or Cancel if not. API Development Course 15
  16. 16. Getting Started 5. Click OK, to close the Properties dialog. Once the source code and Javadocs have been attached, the alfresco-repository.jar icon changes to include a small document: The above steps need to be repeated for the following JARs: • alfresco-core.jar • alfresco-remote-api.jar • alfresco-web-client.jar • alfresco-web-service-client.jar (only Java source code is available)SDK samplesFirstFoundationClient and JCR Samples The SDK FirstFoundationClient, SDK FirstJCRClient and SDK JCRSamples sample projects demonstrate how to access an embedded Alfresco repository via the Foundation Services API and the standards-compliant JCR API. These samples can be tested directly from within Eclipse and will automatically start an Alfresco repository in embedded mode. Before starting, the embedded repository needs to be configured. By default, the sample projects are configured to use a MySQL database named alfresco and a data directory with a relative path of ./alf_data. These parameters are defined in the custom-repository.properties file in the source/alfresco/extension directory of each project. It is good practice to define an absolute path for the data directory (dir.root parameter) and to configure all of the SDK projects to share the same database and the same dir.root. Example custom-repository.properties file: dir.root=C:/alf_data16 Alfresco Enterprise Edition Version 3.2
  17. 17. Getting Started#db.username=alfresco#db.password=alfresco## MySQL connection (This is default and requires mysql-connector-java-3.1.12-bin.jar, which ships with the Alfresco server)##db.driver=org.gjt.mm.mysql.Driver#db.url=jdbc:mysql://localhost/alfrescoThe alfresco MySQL database also needs to be created using the scripts provided in theextras/databases/mysql directory of the unpacked Alfresco SDK. To create the database fromthe command line:C:alfresco-enterprise-sdkextrasdatabasesmysql>mysql -u root -p < db_setup.sqlEnter password: ********The samples can now be tested by running the main Java classes from within Eclipse. In thefollowing example, the FirstFoundationClient class is run as a Java Application:The Alfresco repository is automatically started in embedded mode. Because this is the first timethe repository has been started, the initial bootstrap is executed to create the database tables. Asyou can see from the console messages below, the embedded repository uses C:alf_data asits data directory (dir.root). API Development Course 17
  18. 18. Getting Started The other embedded repository samples (SDK FirstJCRClient and SDK JCRSamples) can be run in the same way.Web Services Samples The SDK FirstWebServiceClient and SDK WebServiceSamples sample projects demonstrate how to access a remote Alfresco repository via the Web Services API. A remote Alfresco repository needs to be installed and running before testing one of these samples. Before running one of the Web Services samples, a remote repository needs to be installed and configured. The easiest solution for development purposes is to install Alfresco on the local machine and configure it to use the same alfresco MySQL database and the same C:/alf_dir data directory as the embedded repository used for the other samples. The location of the remote repository is configured in the webserviceclient.properties file in the source/alfresco/extension directory of each Web Services project. If the remote repository is installed on the same machine and configured to use the default 8080 port, you will not have to modify the default value. Example webserviceclient.properties file: # # Set the following property to reference the Alfresco server that you would like web service client # to communicate with repository.location=http://localhost:8080/alfresco/api Once the remote repository has been installed and started, the Web Clients samples can be tested by running the main Java classes from within Eclipse. In the following example, the FirstWebServiceClient class is run as a Java Application:Custom Repository Samples The SDK CustomAction and SDK CustomAspect sample projects demonstrate how to develop custom modules that may be deployed to an Alfresco repository. Initially, custom repository18 Alfresco Enterprise Edition Version 3.2
  19. 19. Getting Started modules can be developed and tested using unit tests and an embedded Alfresco repository. The SDK CustomAspect project has a sample unit test that does this. An Ant build.xml file is provided for packaging the repository samples. The package target packages the compiled classes and extension files into a JAR file. To deploy the samples, copy the JAR file to the WEB-INF/lib folder of an existing Alfresco installation and restart the application server. For deployment in a production environment, a custom repository module should be packaged as an Alfresco Module Package (AMP). For more information on creating a custom repository action, see the Repository Action Howto on page 79. For a detailed presentation of the SDK CustomAspect sample, see the Custom Aspect with Behaviour Howto on page 71.Custom Web Client Samples The SDK CustomDialog, SDK CustomJSP, SDK CustomLogin, SDK CustomWizard, and SDK TaggingSample sample projects demonstrate how to develop custom modules for the Alfresco Web Client. Custom Web Client modules have to be deployed to an existing Alfresco installation for testing. An Ant build.xml file is provided for packaging the Web Client samples. The package- jar target packages the compiled classes and extension files into a JAR file. The package- extension target then packages the JAR file along with the JSPs into a ZIP file. The optional integrate-extension target can be used to integrate the packaged ZIP file into an Alfresco Web Client WAR file. The alfresco.war file must be copied to the same directory as the build.xml file before running the Ant build and then re-deployed to the application server. For deployment in a production environment, a custom Web Client module should be packaged as an Alfresco Module Package (AMP). The SDK CustomDialog and SDK CustomWizard are presented in detail in the Custom Dialog Howto on page 123 and the Custom Wizard Howto on page 132. The SDK TaggingSample sample is presented in detail in the Repository Action Howto on page 79.Basic AMP Sample The SDK Basic AMP sample project demonstrates how to structure a project and how to arrange classes and configuration files to generate an Alfresco Module Package (AMP). For more information see Basic AMP Howto on page 143.SVN Repository The Alfresco Subversion repository gives you access to all of the Alfresco source code and build artifacts. It provides the latest work-in-progress developments. It should only be used if you wish to extend the Alfresco core framework or work on Alfresco bug fixes as it allows you to perform full re-builds of Alfresco itself. For most requirements, it is best to use the Alfresco SDK. Public read-only access to the Alfresco Subversion repository is available from the Alfresco web site. To checkout the source code, use the following procedure: 1. Install Subversion and ensure that svn is on the path. 2. Checkout the HEAD of the code stream: svn co svn://svn.alfresco.com/alfresco/HEAD or svn co http://svn.alfresco.com/repos/alfresco-open-mirror/alfresco/HEAD 3. Keep up to date by issuing the command: svn update API Development Course 19
  20. 20. Getting StartedSDK ReferenceSDK Contents bin Supporting dlls, exes. doc Zipped Javadocs for all pre-built libraries. extras Additional files - database setup and migration scripts. lib Alfresco pre-built libraries (JAR files). lib/deployment Alfresco libraries required for WCM deployment to a remote server. lib/remote Alfresco libraries required for access to a remote Alfresco repository via web services. lib/server Alfresco libraries required for embedding an Alfresco repository. licenses License files. samples Sample Eclipse projects for common development scenarios (see SDK Eclipse Projects on page 20). src Zipped source code for all pre-built libraries. license.txt Alfresco licence file. notice.txt Notices readme.txt Alfresco SDK readme.SDK Eclipse Projects SDK AlfrescoEmbedded Project containing all of the Alfresco libraries needed to build a custom module that will be embedded into the Alfresco repository or Web Client. SDK AlfrescoRemote Project containing all of the Alfresco libraries needed to build a custom Web Services client. SDK Basic AMP Sample project demonstrating how to build an AMP (Alfresco Module Package) file. SDK CustomAction Sample project demonstrating how to develop a custom Action that may be deployed to an Alfresco repository. SDK CustomAspect Sample project demonstrating how to develop a custom Aspect with behaviour that may be deployed to an Alfresco repository.20 Alfresco Enterprise Edition Version 3.2
  21. 21. Getting StartedSDK CustomDialog Sample project demonstrating how to develop and configure a custom Dialog for the Alfresco Web Client.SDK CustomJSP Sample project demonstrating how to develop and configure a custom JSP for the Alfresco Web Client.SDK CustomLogin Sample project demonstrating how to override the Login page of the Alfresco Web Client.SDK CustomWizard Sample project demonstrating how to develop and configure a custom Wizard for the Alfresco Web Client.SDK FirstFoundationClient Sample project demonstrating how to access an Alfresco (embedded) repository via the Foundation Services API.SDK FirstJCRClient Sample project demonstrating how to access an Alfresco (embedded) repository via the standards-compliant JCR API.SDK FirstWebServiceClient Sample project demonstrating how to access a remote Alfresco repository via the Web Services API.SDK JCRSamples More sample projects demonstrating how to access an Alfresco (embedded) repository via the standards-compliant JCR API.SDK TaggingSample Advanced sample project demonstrating how to develop a custom Action that takes parameters.SDK WebServiceSamples More sample projects demonstrating how to access a remote Alfresco repository via the Web Services API. API Development Course 21
  22. 22. Getting StartedBest PracticesCoding StandardsCoding Standards - Formatting • The core coding standards are the standard Java Code Conventions. • Braces are on new lines. • 4 space for tabbing, except for Web Client project that uses 3 spaces. • 120 characters on a line is fine. • Import declarations are managed by Eclipses standard ordering rules (CTRL-SHIFT-O). This helps prevent code merge conflicts. • XML documents use 3 space tabbing. The Eclipse plug-in, XMLBuddy, is generally used.Coding Standards - Exceptions • When generating a new exception, always attach the cause to it. • Dont log exceptions unless you are adding the logic to absorb the exception. • Put as much context and formatting into the error message as possible. • Use RuntimeException derived exceptions, unless there is a really good reason to bother the client code with a checked exception. • Pay attention to the Javadoc specification on unchecked exceptions. Dont declare them on the interface, just in the Javadocs.Coding Standards - Logging • Use the Apache Commons Logging API so that all logging output is uniform. • Use the class hierarchy categories, but where deviations are made, add comments to the Javadocs. • INFO messages are only added at the request of Alfresco users. All other informative messages are DEBUG. • Put as much context and formatting into the message as time will allow. • Wrap all calls to logger.debug and logger.info, and only log messages if logger.isDebugEnabled and logger.isInfoEnabled respectively.Coding Standards - File Formats • UTF-8 encoding of all text files • Windows line endings (CR-LF)Alfresco Module Packages (AMP) An Alfresco Module Package (AMP) is a collection of code, XML, images, CSS, etc. that collectively extend the functionality or data provided by the standard Alfresco Repository. An AMP file can contain as little as a set of custom templates or a new category. It can contain a custom model and associated UI customisations. It could contain a complete new set of functionality, for example records management. As a general rule of thumb, anything that is considered to be an “installable” extension to the Alfresco repository should be called a module and packaged as an AMP file. AMP files can be installed into the Alfresco WAR using the Module Management Tool. An AMP file has a standard format that can be customised if required.22 Alfresco Enterprise Edition Version 3.2
  23. 23. Getting Started Once the contents of the AMP file has been mapped into an Alfresco WAR using the Module Management Tool, the WAR can be deployed to the application server. When the repository is next started, the installed module configuration will be detected, and the repository will be bootstrapped to include the new module functionality and data.AMP Project Structure An Alfresco Module project can be structured in any way that suits the developer environment. As long as the resulting AMP file is packaged correctly and the required property and context files are present, the module will install successfully. The recommended project structure is as follows: |-- source | |-- java |-- <module package structure starts here> | |-- web |-- css |-- images |-- jsp |-- scripts | |-- config |-- <resource package structure starts here> | |-- build |-- dist |-- lib | |-- build.xml source/java/ Contains the Java source for the Alfresco Module. source/web/ Contains any web UI resources (JSPs, images, CSS, JavaScript). config/ Contains configuration files and resources used by the module. build/ Build directory for compiled class files. build/dist/ Build directory for AMP files. build/lib/ Build directory for JAR files. The recommended package structure for Java source (source/java), configuration files and resources (config) is org.alfresco.module.<moduleid>, where moduleid is the unique module id of the module. Alfresco Module Packages are presented in more detail later on in the course. For more details, see Introduction on page 143. API Development Course 23
  24. 24. Getting StartedAlfresco Repository ArchitectureOut of the Box Out-of-the-box, Alfrescos simple installation procedure provides a pre-configured deployment aimed at reaching a complete and working Content Management application as quickly and easily as possible. The deployment is as follows: This is typical of a web architecture, where an application server houses the logic for both the user interface and domain. Storage of data and content is provided by persistent back-ends such as a database or file system. Any number of web browsers can connect to the application without prior client installation costs. In this particular case, the application server houses both the Alfresco Application and the Alfresco Repository. An Alfresco Application provides a complete solution tailored for a specific area of Content Management such as Document Management (DM), Web Content Management (WCM) and Records Management (RM). The Alfresco Repository provides a set of reusable cross-cutting Content Management services such as content storage, query, versioning and transformation which may be utilised by one or more applications. Although this is the default installed deployment, it is only one of many ways of utilising the capabilities and components of Alfresco. When we first set out to design Alfresco, we wanted to break away from the mould of typical Content Management architectures which are monolithic and closed. The result is that Alfresco can neatly fit into existing environments and each of its24 Alfresco Enterprise Edition Version 3.2
  25. 25. Getting Started components may be used in isolation or together to form the basis of many differing Content Management solutions. The remainder of this module explores the anatomy of the Alfresco Repository which will give a good understanding of the concepts and capabilities and how it achieves openness, scalability and flexibility.Service & Component Architecture Every part of the Alfresco Repository is either a component or a service. A component is an implementation black box that provides a specific feature or capability. A service is an interface entry point for a client to bind to and use. This fundamental approach allows for existing components to be switched with new implementations, new components to be added with ease and for clients to connect and use services without knowledge of how theyre implemented. If theres a feature of Alfresco you dont need, you can take it out, providing a lighter and possibly faster Alfresco. If theres a feature you wish to re-implement, you can replace it, either by providing a better implementation, or integrating with your existing environment. Implementation of this approach is simplified by using the open source project Spring Framework which Alfresco has taken to heart and has made a core foundation of its architecture. With Spring, Alfresco components are declaratively configured and bound together. Aspect-oriented programming allows the weaving of infrastructure concerns such as Transactions and Security into components without polluting their implementation. Environment touch points are abstracted such as resource (e.g. database) connections. The Alfresco Repository structure looks like this: API Development Course 25
  26. 26. Getting Started The public interface point is the Alfresco Repository Foundation Services. Each service is exposed as a Java Interface to which a Repository client can bind and invoke without knowledge of its underlying implementation. A Service Registry lists the available services. Behind services are the implementation black boxes i.e. components. Each service and component is configured via the Spring framework in XML “context” files. The Spring context file public-service-context.xml provides the configuration and binding of the Alfresco Repository Foundation Services. The Repository Foundation Services are the lowest level of public interface providing access to all Repository capabilities. Binding to this interface is possible via the Repository Service Registry, or via Spring dependency injection if the client is also Spring aware. Access to Foundation Services is limited to Repository clients who reside in the same process as the Repository. That is, the Foundation Services are an excellent API for clients who wish to embed the Repository. An important point to note is that the Foundation Services are where transaction and security policies are enforced. The policies themselves are declaratively specified and enforced via the injection of a transaction and security implementation into each service. Every service of Alfresco is transactional and secure. Other forms of API are provided too, however, all public entry points eventually go through this layer. Alfresco supports a common scheme for making extensions to the Repository i.e. configuring a component, adding a new component or service, or removing capabilities. Extensions are26 Alfresco Enterprise Edition Version 3.2
  27. 27. Getting Started encapsulated outside of the core Repository and plugged-in automatically. This means the core Repository can be upgraded to a newer version and extensions remain intact.Repository Foundation Services API The heart of the Alfresco Repository is responsible for the storage and retrieval of content. This is split into nodes, content and index information. Nodes provide meta-data and structure to content. A node may support properties (e.g. author) and relate to other nodes (e.g. represent folder hierarchies or annotations). Content is the actual information being recorded e.g. a Word document or XML fragment. Meta-data and content may be structured according to the rules defined in a Content Model. For example, the Alfresco Document Management application relies on a model that describes Folders and Files. Indexing information allows the retrieval of meta- data and content via many different lookup options. Repository storage and retrieval is provided by the following Foundation Services: • Node Service for managing meta-data i.e. nodes • Content Service for managing content • Search Service for performing queries By default, Alfresco has chosen to store meta-data in a database and content in a file system. Using a database immediately brings in the benefits of databases that have been developed over many years such as transaction support, scaling & administration capabilities. Content is stored in the file system to allow for very large content, random access, streaming and options for different storage devices. The Alfresco out-of-the-box implementations of the above services are built upon strong open source projects that already have many man-years of development effort and strong communities: Hibernate and Lucene. API Development Course 27
  28. 28. Getting Started Apart from the strong Object/Relational mapping that Hibernate provides, it also brings pluggable caching support and SQL dialects. The first allows for tuning of the Alfresco meta-data store to provide optimum read and write performance in both single and clustered environments. The second allows for nearly any SQL database back-end by configuring just two properties; the Alfresco community has already confirmed working support for MySQL, Oracle, DB2, Sybase, SQL Server. By externalising the indexing of meta-data and content and using the Lucene engine as a basis, it is possible to perform complex queries which combine property, location, classification and full-text predicates in a single query against any content type. Multiple query languages are supported including Lucenes native language as well as XPath and a SQL-like language in the future. To ensure reliable operation, transactional support has been added to both Lucene and the content file store providing ACID operations across the complete store. Security is woven into each of the service layer ensuring illegal modifications are not permissible and hidden meta-data and content are not returned. Nearly all other Foundation services and clients rely upon these three core building blocks.Repository APIs The Alfresco Repository actually provides three APIs. Weve already seen one - the Repository Foundation Services - a set of local Java Interfaces covering all capabilities which are ideal for clients who wish to embed the Repository. The two other APIs are: • JCR • Web Services JCR (Content Repository API for Java Technologies) is a standard Java API (as defined by JSR-170) for accessing Content Repositories. Alfresco provides support for level 1 and level 2 giving standardised read and write access. Supporting this API provides the following benefits: • No risk: The Alfresco Repository can be trialled and developed against, but swapped out with another JCR Repository if it does not fit requirements. • Familiarity: Developers who know JCR, know Alfresco. • Tools: Tools, Clients and other 3rd Party JCR solutions are immediately available to the Alfresco community. Alfresco JCR is implemented as a light facade on top of the Repository Foundation Services. So, although a familiar API is provided, it sits upon a fully transactional, secure and scalable Repository which supports many deployment options. Alfresco will continue investment in JCR by both broadening the compliance of the full specification as well driving forward JSR-283, the next version of the JCR. Web Services is the final API provided by the Alfresco Repository. This API supports remote access and bindings to any client environment, not just Java. For example, the Alfresco community is already using PHP, Ruby and Microsoft .NET. Numerous standards and integration efforts are focused around Web Services - SOA is now recognised as a way forward for integrating disparate systems including Content Management and building new enterprise-wide solutions. BPEL plays an important role in orchestrating all of these services. Alfresco fits neatly into this way of thinking.28 Alfresco Enterprise Edition Version 3.2
  29. 29. Getting Started Once again, the Repository Foundation Services serve as the base. Both the JCR and Web Services API eventually go through this layer meaning that all encapsulated content model logic and rules are honoured.Repository Server Protocols A Repository is useless if the content it manages cannot be accessed. To provide the widest possible range of access points, the Alfresco Repository supports a variety of communication protocols. These are: • CIFS (Common Internet File System) • WebDAV • FTP • NFS All of these protocols essentially expose Folders of Files and as such the Alfresco implementations map neatly onto Folder and File nodes held in the Repository as described by the Alfresco Document Management content model. WebDAV, FTP and NFS are well known protocols, but CIFS deserves some more attention. CIFS transforms the Alfresco Repository into a standard file system. Any tool that understands how to read and write to a file system, also knows how to directly read and write to the Alfresco Repository. On the surface, it would seem that a drive mapping to WebDAV provides an equivalent capability, but this isnt the case. CIFS projects an actual file system giving extra compatibility with the hosting operating system. For example, in Windows, its possible to use Offline Synchronisation and Briefcase features against the Alfresco Repository providing native and well-known tools for offline Repository working. Many commercial CMS offerings do not provide this feature. In fact, Alfresco may have the only server-side Java implementation of the API Development Course 29
  30. 30. Getting Started CIFS protocol having brought on board the engineers who spent 7 years developing such a capability. Like every other feature of the Repository, the protocol components are Spring configured and as with all other components may or may not be included in a deployment. Typically, they are enabled when the Repository is deployed as a server to provide access points for remote clients. The various Repository deployment options are explored later in this document. Protocol components are implemented against the Repository Foundation Services. This is important to note, as each protocol will honour the behaviour and content logic encapsulated behind the Foundation Services. In fact, it cannot be bypassed.TerminologyStore Reference (StoreRef) A StoreRef is made up of a store protocol and a store id.30 Alfresco Enterprise Edition Version 3.2
  31. 31. Getting Started public static final String PROTOCOL_WORKSPACE = "workspace"; public static final String PROTOCOL_AVM = "avm"; public static final String URI_FILLER = "://"; The standard store used by the Web Client has the following StoreRef: workspace://SpacesStoreNode Reference (NodeRef) A NodeRef is made up a store reference and a node id. private static final String URI_FILLER = "/"; The node id is a 16 byte (128 bit) A “Universally Unique Identifier” or UUID. Example NodeRef: workspace://SpacesStore/808b2b34-a99f-11db-b572-8337f65f7e0dQualified Name (QName) A QName represents the qualified name of a Repository item. Each QName consists of a local name qualified by a namespace. API Development Course 31
  32. 32. Getting Started Namespace scoped Name Format {URI}localname or prefix:localName Examples {http://www.alfresco.org/model/content/1.0}auditable or cm:auditableNode Browser The Node Browser is your friend!32 Alfresco Enterprise Edition Version 3.2
  33. 33. Developing against the Alfresco RepositoryDeveloping against the Alfresco Repository API Development Course 33
  34. 34. Developing against the Alfresco RepositorySpring FrameworkIntroduction The Spring Framework is a full-stack Java/JEE application framework. Springs main aim is to make J2EE easier to use and promote good programming practise. It does this by enabling a POJO-based programming model remaining faithful to the fundamental ideas of Expert One-on- One J2EE Design and Development. Spring is portable between application servers.Bean Factory A Spring BeanFactory is a generic factory that enables objects to be retrieved by name, and which can manage relationships between objects. Bean factories support two modes of object: • Singleton: in this case, theres one shared instance of the object with a particular name. • Prototype or non-singleton: in this case, each retrieval will result in the creation of an independent object. Beans are defined in an XML bean definition file that is loaded when a new Bean Factory is created.Bean Factory Example 1. Writing a simple JavaBean class Heres the simplest Java Bean you can get! package ex01_simplebean; public class Bean1 { } 2. Defining the Spring beans Two Spring beans are defined for the same class. bean1 is a singleton bean and multibean1 is a prototype bean (singleton="false"): <beans> <bean id="bean1" class="ex01_simplebean.Bean1" /> <bean id="multibean1" class="ex01_simplebean.Bean1" singleton="false" /> </beans> 3. Testing with a Main program a. Creating a new Spring Bean Factory The bean definition file is loaded into the Spring Bean Factory: ClassPathResource res = new ClassPathResource( "ex01_simplebean/ApplicationContext.xml"); XmlBeanFactory factory = new XmlBeanFactory(res); The following messages are written to the console: 15:13:26,515 INFO [XmlBeanDefinitionReader] Loading XML bean definitions from class path resource [ex01_simplebean/ ApplicationContext.xml] 15:13:26,593 INFO [XmlBeanFactory] Creating shared instance of singleton bean bean1 b. Getting bean1 from the Bean Factory34 Alfresco Enterprise Edition Version 3.2
  35. 35. Developing against the Alfresco Repository We retrieve bean1 from the Bean Factory using the getBean() method: Bean1 bean1a = (Bean1) factory.getBean("bean1"); System.out.println("Retrieved Bean1: " + bean1a.toString()); Bean1 bean1b = (Bean1) factory.getBean("bean1"); System.out.println("Retrieved Bean1: " + bean1b.toString()); Each call retrieves the same bean (there is only one instance): Retrieved Bean1: ex01_simplebean.Bean1@471e30 Retrieved Bean1: ex01_simplebean.Bean1@471e30 c. Getting multibean1 from the Bean Factory Now we retrieve multibean1 from the Bean Factory. Bean1 bean1a = (Bean1) factory.getBean("multibean1"); System.out.println("Retrieved MultiBean1: " + bean1a.toString()); Bean1 bean1b = (Bean1) factory.getBean("multibean1"); System.out.println("Retrieved MultiBean1: " + bean1b.toString()); This time each call retrieves a new instance of the bean: Retrieved MultiBean1: ex01_simplebean.Bean1@10ef90c Retrieved MultiBean1: ex01_simplebean.Bean1@a32bInversion of Control (IoC) Through its bean factory concept, Spring is an Inversion of Control container. Spring is most closely identified with a flavour of Inversion of Control known as Dependency Injection. The concept behind Inversion of Control is often expressed in the Hollywood Principle: “Dont call me, Ill call you.” IoC moves the responsibility for making things happen into the framework, and away from application code. Whereas your code calls a traditional class library, an IoC framework calls your code.Dependency Injection Dependency Injection is a form of IoC that removes explicit dependencies on container APIs. Ordinary Java methods are used to inject dependencies such as collaborating objects or configuration values into application object instances. The two major flavors of Dependency Injection are: • Setter Injection (injection via JavaBean setters) • Constructor Injection (injection via constructor arguments). Spring provides sophisticated support for both, and even allows you to mix the two when configuring the one object.Setter Injection Example 1. Writing a simple JavaBean class This simple JavaBean supports properties. The values of the properties are set by the Spring Bean Factory when the bean is instantiated. package ex02_setter; public class Bean1 { public void setString(String val) { m_strVal = val; } public String getString() { return m_strVal; } public void setInt(int val) { m_intVal = val; } public int getInt() { return m_intVal; } API Development Course 35
  36. 36. Developing against the Alfresco Repository public void setList(List strings) { m_strings = strings; } public List getList() { return m_strings; } private String m_strVal; private int m_intVal; private List m_strings; } 2. Defining the Spring beans A single bean is defined with initial values for the properties that will be initialised via the “setter” methods on the JavaBean: <beans> <bean id="bean1" class="ex02_setter.Bean1"> <property name="string"> <value>a string</value> </property> <property name="int"> <value>125</value> </property> <property name="list"> <list> <value>item1</value> <value>item2</value> <value>item3</value> </list> </property> </bean> </beans> 3. Testing with a Main program We retrieve bean1 from the Bean Factory and print out the values of the properties: Bean1 bean1a = (Bean1) factory.getBean("bean1"); System.out.println("Retrieved Bean1: " + bean1a.toString()); String strVal = bean1a.getString(); System.out.println("String property: " + strVal); int intVal = bean1a.getInt(); System.out.println("Int property: " + intVal); List strings = bean1a.getList(); System.out.println("List property: " + strings); The properties have automatically been initialised by the Bean Factory: Retrieved Bean1: ex02_setter.Bean1@21b6d String property: a string Int property: 125 List property: [item1, item2, item3]Constructor Injection Example 1. Writing a simple JavaBean class This time the JavaBean has a constructor and some properties. The String property is passed to the constructor and the int property has a “setter” method. package ex03_constructor; public class Bean1 { public Bean1(String val) { m_strVal = val; } public String getString() { return m_strVal; }36 Alfresco Enterprise Edition Version 3.2
  37. 37. Developing against the Alfresco Repository public void setInt(int val) { m_intVal = val; } public int getInt() { return m_intVal; } private String m_strVal; private int m_intVal; } 2. Defining the Spring beans This time a bean is defined with a constructor argument. The String property will be initialised via the constructor and the int property via the “setter” method on the JavaBean: <beans> <bean id="bean1" class="ex03_constructor.Bean1"> <constructor-arg index="0"> <value>a string</value> </constructor-arg> <property name="int"> <value>125</value> </property> </bean> </beans> 3. Testing with a Main program We retrieve bean1 from the Bean Factory and print out the values of the properties: Bean1 bean1a = (Bean1) factory.getBean("bean1"); System.out.println("Retrieved Bean1: " + bean1a.toString()); String strVal = bean1a.getString(); System.out.println("String property: " + strVal); int intVal = bean1a.getInt(); System.out.println("Int property: " + intVal); The properties have automatically been initialised by the Bean Factory: Retrieved Bean1: ex03_constructor.Bean1@12152e6 String property: a string Int property: 125Dependency Injection Example 1. Writing the JavaBean classes a. Two more simple JavaBean classes These two JavaBeans will be used as dependencies: package ex04_dependency; public class Bean2 { } package ex04_dependency; public class Bean3 { } b. Establish a constructor dependency The Bean1 class depends on the Bean2 class via the constructor: package ex04_dependency; API Development Course 37
  38. 38. Developing against the Alfresco Repository public abstract class Bean1 { public Bean1(Bean2 bean2) { m_bean2 = bean2; } ... public Bean2 getBean2() { return m_bean2; } ... private Bean2 m_bean2; } c. Establish a setter dependency The Bean1 class depends on the Bean3 class via a property setter: public void setBean3(Bean3 bean3) { m_bean3 = bean3; } public Bean3 getBean3() { return m_bean3; } private Bean3 m_bean3; 2. Defining the Spring beans bean1 depends on bean2 and bean3. The Bean Factory will instantiate the bean2 and bean3 objects before “injecting” them into bean1 via the constructor property setter respectively: <beans> <bean id="bean1" class="ex04_dependency.Bean1"> <constructor-arg index="0"> <ref bean="bean2"/> </constructor-arg> <property name="bean3"> <ref bean="bean3"/> </property> </bean> <bean id="bean2" class="ex04_dependency.Bean2"/> <bean id="bean3" class="ex04_dependency.Bean3"/> </beans> 3. Testing with a Main program We retrieve bean1 from the Bean Factory and print out the dependencies: Bean1 bean1 = (Bean1) factory.getBean("bean1"); System.out.println("Retrieved Bean1: " + bean1.toString()); Bean2 bean2 = bean1.getBean2(); Bean3 bean3 = bean1.getBean3(); System.out.println("Retrieved Bean2 Dependency: " + bean2.toString()); System.out.println("Retrieved Bean3 Dependency: " + bean3.toString()); The dependencies have automatically been injected by the Bean Factory: Retrieved Bean1: ex04_dependency.Bean1$$EnhancerByCGLIB$$d8a83b@1cb25f1 Retrieved Bean2 Dependency: ex04_dependency.Bean2@2808b3 Retrieved Bean3 Dependency: ex04_dependency.Bean3@535b5838 Alfresco Enterprise Edition Version 3.2
  39. 39. Developing against the Alfresco RepositoryApplication Context To start using Spring you either instantiate a Spring BeanFactory or an ApplicationContext. ApplicationContext is derived from BeanFactory and provides all of the BeanFactory funtionality and more including: • MessageSource, providing access to messages in, i18n-style • Access to resources, such as URLs and files • Event propagation to beans implementing the ApplicationListener interface • Loading of multiple (hierarchical) contexts, allowing each to be focused on one particular layer, for example the web layer of an applicationWeb Application Context A Spring WebApplicationContext is just an ordinary ApplicationContext that has some extra features necessary for web applications. It is bound in the ServletContext and is created by a ContextLoaderListener.Context Loader Listener The Spring ContextLoaderListener is declared in WEB-INF/web.xml: <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>Spring contextConfigLocation Use the contextConfigLocation <context-param> to set which context files to load: <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:alfresco/web-client-application-context.xml classpath:web-services-application-context.xml classpath:alfresco/application-context.xml </param-value> <description>Spring config file locations</description> </context-param> API Development Course 39
  40. 40. Developing against the Alfresco RepositoryFoundation Services APIIntroduction The Foundation Services API is a set of services providing full access to the capabilities of the Alfresco Repository. It is an in-process API meaning that the client must run within the same process as the Repository. For example, the Alfresco Web Client uses this API and is packaged together with the Repository in a single WAR file for deployment to an application server.Access to Repository Foundation Services The Foundation Services API is comprised of a set of interfaces; each interface represents a function of the Repository. A Spring Framework Bean is provided as the implementation for each interface. The list of available public services (i.e. Spring beans) can be found in: • the Spring configuration file public-services-context.xml • the Service Registry interface org.alfresco.service.ServiceRegistry There are three ways to access Foundation Services: 1. use Spring IoC to directly inject services into your code (If your layer is also Spring enabled); 2. use the Alfresco Service Registry; 3. manually access services via the Spring getBean() method.FirstFoundationClient walkthrough Before getting started, you should be familiar with the Introduction on page 34. The sample uses several of the key foundation services, including the ServiceRegistry, TransactionService, AuthenticationService, SearchService, NodeService and ContentService. After initialising the Spring Application Context and starting the repository in embedded mode, we will use the Spring getBean() method to access the ServiceRegistry. We will then use the ServiceRegistry to access the other foundation services. After authenticating to the repository using the AuthenticationService, we will search for the “Company Home” node using the SearchService. We will then create a new node with properties and add an aspect using the NodeService. Finally, we will write some content to the new node using the ContentService. The sample will be wrapped in a single user transaction with the help of the TransactionService. 1. Getting the ServiceRegistry The Service Registry maintains a list of available foundation services and some meta-data about each. In particular, the Service Registry provides access to each service interface. The registry is a service itself and is therefore accessed using either Spring IoC or the Spring getBean() method. The static variable SERVICE_REGISTRY found on the interface org.alfresco.service.ServiceRegistry provides the Spring Bean name to lookup by. The FirstFoundationClient sample uses the getBean() method on the Spring Application Context to retrieve the ServiceRegistry: ApplicationContext ctx = ApplicationContextHelper.getApplicationContext(); final ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);40 Alfresco Enterprise Edition Version 3.2
  41. 41. Developing against the Alfresco Repository2. Using the TransactionService to run the example in a user transaction By default, all repository foundation services are transactional and each invocation of a service method is wrapped in its own transaction. These transactions are defined declaratively in Spring configuration files and not in your Java code. In most cases, declarative transactions are preferred to user transactions since they are less invasive. There are situations, however, when user transactions do need to be used explicitly in your code. The FirstFoundationClient uses a RetryingTransactionHelper to run the example as a unit of work inside a user transaction. The work is defined as an instance of the RetryingTransactionCallback class. The doInTransaction() method is then called to run the unit of work in a transaction. The RetryingTransactionHelper is obtained via the getRetryingTransactionHelper() method on the TransactionService. For clarity, not all of the available methods are shown. For a complete description, please consult the Javadocs: Interface TransactionService The TransactionService and RetryingTransactionHelper are presented in more detail in the section on Transactions. The following example runs the example work in a user transaction via the RetryingTransactionHelper: TransactionService transactionService = serviceRegistry.getTransactionService(); RetryingTransactionCallback<Object> exampleWork = new RetryingTransactionCallback<Object>() { public Object execute() throws Exception { doExample(serviceRegistry); return null; } }; transactionService. getRetryingTransactionHelper().doInTransaction(exampleWork);3. Using the AuthenticationService for authentication API Development Course 41
  42. 42. Developing against the Alfresco Repository Before making any call to the repository through the public Foundation Services API, a user must first be authenticated. This is done via the AuthenticationService by using the authenticate() method and providing a username and password. Once authenticated, a ticket can be requested using either the getNewTicket() or the getCurrentTicket() method. The ticket can then be used to re-validate the user using the validate() method. The AuthenticationService defines the API for managing authentication information against a username. For clarity, not all of the available methods are shown. For a complete description, please consult the Javadocs: Interface AuthenticationService In the example, the authenticate() method is used to authenticate as the “admin” user. The password must be passed as a character array. AuthenticationService authenticationService = serviceRegistry.getAuthenticationService(); authenticationService.authenticate("admin", "admin".toCharArray()); 4. Using the SearchService to locate the “Company Home” node The SearchService provides many methods for searching the Alfresco repository using any of the available query languages: Lucene, XPath or JCR-XPath. The Lucene query language allows you to run powerful searches, including full text searches on the content and node properties. To run a Lucene search using the query() method, you must specify the StoreRef of the store you wish to search, the query language (using one of the static attributes defined on the SearchService interface - LANGUAGE_LUCENE for example) and the query as a String. The parameters can either be passed directly to the query() method, or be defined on a new SearchParameters object which is then passed to the query() method. The query results are returned as a ResultSet object.42 Alfresco Enterprise Edition Version 3.2
  43. 43. Developing against the Alfresco Repository For clarity, not all of the available methods are shown. For a complete description, please consult the Javadocs: Interface SearchService The following example runs a Lucene query using the PATH syntax to locate the “Company Home” by its absolute path. The getNodeRef(0) call is used to retrieve the first NodeRef from the ResultSet. In theory, the query should only return one result. SearchService searchService = serviceRegistry.getSearchService(); StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"); ResultSet resultSet = searchService.query( storeRef, SearchService.LANGUAGE_LUCENE, "PATH:"/app:company_home""); NodeRef companyHome = resultSet.getNodeRef(0); For more information on using the SearchService and on query string syntax, see the Search page on the Alfresco Wiki.5. Using the NodeService to create a node The NodeService provides methods for operations on nodes and stores. Stores are created with createStore(). Nodes are created with createNode() and deleted with deleteNode(). Properties are set with either setProperty() or setProperties(). Properties are removed with removeProperty(). Aspects are applied with addAspect() and removed with removeAspect(). Associations are created and removed with createAssociation() and removeAssociation(). Associations can be navigated with getSourceAssocs() or getTargetAssocs(). Child associations can be navigated with getChildAssocs() and getParentAssoc(). Almost all NodeService methods take a NodeRef as an argument. A NodeRef is obtained either by navigation or from the results of a search. Otherwise a new NodeRef object can be created from the nodes unique UUID. API Development Course 43
  44. 44. Developing against the Alfresco Repository For clarity, not all of the available methods are shown. For a complete description, please consult the Javadocs: Interface NodeService a. Setting properties Properties are set on nodes using either the setProperty() or setProperties() methods. setProperty() allows a single property to be set, whilst setProperties() takes a Map of properties and sets all of the nodes properties at once. Each property is identified by its QName and its value must be Serializable. public void setProperty( NodeRef nodeRef, QName qname, Serializable value) public void setProperties( NodeRef nodeRef, Map<QName, Serializable> properties) nodeRef NodeRef of the node to set the property on.44 Alfresco Enterprise Edition Version 3.2
  45. 45. Developing against the Alfresco Repository qname QName of the property to set. value Value of the property. The value must be Serializable. properties Map of all the properties of the node keyed by QName. The property QNames are usually defined as a static constants on the dictionary model interfaces. For example, the cm:name property is defined by the static constant ContentModel.PROP_NAME. The following example creates a Map containing the cm:name property that will be used in the next step: String name = "Foundation API sample (" + System.currentTimeMillis() + ")"; Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>(); contentProps.put(ContentModel.PROP_NAME, name);b. Creating a node Nodes are created using the createNode() method. A node is created as a child of a parent node. The child association name and child association type have to be supplied as QName objects, as well as the QName of the type of node to create and optionally a Map of properties to set on the newly created node. public ChildAssociationRef createNode( NodeRef parentRef, QName assocTypeQName, QName assocQName, QName nodeTypeQName, Map<QName, Serializable> properties) parentRef NodeRef of the parent node. The created node will be one of its children. assocTypeQName QName of the type of association to create. This is used for verification against the data dictionary. assocQName QName of the association. nodeTypeQName QName of the node type. properties Optional Map of properties to set keyed by QName. The association and node type QName objects are usually defined as a static constants on the dictionary model interfaces. For example, the cm:contains association type is defined by the static constant ContentModel.ASSOC_CONTAINS and the cm:content node type is defined by the static constant ContentModel.TYPE_CONTENT. If a constant does not exist, a QName can be created using the QName.createQName() static method as in the example below. The createNode() method returns a ChildAssociationRef to the newly created child association. The NodeRef of the newly created node is obtained by calling the getChildRef() on the ChildAssociationRef object. API Development Course 45
  46. 46. Developing against the Alfresco Repository The following example creates a new node of type cm:content, using the standard cm:contains child association. The Map created in the previous step sets the cm:name property on the newly created node. NodeService nodeService = serviceRegistry.getNodeService(); ChildAssociationRef association = nodeService.createNode(companyHome, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_PREFIX, name), ContentModel.TYPE_CONTENT, contentProps); NodeRef content = association.getChildRef(); c. Adding an aspect Aspects are applied to nodes using the addAspect() method. The node is identified by its NodeRef and the aspect by its QName. The property values are provided as a Map. public void addAspect( NodeRef nodeRef, QName aspectTypeQName, Map<QName, Serializable> aspectProperties) nodeRef NodeRef of the node to apply the aspect to. aspectTypeQName QName of the aspect to apply. aspectProperties Map containing a minimum of the mandatory properties required for the aspect. The aspect QNames are usually defined as a static constants on the dictionary model interfaces. For example, the cm:titled aspect is defined by the static constant ContentModel.ASPECT_TITLED. The following example applies the cm:titled aspect and sets the cm:title and cm:description properties: Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(); titledProps.put(ContentModel.PROP_TITLE, name); titledProps.put(ContentModel.PROP_DESCRIPTION, name); nodeService.addAspect(content, ContentModel.ASPECT_TITLED, titledProps); 6. Using the ContentService to write content The ContentService provides methods for reading, writing and transforming content. In order to read or write content from and to a node, you must first obtain a ContentReader or a ContentWriter via the getReader() and getWriter() methods respectively. Methods can then be used on the ContentReader or ContentWriter to read and write content. Both the ContentReader and the ContentWriter implement the methods defined by the ContentAccessor interface. These methods allow you to get and set information about the content, for example to set the mime type, the encoding or to get the size. The actual content is stored on the cm:content property (ContentModel.PROP_CONTENT) of each node. When requesting a ContentReader or a ContentWriter, the NodeRef needs to be supplied along with the ContentModel.PROP_CONTENT QName. The ContentService is also used for transforming content. A suitable transformer can be obtained for a given transformation (defined by a source and target mime type) using46 Alfresco Enterprise Edition Version 3.2
  47. 47. Developing against the Alfresco Repositorythe getTransformer() and getImageTransformer() methods. The transformation canthen be performed by calling transform directly on the content transformer. Otherwise,a transformation can be attempted from a source ContentReader object to targetContentWriter object by calling the transform() method on the ContentService.For more information, see Introduction on page 91. For clarity, not all of the available methods are shown. For a complete description, please consult the Javadocs: • Interface ContentService • Interface ContentReader • Interface ContentWriter • Interface ContentAccessorThe following example gets a ContentWriter to the newly created node. The propertyto be updated is defined by the QName ContentModel.PROP_CONTENT. The boolean truevalue is to request that the content is updated atomically when the content write streamis closed. The content mime type and encoding are set before writing the content with theputContent() method.ContentService contentService = serviceRegistry.getContentService();ContentWriter writer = contentService.getWriter(content, ContentModel.PROP_CONTENT, true);writer.setMimetype(MimetypeMap.MIMETYPE_TEXT_PLAIN);writer.setEncoding("UTF-8");String text = "The quick brown fox jumps over the lazy dog";writer.putContent(text); API Development Course 47
  48. 48. Developing against the Alfresco Repository Once completed, the newly created node may be viewed via the Web client. The web client will need to be re-started after executing the sample to see the changes in effect.Other Foundation ServicesFileFolderService The FileFolderService provides methods specific to manipulating Alfresco defined content files and folders. The methods can be more convenient and easier to use than the equivalent NodeService and ContentService methods. Certain methods, such as create(), return a FileInfo object. A NodeRef can then be retrieved using the FileInfo.getNodeRef() method.48 Alfresco Enterprise Edition Version 3.2
  49. 49. Developing against the Alfresco RepositoryFor clarity, not all of the available methods are shown. For a complete description, pleaseconsult the Javadocs: • Interface FileFolderService • Interface FileInfo API Development Course 49
  50. 50. Developing against the Alfresco RepositoryJCR APIIntroduction The JCR API (Java Content Repository) specifies a standard, implementation independent API to access content repositories in Java. It is defined by the Java Specification Request (JSR) 170 as part of the Java Community Process (JCP). The official JSR-170 Specification can be found on the JCP web site at the following address: http://jcp.org/en/jsr/detail?id=170 Alfresco implements the JCR API against its own scalable repository and is actively contributing to the next version of JCR defined by the Java Specification Request (JSR) 283.JCR Compliance Levels The JSR 170 specification defines two compliance levels and a set of additional optional features which repositories of either level may support. Level 1 provides for read functions and includes: • Retrieval and traversal of nodes and properties • Reading the values of properties • Transient namespace remapping • Export to XML/SAX • Query facility with XPath syntax • Discovery of available node types • Discovery of access control permissions Level 2 adds additional write functions: • Adding and removing nodes and properties • Writing the values of properties • Persistent namespace changes • Import from XML/SAX • Assigning node types to nodes Optionally, any combination of the following features may be added to an implementation of either level: • Transactions • Versioning • Observation (Events) • Locking • SQL syntax for queryJCR Repository Model Like the Alfresco repository, a JCR repository consists of one or more workspaces, each of which contains a tree of items. An item is either a node or a property. Each node may have zero or more child nodes and zero or more child properties. There is a single root node per workspace, which has no parent. Unlike the Alfresco repository, all other nodes have only one parent. Properties have one parent (a node) and cannot have children; they are the leaves of the tree. All of the actual content in the repository is stored within the values of the properties.50 Alfresco Enterprise Edition Version 3.2

×