Obsolete Pages{{Obsolete}}
The official documentation is at: http://docs.alfresco.com
Alfresco provides a scalable WCM platform for developing enterprise Web Content Management (WCM) solutions. An Alfresco WCM architecture can vary in design depending upon requirments regarding performance, scalability, security and redundancy. The below diagrams show simplified views of both a single and a two-tier approach.
Single tier WCM architecture: With a single tier architecture, Alfresco provides both content editorial services as well as content delivery services from a single Alfresco installation.
alt=Single Tier WCM Architecture | WCM Architectures
Two-tier WCM Architecture: With a two-tier architecture, the editorial and delivery services are separated to use two Alfresco installations.
alt=Two Tier WCM Architecture | WCM Architectures
Web Quick Start is a sample application built on the Alfresco WCM platform. It provides an end-to-end WCM example including an authoring and publishing environment using Alfresco Share and a web application built using Spring MVC, Spring Surf and OpenCMIS. The web site is delivered dynamically using Alfresco as a CMIS runtime.
The primary design goals of the QS are to illustrate the power of the Alfresco WCM platform in an easy-to-install package and to provide developers with a strong starting point for their Alfresco implementations. Both of these goals are fundamentally aimed at getting both business people and developers up and running with the Alfresco WCM platform in as short a time as possible. The Alfresco core product has not been changed in any way, just extended by plugging in content model, behaviours, workflows, etc using the many standard hooks provided by the Alfresco product.
Web Quick Start consists of four parts:
The diagram below shows each of the QS components deployed in a single-tier architecture as described previously:
alt=WQS Architecture | WCM Architectures
Alfresco Share is the primary editorial tool (along with the Web Editor for in-context changes) for managing the Web Quick Start website. Using Share, content editors and web producers alike have the ability to manage and control a wide variety of features including (but not limited to) content items, sections, navigation, templates, renditions, workflow, UGC and tagging. It is important to note that the core Alfresco Share code has not been modified to support Web Quick Start, only extended.
Site Structure and content - Web Quick Start provides a sample site structure and content populating each of the website sections. This allows for full site functionality to be evaluated once installed.
Publishing Mechanism - Web Quick Start includes a workflow driven publishing mechanism that allows for a clean separation between the editorial content and the approved live content. The Editorial and Live sections are implemented as part of the default Document Library site structure.
Content Model - The content model used by the system is designed to be generic enough to let you build many website solutions. So just by understanding the web application and altering it for your requirements you can get a head start in creating your own content managed enterprise website
Workflow - Web Quick Start provides example workflows for review and approval of content.
Renditions - Web Quick Start makes use of the Alfresco Rendition Service and provides multiple examples of content transformations and resizing.
The Web Quick Start web application provides a richly-featured web application built using Spring MVC, Spring Surf and OpenCMIS. The web application can be used for both website preview (by the editorial team) and also for delivering the live website content.
The rendered website within the diagram simply represents the delivered site via a browser, viewable by the editorial team and website visitors alike, depending upon configuration.
The Web Quick Start (WQS) model is deliberately simple. A WQS website is made up of sections, assets, and asset collections. Sections are basically folders with additional metadata and behaviour, and assets are basically files with additional metadata and behaviour that are located inside sections. An asset collection is a named group of assets that is defined in a section. Each section may have zero or more asset collections. Each asset may have zero or more pieces of visitor feedback associated with it.
A website contains precisely one section that is the root of a tree of sections. Each website is configured with a host name, port number, and root context. These attributes correspond to the URL used to address the home page of the website:
http://hostname:portno/context/
As an example, the QS website comes preconfigured with a website named 'Quick Start Editorial' which has the following attributes when first loaded:
host name = localhost
port = 8080
context = wcmqs
which means that the site home page can be accessed at the URL 'http://localhost:8080/wcmqs/'. We'll use this URL in future examples throughout this guide.
It is possible configure websites so that one publishes to another. Each website may be associated with one other website that is its publishing target. Again, the QS comes with an example of this, with the Quick Start Editorial website pointing at the Quick Start Live website as its publishing target. The publishing mechanism is looked at in some detail later.
Finally, each website may have a list of configuration properties of the form 'propertyname=propertyvalue'. In the QS website there is just one property used: 'isEditorial'. If set to 'true' then the templates used to render the QS site will include the markup needed to launch the Alfresco Web Editor.
As mentioned above, a section is best thought of as a folder with additional metadata and behaviour. Each section is uniquely named within its parent section. Each website has one root section which is the only section whose parent is not another section. The name of a section is used to determine its URL at delivery time. So, for example, the 'blog' section in the QS website is located at 'http://localhost:8080/wcmqs/blog/'. If you rename it so that it is named 'blogs' instead, then its URL will change to be 'http://localhost:8080/wcmqs/blogs/'.
In addition to the normal metadata such as name, title, description, and so on, a section has a few other properties. One of these is used to configure template mappings. These determine which web template should be used to render a particular type of content in that section, and take the form of name/value pairs where the content type is the name and the template name is the value. So, for example, a setting of 'ws:article=articlepage2' means that the template named 'articlepage2' should be used to render content of type 'ws:article' in that section. The way in which template mappings are processed is described later.
Another attribute of a section worthy of note is the rendition configuration. On each section it is possible specify what renditions you want to create for assets that are placed in that section. For example, you may want to create a thumbnail version of any asset that has a MIME type of 'image/jpeg' or you may want to trigger that same thumbnail rendition for any asset of type 'Image'. Each rendition setting is, again, a name/value pair with the name being either a MIME type or a content type and the value being the name of the rendition definition to run. This mechanism is described fully in the rendition configuration section of this guide.
An asset is any piece of content that is placed in a section. An asset doesn't have very much 'special' metadata, but does contain summary information about visitor feedback that has been received for that asset such as the number of comments received and the average rating. This is described further in the section about processing visitor feedback. An asset may optionally specify a presentation template that is to be used when rendering it. If set, this overrides the template mappings set on its parent section. You can read about this in the section about how templates are resolved.
As the name suggests, an asset collection groups together a number of assets. Each asset collection is associated with a particular section and is uniquely named within that section. There are two general types of asset collection: 'dynamic' and 'static'. A dynamic asset collection is configured with a search query that is run periodically. The assets found by the query are placed in the collection. A static asset collection has no search query defined, and contains assets that are placed in it either manually or through some other automated mechanism.
In the case of a dynamic collection it is possible to specify the maximum number of assets it should contain and the interval between re-runs of its query. Dynamic asset collections are described in more detail later.
Visitor feedback is information that has been passed back through a rendered website into the repository. It may be used for numerous purposes, but in the Quick Start example it is used to record comments about an asset and requests from the 'Contact us' page. A piece of visitor feedback has a number of generally useful properties such as the name and email address of the person who submitted it, a text property for the message or comment, and an integer property that can be used for ratings. It is also possible to have different categories of visitor feedback.
Received visitor feedback is added into a Share data list and can be processed in different ways depending on its category. For example, the Quick Start processes comments about assets and 'contact us' requests differently. The way in which visitor feedback is processed is described in the section entitled 'Processing Visitor Feedback'.
The Alfresco data dictionary is extended by a new content model named ws:webSiteModel. The types and aspects defined in this model are used by Web Quick Start to represent different elements of the website. Some of the types in the model correspond directly to parts of the website itself, others are used solely to provide structure to data in the repository. The model is designed to be as generic as possible, so, although it is used to render a financial web site in the Web Quick Start, it can be used for many different web sites with the necessary changes being limited to the actual content itself. The website model is defined in wcmquickstartmodule/config/alfresco/module/org_alfresco_module_wcmquickstart/model/webSiteModel.xml. The model is bootstrapped into the Alfresco data dictionary using the context model-context.xml in the same directory. The following subsections describe the new types:-
The ws:website type is derived from the cm:folder type and represents a website. This type has properties that apply to an entire website, such as the host name, port, and context of the web application that delivers the website. In the Quick Start data in Alfresco Share, the folder at Documents/Alfresco Quick Start/Quick Start Editorial
is of this type. You can see the host name, port and context in the folder's metadata.
The ws:section type is derived from the cm:folder type and represents a section of a website. The website is modelled as a tree of sections. A section defines an element in the website navigation and can contain child sections and web assets, such as the section's landing page, articles, collections of articles, and images. In the Web Quick Start data in Alfresco Share, the Documents/Alfresco Quick Start/Quick Start Editorial/root/blog
folder is of this type.
The ws:webroot type is derived from the ws:section type and represents the root of a website's tree of sections. This type extends the section type so therefore a webroot folder *is* also a section. In the Web Quick Start data in Alfresco Share, the Documents/Alfresco Quick Start/Quick Start Editorial/root
folder is of this type.
The ws:webassetCollectionFolder type is derived from the cm:folder type and is used to hold asset collections. Each section folder has a webassetCollectionFolder below it named 'collections' in which all of that section's asset collections are placed. In the Web Quick Start data in Alfresco Share, the Documents/Alfresco Quick Start/Quick Start Editorial/root/blog/collections
folder is of this type.
The ws:webassetCollection type is derived from the cm:folder type and represents an asset collection. In the Web Quick Start data in Alfresco Share, the Documents/Alfresco Quick Start/Quick Start Editorial/root/blog/collections/latest.articles
folder is of this type.
The ws:indexPage type is derived from the cm:content type and represents an index page of a section (also known as the section's landing page). Each section has an index page. In the Web Quick Start data in Alfresco share, the Documents/Alfresco Quick Start/Quick Start Editorial/root/blog/index.html
asset is of this type.
The ws:article type is derived from the cm:content type and represents any piece of text-based content such as a news article or a blog post. The article type defines a few associations that allow an article to be linked with related articles and a couple of images. In the Web Quick Start data in Alfresco Share, the Documents/Alfresco Quick Start/Quick Start Editorial/root/blog/blog1.html
file is of this type.
The ws:image type is derived from the cm:content type and is used for general image assets. In the Web Quick Start data in Alfresco share, the Documents/Alfresco Quick Start/Quick Start Editorial/root/news/detail_img1.jpg
file is of this type. The images that can be associated with articles must be of this type.
The ws:visitorFeedback type is derived from the dl:dataListItem type and represents feedback that has been submitted by visitors to a website. The intention is for this type to be sufficiently generic to be useful for a number of different types of feedback including comments, reviews, ratings, and questions. Each website has a Share data list created for it into which items of visitor feedback are placed. When first installed, Quick Start does not have any visitor feedback. Submitting a comment to a blog post or a 'contact us' request from the website will create a node of this type in the repository.
The ws:visitorFeedbackSummary type is derived from the cm:cmobject type and is used to record summary information about visitor feedback received for a given asset such as the number of comments received and the average rating given.
The wsublishqueueentry type is derived from the cm:cmobject type and is used to record nodes that have been queued up for publishing.
The ws:webasset aspect is derived from the cm:titled aspect and is used to mark any piece of content that is addressable through a website.
Among other things, a web asset (a node with the ws:webasset aspect) has two multi-valued NodeRef properties (wsarentSections and ws:ancestorSections) that contain the identifier(s) of the section(s) in which the asset is placed and its ancestor sections. When an asset is created in, moved to, or removed from a section, these properties are updated to reflect the asset's new location. This is done to make certain kinds of common queries very fast.
Numerous custom behaviours are provided in the core Quick Start module. This section looks at each of them in turn, breaking them into groupings based on the type or aspect to which they apply.
The behaviours that have been defined for the ws:section type can be found in the class org.alfresco.module.org_alfresco_module_wcmquickstart.model.SectionType
. They relate to three primary events: when a section is created; when a child node is added into or removed from a section; and when the roll-up of tag usage in a section is updated.
The creation of a new section causes the automatic creation of its index page (of type ws:indexPage), its asset collection folder (of type ws:assetCollectionFolder), and a few default asset collections. When a new folder is created inside a section then that folder is automatically converted into a section. The set of default asset collections can be altered by overriding a bean with identifier 'wqsmodule_sectionAssetCollections'. By default, this bean looks like this:
<bean id='wqsmodule_sectionAssetCollections' class='java.util.ArrayList' >
<constructor-arg>
<list>
<bean class='org.alfresco.module.org_alfresco_module_wcmquickstart.model.AssetCollectionDefinition'>
<property name='name' value='latest.articles' />
<property name='title' value='Latest Articles' />
<property name='maxResults' value='3' />
<property name='queryType' value='alfrescoCmis' />
<property name='query'><value>SELECT d.* FROM cmis:document AS d JOIN ws:webasset AS wa ON d.cmis:objectId = wa.cmis:objectId WHERE d.cmis:objectTypeId='D:ws:article' AND in_tree(d, '%{section:.}') ORDER BY wa.ws:publishedTime DESC</value></property>
</bean>
<bean class='org.alfresco.module.org_alfresco_module_wcmquickstart.model.AssetCollectionDefinition'>
<property name='name' value='section.articles' />
<property name='title' value='Articles' />
<property name='queryType' value='alfrescoCmis' />
<property name='query'><value>SELECT d.* FROM cmis:document AS d JOIN ws:webasset AS wa ON d.cmis:objectId = wa.cmis:objectId WHERE d.cmis:objectTypeId='D:ws:article' AND in_tree(d, '%{section:.}') ORDER BY wa.ws:publishedTime DESC</value></property>
</bean>
<bean class='org.alfresco.module.org_alfresco_module_wcmquickstart.model.AssetCollectionDefinition'>
<property name='name' value='featured.articles' />
<property name='title' value='Featured Articles' />
</bean>
</list>
</constructor-arg>
</bean>
This means that each new section is automatically endowed with two dynamic asset collections ('latest.articles' and 'section.articles') and one static asset collection ('featured.articles'). Note that in this configuration the 'queryType' of a dynamic asset collection may be either 'alfrescoCmis' (the default) or 'lucene'.
When a file is created in a section then one of four things happen. If the file is an image (as determined by its MIME type) then the file is given the ws:image type and marked as a web asset. If the file is text-based (again, as determined by its MIME type) then it is given the ws:article type and marked as a web asset. If the file is neither an image nor an article then it is simply marked as a web asset. It is possible to configure a set of content types that are ignored by this processing by overriding a Spring bean with the id 'wqsmodule_sectionTypesToIgnore'. By default, this bean looks like this:
<bean id='wqsmodule_sectionTypesToIgnore' class='java.util.TreeSet'>
<constructor-arg>
<set>
<value>ws:visitorFeedback</value>
<value>ws:indexPage</value>
</set>
</constructor-arg>
</bean>
You may replace it with another bean with the same identifier and add the types you'd like to be ignored. Please keep the types from the default configuration. Note that the ignoring mechanism only ignores the specific types listed in this bean - it does not cascade down the type hierarchy.
The behaviours that have been defined for the ws:webasset aspect can be found in the class org.alfresco.module.org_alfresco_module_wcmquickstart.model.WebAssetAspect
. There are four main behaviours associated with this aspect: onCopyNode; onContentUpdate; and beforeDeleteNode.
As mentioned earlier, an asset keeps a record of which sections it's in. When an asset is copied, however, we want to ensure that the copy recalculates its parent sections. Therefore a behaviour is hooked into the onCopyNode policy that ensures the wsarentSections property of the copied node is not taken across to the copy.
Assets often have renditions associated with them, and Quick Start provides a hierarchical configuration mechanism to determine what renditions should be generated for certain assets in given sections. This configuration is processed whenever an asset is created or has its content updated via behaviours hooked into the onContentUpdate and onAddAspect policies.
Finally, when an asset is deleted, a behaviour is invoked that causes the deletion to be queued up for publishing. This means that, in Quick Start, a deletion of an asset in the editorial system is quickly reproduced on the live system - a deletion is not subject to workflow.
When visitor feedback is received it may contain the identifier of an asset to which it relates. This is stored as a NodeRef property initially, but a behaviour is used to translate this property into an association. This behaviour is defined in the class org.alfresco.module.org_alfresco_module_wcmquickstart.model.VisitorFeedbackType
When the properties on a visitorFeedbackSummary node change then a behaviour that is hooked into the onUpdateProperties policy cause the summarised comment count and average rating to be copied onto the asset to which the summary is related. This behaviour is defined in the class org.alfresco.module.org_alfresco_module_wcmquickstart.model.VisitorFeedbackSummaryType
All assets are decorated with the cm:taggable aspect (cm:taggable is a mandatory aspect of the ws:webasset aspect). The tags set on a taggable node are normally stored as a multi-value NodeRef property, but a behaviour (in the class org.alfresco.module.org_alfresco_module_wcmquickstart.model.TaggableAspect
) copies the tag values into a multi-value text property (ws:tags) which is then used for tag-based queries. This behaviour is hooked into the onUpdateProperties policy.
All sections are decorated with the cm:tagscope aspect which is used to automatically 'roll up' a summary of which tags have been applied to assets in that section and its subsections. The tagscope aspect uses a content property to hold the summary information which makes it difficult to get hold of through CMIS. A behaviour hooked onto the onContentPropertyUpdate policy on this aspect copies the information into a couple of multi-value properties (one for the tag value and another for the tag count). This behaviour can be found in the class org.alfresco.module.org_alfresco_module_wcmquickstart.model.TagScopeAspect
Any asset collection that has a search query defined on it is referred to as a dynamic asset collection. Periodically (as defined by the refresh interval on the asset collection) this search query is executed in the background and the resulting assets are bound into the asset collection.
The search query may use either Lucene or CMIS query languages, and may contain a special placeholder that is automatically replaced by a section identifier prior to executing. This placeholder takes the form ${section:<arg>} where <arg> may be any of the following:
It is also possible to chain these together to form a complete path. For example ${section:/news/./global/../companies} would resolve to the identifier of the section '/news/companies'.
Several classes are provided that do work at scheduled times. These classes can all be found in the org.alfresco.module.org_alfresco_module_wcmquickstart.jobs package, and provide processing of publishing queues, visitor feedback, and dynamic asset collections. Each of the classes has a scheduled time at which it will run, specified as a cron expression in the WQS properties file. The Spring context file for all the scheduled job classes is config/alfresco/module/org_alfresco_module_wcmquickstart/job-context.xml.
Articles are placed on a website's publishing queue when they have gone through the approval workflow, or on deletion. The PublishQueueProcessor class is responsible for processing all websites' publishing queues. It runs periodically, by default every minute, and publishes any nodes found in each publishing queue to the target website. The property used to control this schedule is 'wcmqs.publishQueueProcessor.schedule'. Its default value is '0 0/1 * * * ?'.
Each item of visitor feedback may be related to a particular web asset. Each web asset for which there is any visitor feedback is 'stamped' with summary information such as the total number of comments received and the average rating given. The FeedbackProcessor class finds any visitor feedback that has not been processed yet, and incorporates it into the summary information for each asset. It runs periodically, by default every 30 seconds. The property used to control this schedule is 'wcmqs.feedbackProcessor.schedule'. Its default value is '0/30 * * * * ?'.
The summary information for an asset is not held directly on the asset, instead it is held in a separate summary node. This is because an asset is typically published from the editorial site to the live site. On each site visitors will create feedback items. There may be 2 or 3 test feedback comments for an asset on the editorial site, but several thousand feedback comments for the same asset on the live site. When the asset is re-published from the editorial site to the live site, the whole asset is replaced. If the summary statistics were part of the asset, the live summary statistics would be incorrectly replaced by the test summary statistics. Holding the statistics in a separate, unpublished node removes the problem by making the summary statistics for an asset site-specific.
Each item of visitor feedback is typed. The type is simply recorded in a text property (ws:feedbackType), and can have any value that you wish. Out of the box, the Web Quick Start uses two types of visitor feedback: 'Comment' and 'Contact Request'. Each different type of visitor feedback may have a handler configured that knows what to do with it. When the feedback processor finds an unprocessed item, it looks at its type and passes processing off to the appropriate handler. Adding a handler for a new type of feedback can be done by creating a class that extends the abstract class 'org.alfresco.module.org_alfresco_module_wcmquickstart.jobs.feedback.FeedbackProcessorHandlerBase' and overriding the processorCallback method. An example of a handler is as follows:
<bean id='commentFeedbackProcessorHandler' parent='feedbackProcessorHandler'
class='org.alfresco.module.org_alfresco_module_wcmquickstart.jobs.feedback.CommentFeedbackProcessorHandler'>
<property name='feedbackType' value='Comment' />
</bean>
The important parts of this are specifying the parent 'feedbackProcessorHandler' and setting the feedbackType property to match the type of feedback that the handler knows how to handle.
Each dynamic asset collection has a 'Minutes To Query Refresh' property that is set in the asset collection's metadata. The DynamicCollectionProcessor class is responsible for refreshing dynamic collections. It runs periodically, by default every minute, and iterates over all the dynamic asset collections. For each one that is due to be refreshed it executes the configured query, refreshes the asset collection with the results, and updates the time at which that asset collection should next be refreshed using the configured 'minutes to refresh' property. The property used to control the schedule for this processing is 'wcmqs.dynamicCollectionProcessor.schedule'. Its default value is '0 0/1 * * * ?'.
Each section in a Web Quick Start site may optionally specify which presentation template should be used for which type of content in that section. This information is stored as a multi-value text property on a section ('ws:sectionConfig') and each value takes the form of 'my:typename=MyTemplateName'. In the Web Quick Start webapp (which uses Spring Surf) the template name is the name of the Surf page, but it could be something else if you've built your webapp using a different framework (the name of a JSP, for example).
To take an example, at the time of writing (8/Nov/2010) the blog section has the following template mappings defined:
ws:indexPage=sectionpage2,ws:article=articlepage2
This means that an asset of type ws:indexPage in this section (the landing page) will use the template called 'sectionpage2' and an asset of type 'ws:article' will use the template called 'articlepage2'. Naturally, you will almost certainly have different templates and types in your implementation - just change the mappings to suit your needs.
The Alfresco Rendition Service is used throughout Web Quick Start to reformat content dynamically for the web. It is used for resizing images, producing flash previews of pdf documents, and producing PDF renditions of business documents.
The set of renditions that Web Quick Start uses is configured in the Spring file config/alfresco/module/org_alfresco_module_wcmquickstart/bootstrap/rendition-context.xml. Each definition specifies the rendering engine, and the parameters and values to be used when creating the rendition definitions. You can find a table of the default Web Quick Start rendition definitions in the Reference section below. You are likely to want to change the rendition definitions available for your website, and this can be done by overriding the Spring bean with the identifier 'wqsmodule_renditionDefinitions'. This is simply an ArrayList of rendition definitions. A truncated version of the default configuration is as follows:
<bean id='wqsmodule_renditionDefinitions' class='java.util.ArrayList'>
<constructor-arg>
<list>
<bean class='org.alfresco.module.org_alfresco_module_wcmquickstart.rendition.BootstrapCompositeRenditionDefinition'>
<property name='name' value='smallThumbnail'/>
<property name='renderingEngineName' value='compositeRenderingEngine'/>
<property name='definitions'>
<list>
<bean class='org.alfresco.module.org_alfresco_module_wcmquickstart.rendition.BootstrapRenditionDefinition'>
<property name='renderingEngineName' value='reformat'/>
<property name='parameters'>
<map>
<entry key='mime-type' value='image/jpeg'/>
<entry key='runAs' value='System'/>
</map>
</property>
</bean>
<bean class='org.alfresco.module.org_alfresco_module_wcmquickstart.rendition.BootstrapRenditionDefinition'>
<property name='renderingEngineName' value='imageRenderingEngine'/>
<property name='parameters'>
<map>
<entry key='xsize' value='72'/>
<entry key='ysize' value='72'/>
<entry key='maintainAspectRatio' value='false'/>
<entry key='runAs' value='System'/>
</map>
</property>
</bean>
</list>
</property>
</bean>
<!-- ....other rendition definitions are configured here.... -->
</list>
</constructor-arg>
</bean>
The example shown above creates a rendition definition named 'smallThumbnail' (which will be placed in the 'ws' namespace). This is a composite rendition that first transforms the image to the JPEG format and then resizes it to be 72x72 pixels.
Web Quick Start maps a content type or mime type to one or more rendition definitions. The mapping is specified in a section's Rendition Config metadata. A section can have its own list of mappings, or can inherit the parent section's mappings, or have no rendition mappings. For example, when the Web Quick Start web site data is loaded, the root section has the following mappings:
ws:image=ws:smallThumbnail,ws:image=ws:imagePreview,application/pdf=ws:swfPreview
So in the root section, or a descendant section that inherits its rendition config from the root section, any asset of type 'ws:image' will have two renditions generated ('ws:smallThumbnail' and 'ws:imagePreview'), and any asset with the 'application/pdf' MIME type will have a Flash preview rendition generated (the 'ws:swfPreview' rendition).
As described in Behaviours, the processing of renditions is governed by Alfresco behaviours.
Whenever a web asset is created or has its content updated the appropriate renditions for that type of asset are recreated by behaviours hooked into the onContentUpdate and onAddAspect policies (in the WebAssetAspect class).
The Quick Start API provides a client application with a means of interacting with the Quick Start model held in an Alfresco repository. It is used by the Quick Start webapp.
If you obtain the source code from Alfresco's Subversion repository, the Quick Start API project is located in the folder code/root/modules/wcmquickstart/wcmquickstartclientapi
. It can be built from the code/root
folder using the package-wcmquickstart-clientapi
ant target:
ant package-wcmquickstart-clientapi
The result of this is a JAR file named 'alfresco-wcmqs-clientapi-x.y.z.jar' in the project's 'build/dist' folder.
This JAR file contains everything necessary to expose the Quick Start model to client applications such as the Quick Start webapp. At the time of writing (22/Sep/2010), this JAR file has the following dependencies:
chemistry-opencmis-client-api-0.1.0-incubating-SNAPSHOT.jar
chemistry-opencmis-client-bindings-0.1.0-incubating-SNAPSHOT.jar
chemistry-opencmis-client-impl-0.1.0-incubating-SNAPSHOT.jar
chemistry-opencmis-commons-api-0.1.0-incubating-SNAPSHOT.jar
chemistry-opencmis-commons-impl-0.1.0-incubating-SNAPSHOT.jar
commons-codec-1.3.jar
commons-collections-3.1.jar
commons-httpclient-3.1.jar
commons-logging-1.1.jar
commons-pool-1.4.jar
ehcache-core-2.0.0.jar
json.jar
org.springframework.aop-3.0.0.jar
org.springframework.asm-3.0.0.jar
org.springframework.beans-3.0.0.jar
org.springframework.context-3.0.0.jar
org.springframework.context.support-3.0.0.jar
org.springframework.core-3.0.0.jar
org.springframework.expression-3.0.0.jar
org.springframework.jdbc-3.0.0.jar
org.springframework.orm-3.0.0.jar
org.springframework.transaction-3.0.0.jar
slf4j-api-1.5.11.jar
slf4j-log4j12-1.5.11.jar
log4j-1.2.15.jar
All of these dependencies can be found in the Alfresco '3rd Party' project, or, in the case of the OpenCMIS libraries, in the Quick Start Client API project itself.
There is a single properties file that contains a few properties that are used to configure the API. This file is named 'wcmqs-api.properties'. The default file is located in the clientapi JAR file (in the 'alfresco' folder), but can be overridden by placing a file with the same name on the classpath before the clientapi JAR. For example, if you're using the WQS API from within a JEE webapp then place a file named 'wcmqs-api.properties' in the folder 'WEB-INF/classes/alfresco/'.
The properties that are contained by this file are:
Changes in 3.4.b Community: Note that, from 3.4.b onwards, it is possible to override individual properties by placing them in a file named 'wqsapi-custom.properties' located on the classpath in a directory '/alfresco/extension/' (under '/shared/classes/' in a Tomcat installation, for example). There are also three additional properties available:
The API is wired together with a Spring application context that is embedded in the JAR file at the location '/alfresco/wcmqs-api-context.xml'. If the API is being used inside a Surf application then this context file will be automatically bootstrapped on start up, otherwise you will have to load it up yourself.
In the following subsections we'll take a look at the main interfaces that you'll interact with as a user of the API. Later we'll dive under the covers and look at some of the classes that do the actual work.
The starting point for most applications that use the Quick Start API will be the Website Service. This is represented by the abstract class org.alfresco.wcm.client.WebSiteService
, an instance of which is defined in the Spring context file with the id 'webSiteService'. The website service has only a few operations defined, one returning a collection of all the websites that have been configured in the repository and another returning a specific website based on host name and port number.
A website is represented by an object with the interface org.alfresco.wcm.client.WebSite
. This gives read access to the properties of a website as well as providing operations to retrieve assets and sections given a path. For example:
WebSite website = websiteService.getWebSite('localhost', 8080);
Section blogSection = website.getSectionByPath('/blog/blog1.html');
Asset blogPost1 = website.getAssetByPath('/blog/blog1.html');
The website service also gives access to another service which is described a little later: the UGC (user-generated content) Service.
As you would expect, an object that implements the Section interface represents a section of a website. It provides a number of operations that give access to child sections (getSections, getSection) and assets (getAsset, getIndexPage), as well as configuration settings on the section (getTemplateMappings, getExcludeFromNav). It also offers access to search functionality with a few flavours of 'search' operations:
SearchResults search(Query query);
SearchResults search(String phrase, int maxResults, int resultsToSkip);
SearchResults searchByTag(String tag, int maxResults, int resultsToSkip);
Query createQuery();
Results from these searches are returned wrapped in a SearchResults object that exposes a list of the actual results, the Query that was executed to obtain the results, and the total number of results. Each result is represented as an object of type SearchResult. This is an interface that extends the Asset interface (each search result represents an asset) and adds the search score as a readable property.
In 3.4.b and beyond it is also possible to access the asset collections that are defined on a section through the getAssetCollection operation on the Section interface.
Objects with the Asset interface are used to represent Quick Start assets. This interface exposes operations to read the asset's properties and to discover any related assets and renditions that it may have. It's worth pointing out that both relationships and renditions are named, so the operations that provide access to them allow the caller to select by name.
Another operation provided on any asset is 'getTemplate'. This does a calculation based on the asset's type and the template mappings defined on the section it's in to work out which template should be used to render it.
Currently, asset collections are accessed through the asset collection factory which is represented by an object exposing the org.alfresco.wcm.client.CollectionFactory
interface. There is an asset collection factory bean defined in the Spring application context with the id 'collectionFactory'. In 3.4.b and beyond, asset collections can be accessed from the Section interface - 'Section.getAssetCollection(String)'
The CollectionFactory interface is a very simple one with just two operations currently (23/Sep/2010). One operation returns an entire asset collection given the section identifier and asset collection name, and the other provides the ability to retrieve just a portion of the identified asset collection by specifying the maximum number of assets to return and the number of assets to skip over. Both return an object with the AssetCollection interface.
The AssetCollection interface provides access to the underlying list of assets as well as the properties of the asset collection itself such as its name, title, and description.
The Web Quick Start API provides a balance of editorial control against speed of content delivery by keeping the data needed to render web pages local to the web app. This massively reduces the load placed on the repository and enables very fast dynamic page rendering.
There are four different caches provided by the WQS API which are described here.
Each website held in the Alfresco repository has its own hierarchy of sections and assets. A single repository may hold many different websites, and a single WQS web application can be used to deliver any number of those websites. The website cache enables the fast lookup of which website hierarchy is relevant for a given HTTP request along with configuration settings for that website (whether it is an editorial site or not, for example). Generally, the websites don't change very frequently, so this cache is configured to refresh every five minutes. This interval can be adjusted with the configuration property 'wcmqs.api.websiteCacheSeconds'.
Once the website has been looked up in the website cache the next job is to resolve the section that is being addressed. This also needs to be extremely fast, so the section hierarchy is also held in memory by the API. As well as providing very fast resolution of the requested path to the appropriate section and asset in that section, this cache is also used to quickly determine which template is to be used to render the page. The section hierarchy doesn't change very often in a website either - this cache is configured to refresh every 60 seconds by default. This setting can be changed with the property 'wcmqs.api.sectionCacheSeconds'.
Asset collections are intended to provide very fast delivery of arbitrary lists of assets - a very common feature of any website. Most coupled or 'fried' web delivery systems carry out queries against the repository at request time to provide this kind of capability, and this seriously impacts on their ability to perform well under load. With asset collections, Web Quick Start removes this overhead and enables these user-defined asset lists to be efficiently cached in the web tier. The asset collection cache is implemented as a caching proxy over the asset collection factory in the API.
For a dynamic asset collection the cache uses knowledge about when the asset collection was last refreshed and the frequency at which it is refreshed to make intelligent decisions about when to check the repository for any updates. For example, if a dynamic asset collection is configured to be refreshed every 15 minutes and the copy that was last loaded from the repository was refreshed at 10:15 then the API will not ask the repository for that asset collection again until 10:30.
For a static asset collection the cache periodically checks the modified time in the repository and only reloads the asset collection when it changes.
The asset cache is similar to the asset collection cache and holds properties and associations for each asset that is accessed through the API. An asset in the cache is refreshed only when the asset is found to have changed in the repository (by checking its modified time periodically).
When the content of an asset is read for the first time the content stream is also cached in a temporary file store in the web tier. This, again, helps reduce the load on the repository and means that a web app built using the WQS API typically delivers most of its content either from memory or from local disk.
As mentioned before, each section may define mappings between content types and presentation templates. For example, if you want content of type 'ws:article' in a given section to be rendered using a template named 'articlepage1' then you would specify a template mapping on that section like this: ws:article=articlepage1. Additionally, each asset may have a template explicitly specified for it. In this case, just the template name is specified: 'articlepage1'. If a template is specified on the asset itself then it will be used in preference to any template mappings that are set on its parent sections, and the rest of the description here is not relevant.
It's important to understand how the section template mappings are processed by the WQS API. For the sake of this example we shall assume that there is a section structure 'root/news/global' and a type hierarchy 'cm:content' -> 'ws:article' -> 'myappressrelease'. We shall also assume the following template mappings have been defined:
root: cm:content=generalpage, myappressrelease=pressreleasepage
news: ws:article=articlepage
global: myapp:blogpost=blogpage
Now let's take an example of a press release being requested from the 'global' section. First we look up the type hierarchy to see if we can find a match on the current section. Since myappressrelease is not derived from myapp:blogpost, there is no suitable match found. We therefore move up to the news section and try looking up the type hierarchy again. myappressrelease is derived from ws:article, so we find a match and return the template name 'articlepage'. So the process is: look up the type hierarchy on the current section first; if no match is found move to the parent section and then look up the type hierarchy again there; repeat until the root section has been processed.
The Quick Start web application is a Spring Surf application, and as such uses the extremely popular Spring MVC framework. In this section we'll take a look at how the webapp works and how it's wired together.
Having checked out the source code from the Alfresco Subversion repository, you can find the source code for the Quick Start webapp in the folder 'root/modules/wcmquickstart/wcmquickstartwebsite'. Any references to source file locations in this section assume this as the starting point.
Often when examining a Spring-based application the hardest part is working out where and how all the wiring takes place. This section takes a look at the Quick Start webapp from this point of view.
The starting point is the web.xml file ('source/web/WEB-INF/web.xml' in the source). This is a fairly short file, and the part that we'll concentrate on right now is the part that kicks off all the Spring magic: the dispatcher servlet.
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/web-application-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
This DispatcherServlet object loads up a Spring application context using the referenced configuration file: '/WEB-INF/classes/web-application-config.xml'. This file can be found in the config folder in the source, and just causes two other Spring configuration files to be loaded: 'surf-config.xml' first and then 'wcmqs-webapp-context.xml'
The first of these ('config/surf-config.xml') loads up the Spring Surf and Spring Webscripts extensions, and then configures a default request handler:
<bean id='handlerMappings' parent='webframeworkHandlerMappings'>
<property name='order' value='2' />
<property name='interceptors'>
<list>
<ref bean='requestContextInterceptor'/>
<ref bean='cmisSessionInterceptor'/>
<ref bean='applicationDataInterceptor'/>
</list>
</property>
<property name='defaultHandler'>
<bean class='org.alfresco.wcm.client.controller.GenericTemplateAssetController'>
<property name='staticPages'>
<set>
<value>\/messages\.js</value>
</set>
</property>
</bean>
</property>
</bean>
This creates an instance of the class 'org.alfresco.wcm.client.controller.GenericTemplateAssetController', which is a Spring MVC controller, and also puts in place three interceptors that Spring will invoke prior to passing a request to the controller. The first of these, 'requestContextInterceptor' is a Spring Surf object that is necessary when using Surf as a Spring view resolver. The next two, 'cmisSessionInterceptor' and 'applicationDataInterceptor' are beans that are defined by Quick Start in the file 'wcmqs-webapp-context.xml' which we'll look at in greater detail later. The cmisSessionInterceptor ensures that there is a CMIS session available throughout the processing of the request (accessible through the CmisSessionHelper class), and the applicationDataInterceptor uses the requested host name, port number, and path to obtain the appropriate website, section, and asset from the Quick Start API. It then places these resolved objects onto the request context with the names 'webSite', 'section', and 'asset' so that they can be used while processing the request. (Note: from 3.4.b onwards, the resolved WebSite object is placed on the request context with two names: 'webSite' (as before) and 'website')
The other Spring context file ('wcmqs-webapp-context.xml') is used to wire together everything else. There are numerous objects defined in this file, but the most important ones are the three other controllers (asset, search, and rss), the dynamic page view resolver (used to work out which template to use for a given request), the interceptors mentioned earlier, and a 'model decorator' which is used to inject Freemarker directives into the model that are then available to FreeMarker templates.
There are four Spring controllers configured in the Web Quick Start webapp. In this section we'll look at each in turn.
This is the default controller. It actually doesn't do very much - the only important thing is that it redirects a request for a resource named 'index.html' to its parent section (so '/news/global/index.html' is redirected to '/news/global/'). More important are the interceptors that are configured to sit in front of this controller. These have been described in the previous section.
The streamed asset controller is configured to handle all requests that are addressed at a URI with the pattern '/asset/**'. The structure of the expected URI is '/asset/uuid/filename' where the UUID is the id of the asset being requested and the (optional) filename is the name of the asset being requested. This controller is useful if you want to generate 'perma-links' for assets, since the URLs will not change even if the asset moves (assuming you omit the filename). It's also useful if you have the identifier for an asset, but you don't know where it is located. Search results may be one example of this.
If the addressed asset can be rendered through a template then this controller will make that happen, otherwise it will stream the asset content back 'raw' to the browser. The controller will look for a request parameter named 'rendition' and, if present, will resolve and stream back the named rendition of the specified asset.
This controller is used to process the search form, execute the query against the repository, and place the results on the model ready to be rendered. This controller is an example that makes use of Spring annotations, and is configured to respond to requests for '/search.html'.
The RSS controller is used to handle requests for RSS format information. It is also mapped using annotations, and handles requests for any URI that ends '/rss.xml'. This controller is particularly simple in that all it does is specify which page view should be used ('rssfeed').
This interceptor has been mentioned earlier, but it's worth describing in a little more detail. It is configured to sit in front of all of the controllers apart from the StreamedAssetController, and is responsible for resolving the requested URL into the WebSite, Section, and Asset objects that are being addressed. It does this simply by making calls into the WQS API (WebSiteService and WebSite), and it places the objects that it finds onto the servlet request context with the names 'webSite', 'section', and 'asset'. You can find more information about the process of resolving these objects in the Request Handling section.
Once it's done that it also takes responsibility for injecting those three objects in addition to some others onto the model that is returned from the underlying controller. It does this by delegating to a utility class named 'ModelDecorator'. The other objects that are placed in the model are:
There are six Freemarker directives included in the WQS webapp currently (11/Nov/2010). These are configured and injected into the ModelDecorator from the wcmqs-webapp-context.xml file, and are described in this section.
This directive is an instance of the class 'org.alfresco.wcm.client.directive.AssetDirective'. It takes a single parameter ('asset' of type Asset), and streams the content of that asset to the servlet writer. The content comes from the asset's cm:content property. A simple example of its use can be seen in the 'content/current' component (file: 'current.get.html.ftl'):
This directive is an instance of the class 'org.alfresco.wcm.client.directive.UrlDirective'. It takes a few parameters: 'asset' of type Asset; 'section' of type Section; 'rendition' of type String; 'force' of type String. One or other of 'asset' and 'section' must be supplied (asset wins if both are supplied), and both 'force' and 'rendition' are optional and are ignored if 'asset' is not supplied. 'force' must have the value of either 'long' or 'short', if it's specified at all.
The directive is used to output the URL of the specified asset or section. There are two kinds of URLs that can be generated for an asset: 'long' and 'short'. A long URL gives the full path to the asset whereas as the short URL uses the asset's UUID. Effectively, short URLs are less friendly (both to humans and search engines) but are less prone to change when the asset changes (if it's moved, for example). The 'rendition' parameter allows the caller to specify the name of a rendition that is to be addressed. For example, the wide list component ('list/wide') uses the makeurl directive to address the asset's small thumbnail and to link to the relevant article:
</a>
This directive is an instance of the class 'org.alfresco.wcm.client.directive.TruncateDirective'. It requires two parameters: 'value' of type String; 'chars' of type Integer. It writes the supplied String value out to the servlet writer, truncating it to be no longer than the number of characters specified by the 'chars' parameter. It appends an ellipsis ('...') to the output. An example of this directive being used can be seen in the 'list/narrow' component:
This directive is an instance of the class 'org.alfresco.wcm.client.directive.WebEditorStartTemplateDirective'. It accepts one parameter named 'toolbarLocation' of type String that may have one of the following values: 'top', 'left', or 'right'. 'top' is the default.
The purpose of this directive is to inject a reference to the Alfresco Web Editor bootstrap script. It's used in templates that render content that is to be editable with the Web Editor. In the Web Quick Start we enable this functionality in any page that uses either the 'article/style1' or the 'article/style2' components. For example, the file 'style2.get.head.ftl' (note the head) contains this single line:
This directive is an instance of the class 'org.alfresco.wcm.client.directive.WebEditorStartTemplateDirective'. It accepts up to four paramaters: 'id' of type String; 'title' of type String; 'formId' of type String; and 'nestedMarker' of type String. Its purpose is to mark the location of a piece of content so that it can be edited using the Alfresco Web Editor.
'id' is mandatory and is the identifier of the asset that is being marked as editable. 'title' is optional, and is used to override the content title that is displayed by the Web Editor. 'formId' is optional and is used to specify which Alfresco form should be used by the Web Editor when editing the marked content. 'nestedMarker' is optional and, if set to 'true', indicates that the content being marked is contained by the 'parent' tag of the marker.
An example of this being used can be found in the 'article/style1' component:
This directive is an instance of the class 'org.alfresco.wcm.client.directive.WebEditorEndTemplateDirective'. It accepts no parameters. This directive is used together with the startTemplate and markContent directives to provide the information needed by the Alfresco Web Editor. It is typically used immediately before closing the body tag on the rendered HTML page. Its usage is very simple:
A request to a URL such as 'http://my.example.com:8080/wcmqs/blogs/brian/a_great_blog_post.html' is broken down and used as follows:
If either the section or the asset cannot be found then a 404 error page is returned to the browser.
The webapp was created as a spring surf application, but has changes to allow it to work with the URL handling described above.
A default Spring Surf project created using Spring Roo creates has the the following configuration files :-
To support the required handling of URLs in wcmqs, the handler mappings have the following changes from the default :-
Other features of the web application that are involved in URL handling are detailed below :-
The Web Quick Start Web application, wcmqs contains the following packages :-
The webscripts that fetch web assets, such as the navigation menu, need application-wide data available on every page, for example the site structure data. The set of webscripts that fetch data for parts of one page share a common need for data which corresponds to the page as a whole, for example an article.html asset. To make this type of data available across the request, a Spring HandlerAdapterInterceptor has been used, ApplicationDataInterceptor. This loads the website, section and asset objects into the Surf RequestContext and the Spring Model.
The UrlUtilsImpl handles getting a URL for an asset, extracting an asset id from a URL, and other URL specific functions. The mapping of a URL safe object Id to an Alfresco uuid is delegated to an Alfresco specific class called AlfrescoCmisUrlEncoderImpl. This removes the prefix workspace://SpacesStore/ to create a URI friendly uuid.
Since Roo was used to create the default Spring Surf project , two log4j configuration files are created, src/main/resources/META-INF/spring/log4j.properties and src/main/webapp/WEB-INF/classes/log4j.xml. Only the second of these is used by the application, so any changes you make need be applied there.
Spring Surf a scriptable, content-oriented framework for defining pages, templates, components and layout of a web application. It takes care of a lot of the detail of creating a Spring MVC application for you. The Spring Surf Tutorial shows you how to get a web application built and running quickly, and explains the standard layout of a Spring Surf application. The wcmqs webapp conforms to the standard spring surf layout, so if you look at the project folder wcmquickstartwebapp/src/main/webapp/WEB-INF, you will see the following layout:-
500page.html
chrome/
classes/
common/
config/
dtd/
lib/
pages/
surf.xml
templates/
urlrewrite.xml
web.xml
webscripts/
You can see an outline of what these files and folders contain in the Spring Surf Tutorial, but in particular the folders pages, templates, webscripts, and config are useful to explore in this webapp.
Surf provides tools to create the view composition part of a Spring MVC framework application. The Surf model lets you define pages, templates, components and more. Each of the definitions is a simple xml file.
The wcmqs webapp uses several page layout definitions, which can be seen, not surprisingly in the pages folder.
404page.xml
articlepage1.xml
articlepage2.xml
errorpage.xml
homepage.xml
publicationpage1.xml
search.xml
sectionpage1.xml
sectionpage2.xml
sectionpage3.xml
sectionpage4.xml
Spring Surf regards a page as a navigable html page in your web application. A page can have associations to other pages defined in your application. A page can have one or more formats defined by tempates. A page can have regions bound to zero or more components, which define the page layout.
If you have installed and played with Web Quick Start and viewed the website, try opening some of these files. You will probably recognise some of of the page structures. For example, if you look at the sectionpage1.xml file :-
<page>
<id>sectionpage1</id>
<title>sectionpage1</title>
<template-instance>two-block</template-instance>
<authentication>none</authentication>
<components>
<component>
<region-id>left1</region-id>
<url>/list/twocolumn</url>
<properties>
<collection>featured.articles</collection>
</properties>
</component>
<component>
<region-id>right1</region-id>
<url>/list/links</url>
<properties>
<collection>section.articles</collection>
</properties>
</component>
</components>
</page>
In this example, the page sectionpage1 associates itself to a template managed by the template-instance two-block, and consists of two components, one bound to a region called left1, and one to the region right1.
A Spring Surf component associates a region with a webscript. The component right1 contains a url /list/links which is the path of the webscript that models the data for this region. The path is relative to the webscripts directory.
To understand the properties tag in the above xml file, it is necessary to know a little of how the Web Quick Start Model is constructed:-
The website is modelled by a Website object which contains the website's title, the hostname and port that the wcmqs website is listening on , and other data related to the website as a whole. The website content is modelled as a tree of Sections anchored by a root section, A section contains Assets. Assets can be child sections, or singular items of content, or items of content grouped in ordered or unordered Collections. This is not a complete list of the object types, but is enough to understand the above Page definition.
The xml file defines a new Surf property called collection to contain grouped content.
So as its name suggests, sectionpage1 describes a page displaying a section of news articles, which are organised in two Collections, a collection of featured articles in the left region of the page, and a collection of other news articles in the right region.
In the wcmqs webapp, pages are designed to be as generic as possible. Instead of a page for every named section, various styles of page such as 'sectionpage1.xml' have been defined. Using standard collection names such as 'section.articles' and 'featured.articles' allows page to be re-used for various sections of the website, and allows pages to be the central place for defining what data should be displayed, and how it should be rendered.
Spring Surf templates are transformers that generate html for the browser to render. If you look in the templates folder, you can see there are two files that make up the template. There is an xml template instance configuration file, and the template itself, an ftl file which is a FreeMarker template. So the wcmqs webapp templates folder contains the following files:-
404page.ftl
404page.xml
errorpage.ftl
errorpage.xml
one-block.ftl
one-block.xml
searchpage.ftl
searchpage.xml
sprint1.ftl
sprint1.xml
three-block.ftl
three-block.xml
two-block.ftl
two-block.xml
Some templates are designed to be generic. For example :-
These templates have multiple regions in each div, for example 'right1', 'right2', 'right3', so that pages can define one or more components for an area of the page.
The template instance is the configuration file for the template itself. The template receives all the properties of the template instance, and the template can uses them to influence its final rendering. A single template can render differently depending on its configuration file. In the wcmqs webapp there is just a single configuration file for each template file. So if you look at the template-instance file specified by the sectionpage1, which is two-block.xml it contains the following xml :-
<template-instance>
<title>two-block</title>
<description>Template with two main areas</description>
<template-type>two-block</template-type>
<components>
<component>
<region-id>top-right</region-id>
<url>/search/box</url>
</component>
<component>
<region-id>footer</region-id>
<url>/footer/footer</url>
</component>
</components>
</template-instance>
The template-type contains information common to all template-instances of the same type, again the wcmqs webapp has one template-type for each template-instance. The template-type can specify the template processor, but the wcmqs webapp uses FreeMarker as the processor, which is the default.
This template-instance binds two template scoped components to regions, in the same way as described at the page level.
Templates contain output markup and processing tags. When the tags execute they dynamically generate markup. Spring Surf has built-in tags, or in FreeMarker terms, directives. This is the corresponding FreeMarker template file, two-block.ftl:-
The most significant part of this file is the @region directive, which is a surf built-in directive. Note that the id properties with page scope correspond to regions in the page configuration file and those with template scope correspond to regions in the template-instance configuration file. The regions with global scope are from the website object.
Web scripts are miniature, scriptable MVC applications. In the wcmqs webapp web scripts implement each component described in the page and template configuration files. Each component specifies the URL of its associated Web Script. Surf makes sure the Web Script executes with the right context and runtime environment so that it renders in the context of the whole page request. The output of each Web script is merged into the output of the page's associated template to construct the final html page.
Web scripts conform to the RESTFul architectural style, and accordingly use the HTTP methods for access (HTTP GET, POST, PUT, and DELETE). Web scripts can render output in a number of formats, for example HTML, Atom, XML, RSS. JSON. The wcmqs webapp responds to requests for HTML, so its web scripts all use the HTTP GET access method to render output in the HTML format.
Each Web script consists of three files :-
<web script id>.<http method>.desc.xml
For example: foo.get.desc.xml
<web script id>.<http method>.js
For example: foo.get.js
<web script id>.<http method>.<format>.ftl
For example: foo.get.html.ftl
The location of the files is just a important as the name. If you look back at the sectionpage1.xml page definition file, the left1 region has a URL of /list/twocolumn. The corresponding webscript must be found in webscripts/list with a <tt><web script id> of twocolumn. So the URL is always a path relative to the webscripts directory, plus the Web script id.
The /list/twocolumn web script consists of three files :-
twocolumn.get.desc.xml
twocolumn.get.html.ftl
twocolumn.get.js
The description document twocolumn.get.desc.xml looks like this:-
<webscript>
<shortname>Two col list</shortname>
<description>Two column list</description>
<url>/list/twocolumn</url>
</webscript>
This description just contains a name and the URI used to invoke the Web script. The description document name defines the HTTP method binding, so twocolumn.get.desc.xml specifies the HTTP GET method.
The controller script twocolumn.get.js looks like this:-
model.articles = collectionFactory.getCollection(context.properties.section.id, args.collection);
The controller script's main job is to construct the model for rendering by the response template. The model is a map of names and values. The model root object is given to the controller script by the Web script Framework.
The twocolumn.get.js adds a collection of articles to the model. The controller script uses the client API to get the Collection from the Alfresco repository. The client API javadoc is part of the wcmqs webapp and is provides the webapp's interface to the repository. The controller script just needs to provide the id of the section, and the name of the collection. The client API will generate a CMIS query to retrieve the requested collection and its contents.
The response template twocolumn.get.html.ftl looks like this:-
</a>
From </a>
</a>
${article.description!'no preview'}
From </a>
</a>
${article.description!'no preview'}
The response template renders an HTML div, using data retrieved from articles object.
The articles object is the collection retrieved in the controller script. The template uses the #list FreeMarker directive to iterate over the assets in the collection. FreeMarker interpolations are used to address the properties of each asset.
The response template can access any data in an object using the FreeMarker data model notation. Here is an example :-
${article.containingSection.title}
This adds a string, which is the title of the containing section of this asset to the response html. The dotted name convention addresses the class hierarchy in the wcmqs client api. So, article is of type Asset, and an Asset has a bean property, containingSection, which returns an object of type Section. A Section has a property title which is of type String.
You can study the javadoc to see what is available in the FreeMarker data model. For example, the Asset interface in the org.alfresco.wcm.client package exposes tags, mimetype, size, contentAsInputStream, relatedAssets, template, and renditions as properties. In addition because Asset is a subclass of resource, in inherits the containingSection, description, id, name, properties, property, title, and type.
The response template can also access the Alfresco repository directly using property names of the type from the Alfresco Content Model. Note that in the wcmqs client api, one of the bean properties of Asset is itself called properties. This method retrieves properties for the type of the object directly from the Alfresco data dictionary. You can view the model properties available in the model extension in the file
wcmquickstartmodule/config/alfresco/module/org_alfresco_module_wcmquickstart/model/webSiteModel.xml. For example, the type ws:webasset defines wsarentSections, ws:tags, wsublishedTime, ws:availableFromDate, ws:availableToDate, ws:available, ws:derivedCommentCount, and ws:derivedAverageRating as properties.
Here is an example :-
article.properties['ws:publishedTime']
This refers explicitly to the model property wsublishedTime in the Web site Alfresco model extension.
The view composition webscripts' controllers the path to one of the factory interfaces in the client API to create Web asset model. For example in the twocolumn.get.js controller script the
following JavaScript statement populates the model with a specified collection :-
model.articles = collectionFactory.getCollection(context.properties.section.id, args.collection);
Using the section id and the collection id, the getCollection method in implementation of the CollectionFactory, CollectionFactoryCmisImpl, builds a CMIS query language (cql) query string. The method then invokes the query method on the current CMIS session. CMIS will pass the query over to the repository and return a QueryResult. The CMIS query language is similar to that used for SQL queries. The session is held in ThreadLocal storage to allow it to be reused.
The UML-like sequence diagram below illustrates how a request URL from the user of the Web Quick Start web application is handled. Most of the work is initiated by the Spring interceptors. RequestContextInterceptor gets a Spring request context for the application, CmisSessionInterceptor gets a CMIS session for this thread from a the session pool, and ApplicationDataInterceptor augments the Spring request context with WebSite, Section and web assets from the Alfresco repository.
The diagram shows round trips to the Alfresco Repository for WebSite, Sections, and Web Assets. The round trip is not usually made, since the application implements caches for both the WebSite objects and the Section data.
alt=Sequence Diagram | Interactions between objects in Web Quick Start | 1024px
TBC
The source code for the Web Quick Start atefacts is included in the Alfresco svn repository. Synchronise with HEAD and build alfresco.war and share.war before you attempt to build the Web Quick Start targets.
ant package-wcmquickstart
This will build the alfresco-community-wcmqs-3.4.a.amp.
ant package-wcmquickstart-share
This will build the alfresco-community-wcmqs-share-3.4.a.amp.
ant package-wcmquickstart-webapp-war
This will build the web application wcmqs.war.
ant package-webeditor
Once you have successfully built the above artefacts, you can install then using the process described in Web Quick Start Installation and Configuration.
TBC
TBC
TBC
TBC
Definition Name | Type | Description | Usage |
---|---|---|---|
smallThumbnail | Composite | Reformat to image/jpeg followed by resize to 72px X 72px | Thumbnail image used by an Article |
mediumPublicationThumbnail | Composite | Reformat to image/jpeg followed by resize to 110px X 145px | Thumbnail image used in the Publications landing page |
mediumNewsThumbnail | Composite | Reformat to image/jpeg followed by resize to 223px X 143px | Thumbnail image used in an individual news article |
largeNewsThumbnail | Composite | Reformat to image/jpeg followed by resize to 574px X 395px | Enlarged image shown in the foreground when clicking on an image in a news article |
featuredNewsThumbnail | Composite | Reformat to image/jpeg. Crop 80% height followed by resize to 641px X 281px. | Homepage featured news image slider |
imagePreview | Composite | Reformat to image/jpeg followed by resize to 625px width maintaining aspect ratio | Display an image within the Publications section - full page details view |
swfPreview | Reformat | Reformat to application/x-shockwave-flash | Preview image of a pdf web asset |
pdfWebasset | Reformat | Reformat to application/pdf | Used internally to create a pdf web asset from a business document, for example from a Microsoft Word document |
Back to Web Quick Start
Web Content Management
Web Quick Start
3.3
3.4
Community Edition