Obsolete Pages{{Obsolete}}
The official documentation is at: http://docs.alfresco.com
Draft PagesDeveloper GuideSurf Platform
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 the Alfresco Surf Platform.
__toc__
Surf is a lightweight, scriptable Java-based web framework. As such, it runs inside of a web application. A Surf application is typically packaged as a standalone WAR file which is then deployed to your Java application server.
One such example is the alfwf.war file that builds by default within the Alfresco Web Framework project. You could take this WAR file and drop it into an application server so as to use it. That's all there is to it.
Typically, the WAR file will contain:
We'll assume this to be the case as we proceed.
When the WAR file expands, it has a structure much like the one shown here:
/core
/css
/images
/WEB-INF
/WEB-INF/classes/alfresco
index.jsp
You may have some additional directories, but these are the essential ones. It is a very straightforward web application.
The first file to look at is the web.xml file, located under WEB-INF. The servlet container begins by reading this file. Within web.xml, there are declarations for servlets and Spring objects. It is kept lightweight, but you should note some of the sections.
The following section tells the Spring Framework context how to load. Spring is included with the Surf platform and is responsible for bean management and instantiation. The Spring ContextLoaderListener is configured as a servlet listener and reads the bean configuration files when the Surf application starts.
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
The Spring context loader uses the contextConfigLocation context parameter to find what beans to configure. The context-param section bootstraps webscript-framework-application-context.xml (which loads the Web Script Engine configuration). It then bootstraps web-framework-application-context.xml (which loads the Surf platform config).
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:alfresco/webscript-framework-application-context.xml
classpath:alfresco/web-framework-application-context.xml
</param-value>
<description>Spring config file locations</description>
</context-param>
Once the web application starts up, several servlets are made available. One such servlet is the DispatcherServlet which is the main handler for requests that enter the Surf platform:
<servlet>
<servlet-name>pageRendererServlet</servlet-name>
<servlet-class>org.alfresco.web.site.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>pageRendererServlet</servlet-name>
<url-pattern>/page/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>pageRendererServlet</servlet-name>
<url-pattern>/p/*</url-pattern>
</servlet-mapping>
Requests that arrive to the web application hit index.jsp, which forwards the request to the dispatcher servlet (a forward to /page).
Once requests are directed to the dispatcher servlet, the Surf Platform begins execution of a Model-View-Controller pattern so as to determine how to render back the entire page. This MVC model is described here.
The Dispatcher Servlet is responsible for rendering back a page to the user. It must consider the incoming request context and figure what and how to render. The dispatcher can receive requests for the following:
There are other combinations; the permutations are numerous. As such, the Dispatcher Servlet has been implemented in such a way as to allow developers to customize its behavior with a minimal amount of work.
The Advanced section of this documentation covers further concepts such as Page Mappers, Rendering Engines and overrides, and display processors.
The Surf Platform provides a default object model that implements that majority of common web site and web application object types that you might expect. These include things like Pages, Templates, Components and Themes.
Furthermore, the Surf Platform enables you to define your own object model or extend the out-of-the-box object model to accommodate your needs.
Surf Platform model objects are managed in memory as standard POJOs (Plain Old Java Objects). When written to disk, they are serialized as XML.
In the case of our standalone WAR file, the XML is stored in subdirectories within the following location:
/WEB-INF/classes/alfresco/site-data
Within this directory, you see the following subdirectories, one for each type of model object that is managed by the Surf platform:
/site-data/chrome
/site-data/component-types
/site-data/components
/site-data/configurations
/site-data/content-associations
/site-data/page-associations
/site-data/page-types
/site-data/pages
/site-data/template-instances
/site-data/template-types
/site-data/themes
Inside each subdirectory, you may find XML which represents a serialized model object. For instance, within the default alfwf.war file, there is a file called welcome.xml. This is a page with id welcome
and it contains the following XML:
<page>
<title>The test welcome page</title>
<template-instance>welcome-main</template-instance>
<authentication>none</authentication>
</page>
The exact semantics of each object type is covered later in this document, but this should give you a general feel. From looking at the XML, you can see that this is a page whose title is The test welcome page
and which points to a template that has the id welcome-main
. No authentication is required to access this page.
As you create new pages, new components, or any model object, you do so by dropping new XML into these directories. This means there is no need to access databases or customize web clients.
The Surf Platform controller looks at its model and then asks specific model objects to render. Typically, these are things like components or templates. When the model objects render, they can render using any of Surf's supported rendering engines.
There are several rendering engines supported out-of-the-box. These include:
However, you may also wish to implement your own. The Surf Platform has been designed to allow developers to define their own rendering engines and hook them into existing model objects or their own custom types.
The Web Scripts rendering engine is provided by default and is the most advanced engine since it allows you to take advantage of both JavaScript (for pre-render processing) and Freemarker (for presentation processing). If you have built web scripts using Alfresco's web script engine before, then you will already be familiar with this. Otherwise, take a look at the Web Scripts guide.
Within the Surf platform, web scripts are used most commonly to render components. You build your own web scripts and then drop them into the /WEB-INF/classes/alfresco/site-webscripts directory. They will then be picked up by the container and can be used by your model objects.
To tell a component to use a web script, simply set the url property to the URL of the web script.
The Freemarker rendering engine is provided by default and is used most commonly to render templates. It is also automatically used in conjunction with the web script renderer, but that is only applicable to components. With templates, you can use Freemarker directly.
If you have built Freemarker templates before and used them within Alfresco, then you will already be familiar with what they can do. If you are not familiar with Freemarker templates, see the Alfresco Freemarker Template Guide.
Within the Surf platform, your Freemarker .ftl template files can be placed into the /WEB-INF/classes/alfresco/templates directory. Then they will be picked up by the template processor and will be accessible by your model objects.
To tell a template to use a Freemarker .ftl file, set the template-type parameter to the file's path (relative to /templates).
The JSP renderer is used to render either components or templates, and provide you with access to the full Java language and the Surf platform Java API. They require knowledge of Java programming.
To use a JSP renderer, you have to write your .jsp
file and place it anywhere within your web application, though we recommend a convention of placing them under the /app/components directory.
Once you have done that, you set the renderer property to the path of the JSP (relative to the web application). This is covered in greater detail later on.
The Web Application Basics section provides a high level overview of the Surf platform data model. This section goes into detail concerning each object type.
Chrome describes the border elements around a region or a component. These border elements may include styling elements like shadows, or they may introduce drag and drop capabilities into the page. They may also introduce user-functionality like buttons for popping up component settings (as you frequently see in portals).
By default, chrome is kept to a minimum within the Surf platform. New components that are dropped onto a page will receive the default chrome for the web application (which is empty out-of-the-box).
/WEB-INF/classes/alfresco/site-data/chrome
<chrome>
<title>Sample Chrome 1</title>
<renderer>/app/sample-chrome-1.jsp</renderer>
<renderer-type>jsp</renderer-type>
</chrome>
Note: renderer is the path to the JSP file (relative to the web application)
<chrome>
<title>Sample Chrome 2</title>
<renderer>/sample/chrome-2</renderer>
<renderer-type>webscript</renderer-type>
</chrome>
Note: renderer is the URL to the web script as defined in the web script's XML description document.
Use @component to include the component in the region.
Use @componentInclude for the place where the component is to be rendered.
${htmlid}
A component type is something that the web site builder can grab at and instantiate in many places across their web application. They bind the new instances into pages by snapping them into regions (or slots). In other frameworks it is sometimes called a widget, a gadget, a portlet, or a dashlet.
/WEB-INF/classes/alfresco/site-data/component-types
<component-type>
<title>Alfresco RSS Newsfeed Component</title>
<description>Displays a configurable number of Alfresco news items</description>
<renderer-type>webscript</renderer-type>
<renderer>/sample/alfresco-newsfeed</renderer>
</component-type>
Note: renderer is the URL to the web script as defined in the web script's XML descriptor file
<component-type>
<id>jsp-sample-component-type</id>
<title>Alfresco RSS Newsfeed Component</title>
<description>Displays a configurable number of Alfresco news items</description>
<renderer-type>jsp</renderer-type>
<renderer>/app/components/alfresco-newsfeed</renderer>
</component-type>
Note: renderer is the path to the JSP file (relative to the web application)
<component-type>
<title>Alfresco RSS Newsfeed Component</title>
<description>Displays a configurable number of Alfresco news items</description>
<renderer-type>java</renderer-type>
<renderer>org.alfresco.web.site.ui.AlfrescoRSSNewsFeed</renderer>
</component-type>
Note: renderer is the class name of the Java Bean to be instantiated. This Java class must implement the Renderable interface. This is covered in a greater detail in another section.
A component is an instance of a component type that has been 'bound' into a region or a slot. It represents a binding along with the instance-specific state for that component instance.
/WEB-INF/classes/alfresco/site-data/components
<component>
<scope>page</scope>
<region-id>content</region-id>
<source-id>welcome</source-id>
<url>/test/configtest</url>
</component>
Note: A page-scoped component that is bound to content region of the welcome page. The component type is not specified, so the url property is inspected and determined to be a web script. Therefore, this component will execute the web script at url /test/configtest.
<component>
<component-type>jsp-sample-component-type</component-type>
<scope>template</scope>
<region-id>news</region-id>
<source-id>product</source-id>
</component>
Note: A template-scoped component that is bound to news region of the product template. The component type is jsp-sample-component-type which is from a previous sample. This is a JSP renderer and all of the rendering information is contained on the component type.
A Configuration object is a collection of XML, the purpose of which is general in nature. As opposed to Model objects that have structured XML persistence (with known properties and members), a Configuration has only one requirement - an id. This id can either be specified in the XML or determined from the file name.
In general, other for advanced customization, you will not need to deal with Configuration objects. They are mostly used internally by the system.
/WEB-INF/classes/alfresco/site-data/configurations
One place where Configuration objects are used is to store information that pertains to the global site. At present, there does not exist the notion of a 'web site' object. Instead, web site configuration stored as a Configuration XML file. An example is shown here (note the root-page element that specifies first page to be invoked):
<configuration>
<title>Surf Platform 3.0 Sample Site</title>
<description>Surf Platform 3.0 Sample Site</description>
<source-id>site</source-id>
<properties>
<root-page>welcome</root-page>
</properties>
</configuration>
Note: This XML could have any structure that you wish. In this sense, you can think of a Configuration object as a general purpose Model Object.
A Content Association object describes to the Surf platform how it should handle the rendition of a view for a given piece of content.
To put it another way, imagine that an end-user clicks on a link to view details about a given document. Their objective is not to open up the document, but rather to view its metadata and properties.
With the Surf platform, you might define a general purpose page called document-details-viewer
. Your intention would be to use this page anytime an end-user wants to view the details about any document in the system.
You can do this by creating a Content Association that associates the document to the Page. It can associate either a specific document (by object id) or all documents of a specific type (by object type id). It can associate to a Page instance or it could also associate to a Page Type.
The Surf platform will realize that the end-user clicked on a document and will then look to the Content Association instance to tell it where to go in order to render this content. The rendering Page and all downstream components will have the Content object available to it so that no reloads are necessary.
/WEB-INF/classes/alfresco/site-data/content-associations
<content-association>
<title>details: cm_content</title>
<source-id>{http://www.alfresco.org/model/content/1.0}content</source-id>
<dest-id>page.content.details</dest-id>
<assoc-type>page</assoc-type>
</content-association>
Note: Association between content of type {http://www.alfresco.org/model/content/1.0}content and the page with id page.content.details, which will be used to render it. This is an example of how you might use the Surf platform to render Alfresco content into a page.
A page is a navigable page in your web application. It may have associations to other pages and multiple formats keyed from it to templates. A page is a top-level object from which you can traverse either additional navigation or rendering paths.
none
, user
, or admin
)
<page>
<title>My Home Page</title>
<template-instance>home-main</template-instance>
<authentication>none</authentication>
</page>
Note: A simple unauthenticated home page. When rendering, the page will delegate to the home-main template to render the page markup.
The Page Association objects allows you to link two pages together. Most commonly, this link is of type child and is meant to depict a fixed structure like a navigation tree. However, other types are possible and there is no requirement to use Page Associations as a means to support only a single fixed tree.
Using associations, multiple trees are possible. The nature of the associations, when expanded beyond child, is very similar to that of classifiers, categories, or tags. In other words, Pages may be associated to other pages, but they may also be laterally associated to other elements. This allows for implementations of faceted navigation and tag clouds.
/WEB-INF/classes/alfresco/site-data/page-associations
<page-association>
<title>Products</title>
<source-id>page.home</source-id>
<dest-id>page.products</dest-id>
<assoc-type>child</assoc-type>
</page-association>
Note: Links the Home page to the Products page using a child relationship. At present, child relationships are the only ones understood by the Surf platform.
This sample is from share's site-data\template-instances\search.xml. It points to FreeMarker renderer classes/alfresco/templates/org/alfresco/search.ftl.
<template-instance>
<template-type>org/alfresco/search</template-type>
<properties>
</properties>
</template-instance>
The above sample works because if template-type is not known to Surf (i.e. not webscript, freemarker, etc), it assumes freemarker and looks for it at the specified URI. A way to specify this more explicitly is:
<template-instance>
<template-type>freemarker</template-type>
<url>org/alfresco/search</url>
<properties>
</properties>
<template-instance>
This example is from the default empty Surf project, and specifies Freemarker as the renderer:
<template-type>
<title>Freemarker Template Type</title>
<description>A reusable Freemarker Template Type</description>
<processor mode='view'>
<id>freemarker</id>
</processor>
</template-type>
This next example shows how to use a JSP renderer (taken from Share's main index page):
<template-type>
<title>JSP Template Type</title>
<description>A JSP Template Type</description>
<processor mode='view'>
<id>jsp</id>
<jsp-path>/myjspfile.jsp</jsp-path>
</processor>
</template-type>
The JSP path is relative to the top level application folder (for instance, /webapps/surf/ in Tomcat).
Example below is from share's search.ftl.
<link rel='stylesheet' type='text/css' href='${url.context}/templates/wiki/wiki.css' />
DispatcherServlet can be customized by changing the way it creates pages, users, links, etc. Of course, the Surf platform provides default implementations for all of these. In most cases, you will be able to use the default implementations.
Modifying the mechanisms typically involves extending one or more of the following (look in the source code for examples on how to do so):