Surf Platform - Deployment Configurations

Document created by resplin Employee on Jun 6, 2015Last modified by alfresco-archivist on Aug 31, 2016
Version 11Show Document
  • View in full screen mode

Obsolete Pages{{Obsolete}}

The official documentation is at: http://docs.alfresco.com



Surf Platform
Labs 3

NOTE: This page describes the Alfresco Surf Platform which is included in Alfresco 3.0, 3.1 and 3.2.

If you are looking for information about Alfresco 3.3, please visit Spring Surf.



Back to Alfresco Surf.



__toc__


Overview


Alfresco Surf is a lightweight, scriptable web framework built on top of Alfresco's Web Script and Templating runtime.  It provides web developers with the ability to quickly create web sites built around Alfresco content while utilizing familiar concepts such as pages, templates, components, themes and chrome.

Alfresco Surf installs as a web application.  Typically, this web application is packaged as a WAR file.  You might imagine Alfresco Surf as a WAR called 'surf.war' which is installed into a default Tomcat 6 instance.  It is that simple.


Alfresco WCM


Alfresco Web Content Management provides a robust Subversion-like repository which can manage all of the files of a web application - right down to the class files and source itself.  However, Alfresco WCM doesn't have to do all of that.  Rather, it provides us with a reliable tool for any of the following:


  • Collaborate on semantic content which includes things like press releases, news items and articles.  These are business-specific types of objects which will vary from one implementation to another.  Alfresco WCM provides object modeling tools, schema support and a Forms engine to help make this very easy.
  • Collaborate on presentation content which includes things like pages, web components, gadgets, chrome, themes, navigation trees and templates.  These are web-presentation goodies which facilitate the build out of a web site.  Alfresco Surf provides this and Alfresco WCM works hand-in-hand to provide a nice, clean repository.
  • Collaborate on static content which includes things like images, css, javascript files, flash files and video assets.  These are bits and pieces which the user's browser ends up pulling together when the live site is served up.  Alfresco WCM can manage these and make sure they are deployed to the right place.
  • Collaborate on the web framework itself which includes things like java and php code or anything related to the source of the application itself.  In the case of Surf, this includes things like jar files, web.xml and much more.  Alfresco WCM enables developers to push their build products into the repository and publish it out along with everything else - all at once.

With Alfresco WCM, we can place any or all of these into a Web Project.

A Web Project is a workspace for all or some of the collaborators on a web site or web application.  This could solely be the content contributors or it could everyone altogether.  It's really up to the web site administrator.


Alfresco Surf and Alfresco Web Content Management


Alfresco Web Content Management empowers Surf designers by providing them with the ideal set of tools for building Surf applications.  Alfresco WCM automatically provides rich version control, snapshots, workflow, layering, branching and much more.

In addition, Alfresco WCM provides Deployment capabilities which allow your administrators to publish Surf-sites out to test and production.  This keeps costs low by reducing the need for additional hardware, personnel or intermediaries.

Alfresco Surf can be configured in a variety of ways.


  • It can act as the runtime for your production, presentation tier and serve a completed web site to your end users.  Using Alfresco WCM, Alfresco Surf can receive published updates that reflect on the live site right away.
  • It works in the test tier so that your QA and integration teams can quickly see what the site would look like when it runs side-by-side with other projects within the business
  • It runs in the preview tier so that your content authors can instantly preview changes to the web site without the need for additional servers or personnel.  Alfresco Surf works hand-in-hand with Alfresco WCM to offer instant preview of the entire web application.
  • It also provides an application platform for building custom applications that your development teams may create and deploy entirely via their own methods.  One example of such an application Alfresco Share - Alfresco's collaborative document management application provided with Alfresco 3.0.

Getting Started


This section covers building and configuring Alfresco Surf.


Building Alfresco Surf


As mentioned, Alfresco Surf builds as a WAR file and you can deploy it to a standalone Tomcat application server (or the application server of your choosing).  The first thing we should therefore do is to build Surf itself.

Note: Those new to Alfresco should read through the general guide to setting up an Alfresco SVN Development Environment.  This will give you access to the latest Alfresco code from our source control tree.

Once you have your environment set up, you should build using the incremental-surf-starter build target.  From a command line, you could run the following:



ant incremental-surf-starter

This will produce:



./projects/web-framework/build/dist/surf.war

This is your war file.  It is prestocked with sample components and provides an excellent starting point for your web sites.

These sample components include:


  • Navigation Component - a basic navigation component with horizontal and vertical renderers
  • Image Component - renders images along with minimal formatting
  • HTML Component - render HTML and other markup to the browser
  • List View Component - renders a list of items in various presentation formats
  • Breadcrumb Component - displays a breadcrumb to the current page
  • Audio Component - plays back audio files
  • Video Component - plays back video files
  • Flash MP3 Component - plays back audio files via Flash MP3 Player
  • JW Player Component - plays back video files via the JW Player

Alternatively, if you didn't want any of the sample components and goodies, you can do the following:



ant incremental-surf

This will produce:



./projects/web-framework/build/dist/surf.war

This will build you a completely empty Surf web application - the bare minimum that you would need to get started.

Which one you use is up to you.  If you intend to deploy Surf applications that were built with Web Studio, then you should build using the incremental-surf-starter target.  In general, this is the recommended target for folks to begin with.


Setting up Surf inside of Tomcat 6


Once you have the surf.war file, you can simply deploy it to your application server.  Tomcat 6 is one such application server.  It is an open-source application server and it is a favorite in the open source world, thus it is covered here.

You may have a different application server and that's fine.  Feel free to follow along as this section may serve to provide a general guide.

First, download and set up Tomcat into a convenient place.  You can download Tomcat from http://tomcat.apache.org.  For the sake of brevity, let's assume that you install tomcat to the following directory:



/tomcat

Second, drop your surf.war file into Tomcat's webapps directory:



/tomcat/webapps/surf.war

Third, modify catalina.properties so that configuration files are picked up from the /shared/classes and /shared/lib directories.  This is a convenient thing to do as it will allow you to customize your Surf environment without modifying surf.war:



/tomcat/conf/catalina.properties

Adjust the following and save the file:



shared.loader=${catalina.base}/shared/classes,${catalina.base}/shared/lib/*.jar

Configure Surf


Alfresco Surf provides quite a lot of configuration options.  We can tweak any of them within our Tomcat instance and we can now do so without having to change the surf.war file at all.  We can simply drop files into the /shared/classes path.

Alfresco Surf has default configuration files which it will normally load.  It also checks to see if we've provided any overrides.  Our overrides take precedence.  As such, we can use these overrides to get Surf to behave however we would like.

Fundamentally, there are two files that we will want to work with:


  • web-framework-config-custom.xml - allows us to customize runtime properties about Alfresco Surf
  • custom-web-framework-application-context - allows us to inject new behaviors and runtime classes for Alfresco Surf

If we wanted to, we could drop these files into the following path in our Tomcat instance:



/tomcat/shared/classes/alfresco/web-extension

For a detailed overview of Alfresco Surf configuration options, please visit the Alfresco Surf Advanced configuration section of this Wiki.

If we take a look once more at our SVN, we can see that several example files are provided which will be useful in the coming sections.  Take a look at the following path:



/projects/web-framework/config/alfresco/web-extension

You will find sample files for the various environments into which Surf can be deployed - preview, test and production.  These are:


  • Standalone
    • custom-web-framework-application-context.xml.standalone
    • web-framework-config-custom.xml.standalone
  • Preview
    • custom-web-framework-application-context.xml.preview
    • web-framework-config-custom.xml.preview
  • Test
    • custom-web-framework-application-context.xml.test
    • web-framework-config-custom.xml.test
  • Production
    • custom-web-framework-application-context.xml.production
    • web-framework-config-custom.xml.production

These can be copied into Tomcat's /shared/classes/alfresco/web-extension folder.  Remove the suffix so that each ends with XML.  Tomcat will then pick these up when you next restart.


Stores and Search Paths


A very important concept in Surf is the idea of a Store.  A store is a place from where Surf objects can be loaded.  Surf objects are any of the following:


  • Web Scripts - Java Script and Templates
  • Templates - Freemarker and other template formats
  • Surf Objects - XML describing pages, components, themes, etc.

Another important concept is that of a Search Path.  A search path is an ordered collection of stores.

When Surf needs to load objects, it looks through a search path to figure out where the objects are located.  The first store that it finds with the object is the store that is used.  The object is loaded and Surf moves on to the next thing.

The following types of stores are available:


  • Classpath Store - a store which loads files from the classpath of the currently running web application
  • Local File System Store - a store which loads files from a specified location on the local disk
  • Remote Store - a store which loads files from an Alfresco Repository store

Search paths consist of an ordered list of stores.  You can use this mechanism to 'layer' your stores so that one store supersedes another.  This allows you to override some Surf objects with other Surf objects.

In configuring Surf to run on different environments, it is wise to consider how you might architect your search paths to best accommodate the locations of your Surf files.  A production server, for example, may be configured with a local file system store so that it can automatically pick up changes from a deployment event.

Stores and search paths are configured via Spring beans in the custom-web-framework-application-context.xml file.


Surf as a Standalone Server


A good starting point is to consider the case where Alfresco Surf is running purely in standalone mode.  This means that it is running completely detached from any Alfresco repository.  It runs entirely from the classpath.

When might this be useful?  Consider that you've built a web application using the Surf framework and have compiled it into a WAR file.  All of the assets needed to run the web application are contained within the WAR.  As such, Surf can load everything it needs from the classpath.

You may already be familiar with one web application which is exactly like this - Alfresco Share itself.

Alfresco Surf builds by default with classpath specific settings.  That said, we'll focus this section on looking into the contents of the following two sample files:


  • custom-web-framework-application-context.xml.standalone
  • web-framework-config-custom.xml.standalone

Spring Configuration


The file custom-web-framework-application-context.xml provides definitions for how to look up web scripts and templates:


  • webframework.searchpath
    • The search path to use when looking up declarative web scripts file dependencies.  These are typically the .js, .ftl, .properties and .xml files required by the web script engine.
  • webframework.templates.searchpath
    • The search path to use when looking up templates and templates dependencies.  These are typically .ftl files.



It also provides definitions for how to look up each of Alfresco Surf's model object types.  These are defined in the following beans:


  • webframework.searchpath.chrome
  • webframework.searchpath.component
  • webframework.searchpath.componenttype
  • webframework.searchpath.configuration
  • webframework.searchpath.contentassociation
  • webframework.searchpath.page
  • webframework.searchpath.pageassociation
  • webframework.searchpath.pagetype
  • webframework.searchpath.templateinstance
  • webframework.searchpath.templatetype
  • webframework.searchpath.theme



Finally, the file provides a few interesting overrides which allow us to control the caching of the web application.  Note that by default the Surf application has caching enable.  Here, in our configuration files, we turn caching off for both the Web Script and Template processors.

webframework.webscripts.templateprocessor



<bean id='webframework.webscripts.templateprocessor'
      class='org.alfresco.web.scripts.PresentationTemplateProcessor'>
   <property name='searchPath' ref='webframework.searchpath' />
   <property name='updateDelay'><value>0</value></property>
   <property name='defaultEncoding'><value>UTF-8</value></property>
</bean>

webframework.templateprocessor


 
<bean id='webframework.templateprocessor'
      class='org.alfresco.web.scripts.PresentationTemplateProcessor'>
   <property name='searchPath' ref='webframework.templates.searchpath' />
   <property name='defaultEncoding'><value>UTF-8</value></property>
   <property name='updateDelay'><value>0</value></property>
</bean>

Web Framework Configuration


The file web-framework-config-custom.xml provides configuration settings for the Surf web framework.  This is a configuration service file which is loaded when Surf initializes.

Let's look at what is inside of it:



<persisters>
   <cache-enabled>false</cache-enabled>     
   <cache-check-delay>0</cache-check-delay>
</persisters>

This block tells the Surf persister layer not to cache anything.  The cache is disabled.  You could also enable the cache and set the cache-check-delay to a positive number of seconds in order to have all model object persister cache using these settings.  Finally, you also have the option to adjust caching on a per-model-object basis (not covered here).



<model-type>
   <id>chrome</id>
   <version>1.0</version>
   <name>Chrome</name>
   <description>Chrome</description>
   <namespace></namespace>
   <class>org.alfresco.web.framework.model.Chrome</class>
   <search-path-id>webframework.searchpath.chrome</search-path-id>
   <default-store-id>webframework.classpathstore.chrome</default-store-id>

</model-type>

This is one of several blocks that defines a Surf model object type.  It defines the implementation class (so that Surf can manufacture backing beans) and tells Surf how to look up objects of the given type (which search path to use).  It also defines which store to use by default when new objects of this type are created.

Note that this uses the webframework.classpathstore.chrome store for creating instances of type Chrome.  This is a classpath store.  Thus, if you actually do try to create objects, Surf will inform you that it cannot be done.  Read on further to learn of alternative configurations which might better suit you!

Finally, there are a few cache fields that are commented out.  You could use these to finely control how Surf loads individual model object types.  In general, you will probably deal with the previously mentioned <persister/> block since that controls all model objects at once.


Surf Code


Note that all of the search paths defined in this file include references to both the classpath and the shared web-extension folder.  This allows you to extend the Surf application without having to modify the WAR file, if you so choose.

If you wish to modify Surf files within the WAR file itself, you will need to place the Surf files into the web application classpath so that the classpath store can pick them up.  To do so, you would drop them into:



/tomcat/webapps/surf/WEB-INF/classes/alfresco

If you wish to modify Surf files outside of the WAR (recommended), you will need to place the Surf files into the Tomcat shared/classes path.  To do so, drop your Surf files into:



/tomcat/shared/classes/alfresco/web-extension

For reference, the following are default classpath locations for each of the Surf file types:


  • Surf Web Scripts

alfresco/site-webscripts
alfresco/web-extension/site-webscripts

  • Surf Templates

alfresco/templates
alfresco/web-extension/templates

  • Surf Model Objects

alfresco/site-data/chrome
alfresco/web-extension/site-data/chrome

alfresco/site-data/components
alfresco/web-extension/site-data/components

alfresco/site-data/component-types
alfresco/web-extension/site-data/component-types

alfresco/site-data/configurations
alfresco/web-extension/site-data/configurations

alfresco/site-data/content-associations
alfresco/web-extension/site-data/content-associations

alfresco/site-data/pages
alfresco/web-extension/site-data/pages

alfresco/site-data/page-types
alfresco/web-extension/site-data/page-types

alfresco/site-data/page-associations
alfresco/web-extension/site-data/page-associations

alfresco/site-data/template-instances
alfresco/web-extension/site-data/template-instances

alfresco/site-data/template-types
alfresco/web-extension/site-data/template-types

alfresco/site-data/themes
alfresco/web-extension/site-data/themes

With this in mind, you should be able to begin building Surf sites and Surf applications.  For guidance on doing so, check out the guides and references provided for the Alfresco Surf Platform.




Surf and Alfresco Web Content Management


In the previous section, we saw how you can drop Alfresco Surf files into the classpath of an application and begin building out your web site.  Wouldn't it be much nicer if we had the full power of an Enterprise Class WCM solution to help us?

Alfresco WCM provides change-set management, versioning, workflow, auditing, snapshots and security for our web application code.  It is the ideal environment for working on our Surf files.

To get started, all we have to do is start up Alfresco.  Typically, Alfresco is installed on port 8080.  As such, we can access Alfresco using the following URL:



http://localhost:8080/alfresco

Once inside of Alfresco, we can go into the Web Projects directory and we can create a web project.  Let's call our web project testsite.

surf-deployment-create-webproject-1.png

Now that we have our Web Project, we can simply map a CIFS drive against and use it as if it were a drive on our desktop!  In a Windows world, all you have to do is:



net use Z: \\MYMACHINEA\AVM

...where MYMACHINEA is generally the name of your machine followed by A.  This is the default setting but you may have also changed this via CIFS configuration when you set up Alfresco.

Authenticate as admin/admin.

Navigate into your user sandbox and traverse down into the ROOT web application.  This path should be the following:



Z:\testsite--admin\HEAD\DATA\v-1\www\avm_webapps\ROOT

Create the following path:



WEB-INF/classes/alfresco

That's where we'll drop all of our Surf files.

surf-deployment-mapped-drive-1.png

Note that we're working against our sandbox.  This means that all of the files and directories that we add are not visible to others in the web project until we submit them for approval.  This allows for others in the web project to approve or reject changes and for everyone to agree on what gets promoted into the staging area.

As we add files to our sandbox, we would like to have an Alfresco Surf instance up and running somewhere that we can use to instantly pick up our changes and preview our web application.


Surf as a Preview Server


As before, we can deploy surf.war to an Alfresco Tomcat instance.  This time, we can look at two sample files which help describe how we can configure Surf to act as a Preview Server for Alfresco WCM:


  • custom-web-framework-application-context.xml.preview
  • web-framework-config-custom.xml.preview

Spring Configuration


The file custom-web-framework-application-context.xml provides definitions for how to look up web scripts and templates.  It begins by defining a brand new store to connect to the Alfresco WCM sandboxes.  This is a remote store.


  • webframework.remotestore
    • A remote store which connects to an Alfresco WCM sandbox.

We must complete this section by providing the id of our store:



<bean id='webframework.remotestore' parent='webscripts.remotestore' abstract='true' init-method='init'>
   <property name='endpoint'>
      <value>alfresco-system</value>
   </property>
   <property name='api'>
      <value>/avmstore</value>
   </property>
   <property name='storeId'>
      <value>testsite--admin</value>
   </property>
   <property name='connectorService' ref='connector.service' />
   <property name='storeContext' ref='webframework.context.remotestore'/>
   <property name='connectorProvider' ref='webframework.connector.provider' />     
</bean>

Note that this store is created as an abstract.  It is then extended by two more reomte stores instances which define locations of files for Web Scripts and Templates:


  • webframework.remotestore.webscripts
    • Remote Store instance which will be used to discover Web Scripts
  • webframework.remotestore.templates
    • Remote Store instance which will be used to discover Templates



The search paths for Web Scripts and Templates are then defined.  The remote stores are incorporated into the search path definitions.


  • webframework.searchpath
  • webframework.templates.searchpath

As a result, when Alfresco Surf needs to look up Web Scripts or Templates, it will look to the WCM Sandbox first.

The model objects are then defined.  For each model object, we declare a Remote Store instance which tells Surf how to load that model object from the WCM Sandbox.  We then tell the model object's search path to first look at our model object's remote store when trying to load objects of that type.

Here is the sample definition for Chrome:



<bean id='webframework.remotestore.chrome' parent='webframework.remotestore'>
   <property name='path'><value>alfresco/site-data/chrome</value></property>
</bean>  
<bean id='webframework.searchpath.chrome' class='org.alfresco.web.scripts.SearchPath'>
   <property name='searchPath'>
      <list>
         <ref bean='webframework.remotestore.chrome' />
         <ref bean='webframework.classpathstore.chrome.custom' />
         <ref bean='webframework.classpathstore.chrome' />
      </list>
   </property>
</bean>

If you look through the file, you'll see similar definitions for all of the other model object types.

Finally, at the bottom of the file, you'll see that we've turned off caching for the Web Script processor and the Template processor.  Since this is a Preview server, we don't really want it to cache.  We're not as concerned about it being fast - we're much more concerned about it being accurate.

webframework.webscripts.templateprocessor



<bean id='webframework.webscripts.templateprocessor'
      class='org.alfresco.web.scripts.PresentationTemplateProcessor'>
   <property name='searchPath' ref='webframework.searchpath' />
   <property name='updateDelay'><value>0</value></property>
   <property name='defaultEncoding'><value>UTF-8</value></property>
</bean>

webframework.templateprocessor


 
<bean id='webframework.templateprocessor'
      class='org.alfresco.web.scripts.PresentationTemplateProcessor'>
   <property name='searchPath' ref='webframework.templates.searchpath' />
   <property name='defaultEncoding'><value>UTF-8</value></property>
   <property name='updateDelay'><value>0</value></property>
</bean>




Web Framework Configuration


The file web-framework-config-custom.xml provides configuration settings for the Surf web framework.  This is a configuration service file which is loaded when Surf initializes.

Let's look at what is inside of it:



<persisters>
   <cache-enabled>false</cache-enabled>     
   <cache-check-delay>0</cache-check-delay>
</persisters>

This block tells the Surf persister layer not to cache anything.  By defining it here, we tell all of the model objects not to cache.  This is a quick way to set them all at once without having to go one at a time.



<model-type>
   <id>chrome</id>
   <version>1.0</version>
   <name>Chrome</name>
   <description>Chrome</description>
   <namespace></namespace>
   <class>org.alfresco.web.framework.model.Chrome</class>
   <search-path-id>webframework.searchpath.chrome</search-path-id>
   <default-store-id>webframework.remotestore.chrome</default-store-id>

</model-type>

What follows next are all of the model object type definitions.  This is pretty much the same as for the standalone configuration.  You can adjust settings for cache and so forth on a per-object-type basis, just as before.

The difference here is that default-store-id is now set to webframework.remotestore.chrome.  This means that new model objects of type Chrome will be placed into the remote store.  Thus, they'll be placed right into our web project sandbox.


Surf Code


Note that all of the search paths defined in this file include references to remote store instances which point back to our Alfresco WCM sandbox.  This allows us to work on content inside of our WCM sandbox and see it show up inside of the Surf application right away.

Once we've started our preview instance of Surf, we can go back to using Alfresco WCM to work on our Surf objects.

Using you mapped AVM CIFS drive, navigate to the following path:



Z:\testsite--admin\DATA\v-1\www\avm_webapps\ROOT

Make sure that you have created the following subfolder:



WEB-INF/classes/alfresco

You can edit your Surf files right inside of this folder.

For reference, the following are valid locations:


  • Surf Web Scripts

WEB-INF/classes/alfresco/site-webscripts

  • Surf Templates

WEB-INF/classes/alfresco/templates

  • Surf Objects

WEB-INF/classes/alfresco/site-data/chrome
WEB-INF/classes/alfresco/site-data/components
WEB-INF/classes/alfresco/site-data/component-types
WEB-INF/classes/alfresco/site-data/configurations
WEB-INF/classes/alfresco/site-data/content-associations
WEB-INF/classes/alfresco/site-data/pages
WEB-INF/classes/alfresco/site-data/page-types
WEB-INF/classes/alfresco/site-data/page-associations
WEB-INF/classes/alfresco/site-data/template-instances
WEB-INF/classes/alfresco/site-data/template-types
WEB-INF/classes/alfresco/site-data/themes

Previewing


To preview, all we have to do is open our Surf application in a browser.  The Surf application communicates with Alfresco and presents our sandbox content in the web site.

All of our work-in-progress Surf files are picked up automatically and rendered for us.

Note that this requires that we have provided the storeId and webappId in our Spring configuration file if we wish to preview a specific, known sandbox.

If we would like to use the same Surf instance to preview many different sandboxes (virtualized) via a switch, then we can fire the following URLs at the Surf instance:



http://server:port/surf/page?alfStoreId=<storeId>&alfWebappId=<webappId>

An example might be the following:



http://localhost:9090/surf/page?alfStoreId=greenenergy--admin&alfWebappId=ROOT

Using this mechanism, we can preview any of our Surf Web Projects while using a single Surf server!  We can switch between web applications and between user sandboxes.


Deploying from Alfresco WCM to Production Server


We've now worked on content inside of our Alfresco Web Content Management sandbox and previewed it on our Surf preview server.

Suppose that we're satisfied with our changes.  The first thing we would do is submit the content using Alfresco's WCM UI.

surf-deployment-submit-items-1.png

The content is submitted from our sandbox up to the staging store.  If we wanted to configure workflow here, we could do that so that the content would need to be previewed and approved by a reviewer.  However, in this case we didn't set up a workflow, so it was submitted up to staging.

We would now like to publish this content from our Alfresco Web Content Management authoring environment out to production.  On the production tier, we can have a standalone Alfresco Surf server that is waiting for new content to arrive.  We publish out from the authoring tier to the production tier.


Surf as a Production Server


A production Surf instance is very similar to a Standalone Surf instance.  There are only a few differences.  Fundamentally, we would like the Surf instance to pick up files that are deployed to the production environment.  Surf therefore needs to look outside the classpath (so as to avoid application server restarts).  We would also like to configure the Surf Production web application to be a bit more 'performance focused' and so we may opt to tweak a few of the cache settings.

This time, we can look at two sample files which help describe how we can configure Surf to act as a Production Server for Alfresco WCM:


  • custom-web-framework-application-context.xml.production
  • web-framework-config-custom.xml.production

Spring Configuration


The file custom-web-framework-application-context.xml provides definitions for how to look up web scripts and templates.  It begins by defining a brand new store to connect to a directory on the local disk.  This is a local file system store.


  • webframework.localstore
    • A local file system store which points to a local directory.

Note that this section includes a property root which defines the root location where our files will be deployed:



<bean id='webframework.localstore'
      class='org.alfresco.web.scripts.LocalFileSystemStore'
      abstract='true'
      init-method='init'>

   <property name='root'>
      <value>/deploy/files</value>
   </property>

</bean>

Note that this store is created as an abstract.  It is then extended by two more local stores instances which define locations of files for Web Scripts and Templates:


  • webframework.localstore.webscripts
    • Local File System Store instance which will be used to discover Web Scripts
  • webframework.localstore.templates
    • Local File System Store instance which will be used to discover Templates

The search paths for Web Scripts and Templates are then defined.  The local stores are incorporated into the search path definitions.


  • webframework.searchpath
  • webframework.templates.searchpath

As a result, when Alfresco Surf needs to look up Web Scripts or Templates, it will look to the local disk location first.

The model objects are then defined.  For each model object, we declare a Local File System Store instance which tells Surf how to load that model object from the location on disk.  We then tell the model object's search path to first look at our model object's local store when trying to load objects of that type.

Here is the sample definition for Chrome:



<bean id='webframework.localstore.chrome' parent='webframework.localstore'>
   <property name='path'><value>alfresco/site-data/chrome</value></property>
</bean>
<bean id='webframework.searchpath.chrome' class='org.alfresco.web.scripts.SearchPath'>
   <property name='searchPath'>
      <list>
         <ref bean='webframework.localstore.chrome' />
         <ref bean='webframework.classpathstore.chrome.custom' />
         <ref bean='webframework.classpathstore.chrome' />
      </list>
   </property>
</bean>

If you look through the file, you'll see similar definitions for all of the other model object types.

Finally, at the bottom of the file, you'll see that we've turned on caching for the Web Script processor and the Template processor.  This cache will only update every 600 seconds.  This cache will allow our requests to process through faster since we won't have to incur the lookup on the search path each time Surf tries to load an object.

webframework.webscripts.templateprocessor



<bean id='webframework.webscripts.templateprocessor'
      class='org.alfresco.web.scripts.PresentationTemplateProcessor'>
   <property name='searchPath' ref='webframework.searchpath' />
   <property name='updateDelay'><value>600</value></property>
   <property name='defaultEncoding'><value>UTF-8</value></property>
</bean>

webframework.templateprocessor


 
<bean id='webframework.templateprocessor'
      class='org.alfresco.web.scripts.PresentationTemplateProcessor'>
   <property name='searchPath' ref='webframework.templates.searchpath' />
   <property name='defaultEncoding'><value>UTF-8</value></property>
   <property name='updateDelay'><value>600</value></property>
</bean>

Web Framework Configuration


The file web-framework-config-custom.xml provides configuration settings for the Surf web framework.  This is a configuration service file which is loaded when Surf initializes.

Let's look at what is inside of it:



<persisters>
   <cache-enabled>false</cache-enabled>     
   <cache-check-delay>600</cache-check-delay>
</persisters>

This block tells the Surf persister layer to cache model objects for 600 seconds.  This defines a common cache setting across all Surf model object types.



<model-type>
   <id>chrome</id>
   <version>1.0</version>
   <name>Chrome</name>
   <description>Chrome</description>
   <namespace></namespace>
   <class>org.alfresco.web.framework.model.Chrome</class>
   <search-path-id>webframework.searchpath.chrome</search-path-id>
   <default-store-id>webframework.localstore.chrome</default-store-id>

</model-type>

This is one of several blocks that defines a Surf model object type.  It defines the implementation class (so that Surf can manufacture backing beans) and tells Surf how to look up objects of the given type (which search path to use).  It also defines which store to use by default when new objects of this type are created.

Note that this uses the webframework.localstore.chrome store for creating instances of type Chrome.  This is the local file system store.  Thus, if you actually do try to create objects, Surf will create them on the local disk.

Finally, there are a few cache fields that are commented out.  You could use these to finely control how Surf loads individual model object types.  In general, you will probably deal with the previously mentioned <persister/> block since that controls all model objects at once.



<resource-resolver>
   <id>webapp</id>
   <name>Alfresco Web Application Resource Resolver</name>
   <description>Resolves data access for web application assets</description>
   <class>org.alfresco.web.framework.resource.AlfrescoWebProjectResourceResolver</class>
   <alias-uri>/files</alias-uri>
   <store-id>STORE_ID</store-id>
</resource-resolver>

If your Surf application binds to Web Application resources, like static files from the web application, the webapp resource resolver will help your runtime application determine the location of the files.

Within your Surf application, you can use resource tags to point at resources within the application.  You can acquire a URL to a Surf object's resource binding using a Freemarker directive much like the following:




This might describe a resource within the web application located at:



/a/b/c.gif

With this resource resolver in place, the tag would transform at runtime within your production Surf instance to point to the following:



http://localhost/<webapp>/files/a/b/c.gif

File System Receiver


Alfresco provides both File System Receivers (FSRs) and Alfresco System Receivers (ASRs) to support your live web site.  Both are pluggable and allow you to provide handlers or 'Runnables' which can handle post-deployment processing and data massaging for your live web site.

In this section, we'll set up an FSR which will listen for deployment events from the Alfresco WCM authoring server.  When files arrive to our FSR, they'll be handled by one of two targets:


  • surf - a target that handles Surf objects and writes them to disk
  • static - a target that handles static objects and writes them to disk

We do this for convenience as it is often beneficial to separate your application logic from your static files.  Static files are things like images, css, flash files and the like.

To get started, download and start the installer for the Alfresco Deployment FSR.  This is a relatively small install as it is just a small program that listens for deployment events.  You can also install this by downloading the ZIP archive and manually extracting into a directory.

Here, let us assume that the FSR is deployed to the following directory:



d:/deploy

If you're on Linux or a non-Windows platform, you substitute for the appropriate path.

Inside of the deploy folder, let's create a 'files' folder.

</pre>
d:/deploy/files
</pre>

Now let us edit the deployment.properties file.  If you've used the installer, this file is automatically generated for you.  Otherwise, fill it in as follows:



dep.datadir=d:\deploy\deploy_depdata
dep.logdir=d:\deploy\deploy_deplog
dep.metadatadir=d:\deploy\deploy_depmeta
dep.rmi.port=44100
dep.rmi.service.port=44101

Next, let's set up two deployment targets - one to handle our Surf files and the other to handle our Static files.  We define these inside of our application-context.xml file which tells Spring how to load beans when it starts up.  Spring loads a configuration bean and we would like to provide two custom targets:



<property name='targetData'>
   <map>
      <entry key='surf'>
         <map>
            <entry key='root'><value>/deploy/files/alfresco</value></entry>
            <entry key='user'><value>admin</value></entry>
            <entry key='password'><value>admin</value></entry>
            <entry key='runnable' value-ref='surfRunnable' />
         </map>
      </entry>
      <entry key='static'>
         <map>
            <entry key='root'><value>/deploy/files/webroot</value></entry>
            <entry key='user'><value>admin</value></entry>
            <entry key='password'><value>admin</value></entry>
         </map>
      </entry>
   </map>
</property>

Note that the first target (surf) executes a Runnable once the deployment completes.  As a final step, let's define that Runnable.  Add a bean definition to the end of the file:



<bean id='surfRunnable' class='org.alfresco.deployment.SurfRefreshRunnable'>
   <property name='surfLocation'>
      <value>http://localhost:8280/surf</value>
   </property>
</bean>

Save all of these files and then start up the File System Receiver.  You can do this on Windows by using the deploy_start.bat batch file.


Web Project Configuration


We now need to tell our Web Project how to deploy to our File System Receiver.  The File System Receiver is sitting out there, waiting for a deployment event to be sent to it.  We must tell our web project how to contact the FSR and also tell it how it should go about sending files to it.

To begin, edit your web project settings from within the Alfresco Explorer.  You will arrive at a screen where we can tell our Web Project about the file system receiver and targets that we just defined.

Let's add a File System Receiver that will be responsible for sending Surf files to Production.  We can use the following properties:

surf-deployment-fsr-1.png

Next, let's add a File System Receiver that will be responsible for sending Static files to Production.  We can use the following properties:

surf-deployment-fsr-2.png

Note: For FSR Excludes field, the syntax looks like



[A-Za-z0-9:/_]*ROOT/WEB-INF/*

Save your changes and your web project will be configured to publish out to the File System Receiver!


Tomcat Configuration


By configuring the FSR targets in the previous section, we've told our web project how to publish out both Alfresco Surf objects as well as static things (like images and so forth).

The static bits arrive on disk in a place like:



/deploy/files/webroot/ROOT

We want to tell our production Tomcat server how to pick up these assets by basically creating a virtual directory (or alias) which maps a web application path over to this deployed assets directory.  That way, things get picked up automatically on deployment and Tomcat knows how to serve things back straight away.

Inside of your production Surf Tomcat instance, go to the following directory:



/tomcat/conf

And then create the following path and file (for Tomcat 6):



/tomcat/conf/Catalina/localhost/files.xml

Add the following content to the file:



<Context reloadable='true' docBase='d:\deploy\files\webroot\ROOT' debug='1'/>

Save the file.  When you restart Tomcat, you'll now have a virtual directory that serves back the deployed static assets.  You can access this by using the following URL:



http://<server>:<port>/files




Publishing to Production from WCM


Once the web project is set up correctly, we can use Alfresco Web Content Management's deployment capabilities to either schedule publishing or manually publish a snapshot of our web site to production.

To begin, we should make sure that all of our changed files are successfully submitted up to the staging area.  Let's take a look at our modified items:

surf-deployment-submit-items-2.png

By clicking on submit, we can submit these items to staging:

surf-deployment-submit-items-3.png

Since we have no default workflow configured, these will be automatically promoted up to the staging store.  We should now see that a snapshot has been generated:

surf-deployment-snapshots-1.png

By clicking on the Deploy button, we can now deploy this snapshot to production.  On the next screen, pick the receiver target (your file system receiver):

surf-deployment-receivers-1.png

The deployment will then proceed.  Your files will be sent over to the file system receiver and will be written to disk in the appropriate locations. 

surf-deployment-deployment-finished-1.png

Alfresco Surf on the production machine will be refreshed and your new web site will be live.

Outcomes