3.0 Web Scripts Framework
Back to Web Scripts.
NOTE: This document describes features found in Alfresco v3 onwards (Older versions: v2)
- 1 Introduction
- 2 Web Script MVC
- 3 Architecture
- 4 Configuring the Framework
- 5 Available Runtimes
- 6 Available Authenticators
- 7 Available Containers
- 8 Extending the Framework (SPIs)
- 9 Research
The Web Script framework is the engine for the registration and execution of Web Scripts. This page describes the architecture of the engine and how it can be configured.
Web Script MVC
Before diving into the architecture of the framework it's worth reviewing the flow of execution when a Web Script is called.
1. A request for a given URI arrives at the Web Script Runtime.
5. The Web Script Runtime sends the rendered results back via a response using the same protocol as the URI request.
6. The Web Script client receives the response in the requested format.
In Alfresco v3, the Web Script framework architecture was refactored to allow the hosting of it in any environment, not just the Alfresco Repository server. This opens the door to applying Web Scripts to all sorts of problems (not just data services in the Repository) such as User Interface rendering in a presentation tier. In fact, the Alfresco SURF Platform, a web application framework hosts the Web Script framework for re-usable UI components.
Although Web Scripts are accessible via HTTP, their URI addressability means they can actually be hosted in a number of different environments (and therefore accessed via a protocol appropriate to the environment). The Web Script framework separates the notion of a Web Script (that is, a unit of work) and its environment (that is, the host within which the unit of work is executed), which is known as a Web Script Runtime. The most commonly used run-time is the Servlet run-time which supports the HTTP protocol for access.
A typical deployment includes an Alfresco Repository server hosting data Web Scripts with one or more Alfresco clients hosting presentation Web Scripts where communication between the two is over HTTP. The Alfresco Repository utilises the Servlet Run-time whereas a remote Web Client utilises the SURF Run-time for hosting Web Scripts. However, this is just one of many options given the following available Web Script Runtimes:
- Servlet Runtime (HTTP accessible)
- SURF Runtime (embed Web Script UI components in web-tier UI pages)
- JSR-168 Runtime (adapter between JSR-168 portlet API and Web Script)
- JSF Runtime (JSF tag to include Web Script)
- Facebook Runtime (access to Facebook API and Repository API within Web Script)
It's important to note that presentation Web Scripts may be hosted in multiple environments without code change. For example, a portlet style Web Script such as "My Tasks" which is self-contained from a user interface perspective may be developed once, but deployed as a Share Dashlet, JSR-168 portlet or URI addressable HTML page.
The Web Script framework is a Spring configured engine consisting of the following high-level components:
Most components are an implementation of an interface. This allows alternative component implementations for each environment within which to execute Web Scripts. Responsbilities of each component are:
- Runtime - entry point for execution; encapsulates the execution environment, in particular, requests, responses, authentication, and error handling.
- Container - encapsulates the host within which the Web Script executes and has access to. In particular, is the central hook point for all other services, and is responsible for providing appropriate script & template root objects to Web Scripts.
- Authenticator - responsible for authenticating requests.
- Configuration Service - reads and parses all related XML configuration files.
- Web Script Registry - maintains the index of all registered Web Scripts.
- Web Script - the unit of work to execute.
- Template Processor - responsible for executing Templates.
- Formats - registry of format to mimetype and vice-versa.
- Search Path - an ordered set (from highest to lowest precedence) of Stores for lookup of Web Script files.
We've already seen there are several types of Runtime available out-of-the-box. These Runtimes can be setup in conjunction with one the following out-of-the-box Containers:
- Presentation - a light-weight container for rendering User Interface components that can make service calls to remote data sources.
- Repository - a container for embedded use in the Alfresco Repository providing integration with transactions and direct access to content held in the Repository and services provided by the Repository.
All of these components are bound together via Spring configuration. The vanilla Web Script framework suitable for building User Interface components which can be housed in any environment is defined in
An extended version of the binding to support Repository embedding (and the Alfresco RESTful API) is defined in
Finally, an Alfresco SURF binding to support web page rendering is defined in
Configuring the Framework
Web Scripts logging is controlled via the following log4j entries:
- Web Script framework
- Repository Container
Web Server Host
To execute Web Scripts behind a firewall or proxy, you must first provide your public Web Server address, so that any links generated by Web Scripts refer back to the public server.
This is achieved by editing (or providing a custom):
and providing the host details in the following:
<config evaluator="string-compare" condition="Server"> <!-- The public web server hosting this web client --> <server> <scheme>http</scheme> <hostname>anexample</hostname> <port>8080</port> </server> </config>
HTTP Response Formats
All Web Script URLs support the format argument for specifying the response type.
Formats available "out-of-the-box" are:
- html => text/html
- text => text/plain
- xml => text/xml
- atom => application/atom+xml
- atomentry => application/atom+xml;type=entry
- atomfeed => application/atom+xml;type=feed
- rss => application/rss+xml
- json => application/json
- opensearchdescription => application/opensearchdescription+xml
- mediawiki => text/plain (Media Wiki markup)
- portlet => text/html (head & tail chopped)
- fbml => text/html
- php => text/html
- calendar => text/calendar
GET http://<host>:<port>/<contextPath>/<servicePath>/helloworld?to=fred&format=xml GET http://<host>:<port>/<contextPath>/<servicePath>/helloworld.xml?to=fred
New response formats may be supported by declaring a "Format Map" Spring Bean as follows where format short names are mapped to mimetypes
<bean parent="webscripts.formatmap"> <property name="formats"> <props> <prop key="wav">audio/x-wav</prop> </props> </property> </bean>
Multiple beans may be declared.
A custom "Format Map" may be provided for a given user agent
<bean parent="webscripts.formatmap"> <property name="agent"><value>MSIE</value></property> <property name="formats"> <props> <prop key="atom">text/xml</prop> </props> </property> </bean>
Valid agent values are (currently):
- MSIE (Micrsoft Internet Explorer)
The Servlet Runtime maps HTTP requests to Web Scripts.
It's configured just as any other servlet in web.xml:
<servlet> <servlet-name>WebScriptServlet</servlet-name> <servlet-class>org.alfresco.web.scripts.WebScriptServlet</servlet-class> <init-param> <param-name>authenticator</param-name> <param-value>webscripts.authenticator.basic</param-value> </init-param> </servlet>
The following initialization parameters are supported:
- the web script Authenticator as specified by its unique id
Multiple Web Script servlets may be configured, allowing multiple url mappings where each mapping may use a different authenticator.
<servlet-mapping> <servlet-name>WebScriptServlet</servlet-name> <url-pattern>/service/*</url-pattern> </servlet-mapping>
The following pre-defined Web Script are available:
- /alfresco/service or /alfresco/s
- mapped to HTTP Basic Authenticator
- /alfresco/wcservice or /alfresco/wcs
- mapped to Web Client Authenticator
- /alfresco/168service or /alfresco/168s
- mapped to JSR-68 Authenticator
Alfresco SURF Runtime
See Surf Platform for details.
The JSR-168 Runtime maps a portlet to a Web Script.
A JSR-168 proxy portlet class is provided which may be configured as follows:
<portlet> <description>A Portlet</description> <portlet-name>Portlet Name</portlet-name> <portlet-class>org.alfresco.web.scripts.portlet.WebScriptPortlet</portlet-class> <init-param> <param-name>authenticator</param-name> <param-value>webscripts.authenticator.jsr168.webclient</param-value> </init-param> <init-param> <name>scriptUrl</name> <value>/alfresco/service/portlet/aportlet</value> </init-param> <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports <portlet-info> <title>Portlet Title</title> <short-title>Portlet Short Title</short-title</short-title> </portlet-info> </portlet>
Note: For versions beyond 3.3 the WebScriptPortlet class has been moved to Spring Surf. Instead use:
The following initialization parameters are supported:
- authenticator (optional)
- the web script Authenticator as specified by its unique id. If not specified, the default JSR-168 authenticator (webscripts.authenticator.jsr168) is used.
- the url to the web script
The JSF Runtime maps a JSF component to a Web Script.
It's configured as follows within a JSP:
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> ... <r:webScript scriptUrl="/wcservice/<web script url>" />
The following parameters are available:
- the url of the Web Script
Authentication is handled by the Alfresco Web Client.
Alfresco is a secure server requiring authenticated access.
The Web Script framework defers authentication to a plug-in Authenticator. By default, Basic HTTP Authentication is activated. See available Runtimes for information on how to change the authentication mechanism in each runtime.
Other forms of authentication will also be considered:
HTTP Basic Authenticator
This authenticator supports HTTP Basic Authentication. The authorisation header must contain either:
- username & password
For restricted environments that do not allow the setting of HTTP Request Headers, a ticket may be passed via the URL argument 'alf_ticket'.
Alfresco Explorer Authenticator
This authenticator relies on the authentication mechanism configured into the Alfresco Explorer web client. If login is required, a redirect to the Alfresco Explorer login page is made.
This authenticator relies on the user name setup by the JSR-168 runtime. It assumes the user has already been authenticated by the Portal. The Alfresco Repository executes in the context of the Portal user.
JSR-168 Authenticator with Alfresco Explorer support
This authenticator ensures that the Alfresco Explorer web client user context is kept in sync with the Portal user. This allows Web Scripts that depend on Alfresco Explorer functionality to be used within the Portal.
Note: It is only possible to use this authenticator in the repository tier, not the presentation tier.
The Presentation Container is a vanilla container which provides basic support to Web Scripts for calling remote data sources. Its simplicity makes it ideal for hosting Web Scripts in any environment.
The Repository Container is a specialised container for embedding only in the Alfresco Repository. It hooks directly into Alfresco Repository support for transactions and authentication. It also provides Repository specific root objects to Controller Scripts and Templates.
Extending the Framework (SPIs)
The Web Script Framework has several Service Provider Interfaces for extending or replacing the behaviour of the framework. You will need to understand how to configure Spring and develop Java code to carry out this kind of change.
An Authenticator simply has to implement the interface:
All context required by the implementation should be passed in at construction time. Note, the Authenticator is constructed by the Runtime. There's only method to implement.
/** * Authenticate Web Script execution * * @param required required level of authentication * @param isGuest is Guest accessing the web script * * @return true if authorised to execute the script, false otherwise */ public boolean authenticate(RequiredAuthentication required, boolean isGuest);
The required parameter is an enumeration of the <authentication> value defined in the Web Script Description Document.
A Web Script Runtime is implemented by deriving a Java class from:
This is an abstract class requiring the following methods to be implemented:
/** * Get the web script method e.g. get, post * * @return web script method */ protected abstract String getScriptMethod(); /** * Get the web script Url * * @return web script url */ protected abstract String getScriptUrl(); /** * Create a web script request * * @param match web script matching the script method and url * @return web script request */ protected abstract WebScriptRequest createRequest(WebScriptMatch match); /** * Create a web script response * * @return web script response */ protected abstract WebScriptResponse createResponse();
/** * Create a Web Script Authenticator * * @return web script authenticator */ protected abstract Authenticator createAuthenticator();
org.alfresco.web.scripts.WebScriptRequest org.alfresco.web.scripts.WebScriptResponse org.alfresco.web.scripts.Authenticator
are also required as they are instantiated by createRequest, createResponse and createAuthenticator respectively. The helper class:
provides a skeleton implementation of WebScriptRequest given a URL string.
The following pattern is used to execute a Web Script via a Web Script Runtime:
WebScriptRuntime runtime = new CustomWebScriptRuntime(...); runtime.executeScript();
Runtime context is passed in via the constructor, for example, for a servlet, the HttpServletRequest and HttpServletResponse.
A new Web Script Runtime must be instantiated for each invocation (where the context changes), for example, for each servlet request.
A Web Script Container is implemented by deriving a Java class from:
This is an abstract class requiring the following methods to be implemented:
/** * Execute the script in the context of the provided request and response * * @param scriptReq * @param scriptRes */ public void executeScript(WebScriptRequest scriptReq, WebScriptResponse scriptRes, Authenticator auth) throws IOException;
Format Reader SPI
A Format Reader simply has to implement the interface:
It has to implement the following methods:
/** * Gets the source mimetype to convert from * * @return mimetype */ public String getSourceMimetype(); /** * Gets the Java Class to convert to * * @return Java Clas */ public Class<? extends Type> getDestinationClass(); /** * Converts mimetype to Java Object * * @param req web script request * @return Java Object */ public Type read(WebScriptRequest req); /** * Create script parameters specific to source mimetype * * @param req web script request * @param res web script response * @return map of script objects indexed by name */ public Map<String, Object> createScriptParameters(WebScriptRequest req, WebScriptResponse res);
Format Reader implementations are registered via Spring configuration:
<bean id="..." parent="webscripts.adaptorset"> <property name="readers"> <list> <bean class="x.x.x.CustomFormatReader"/> </list> </property> </bean>
- REST Resources
- REST Search Engine
- REST Ajax Atom Atom Publishing Protocol JSON OpenSearch OpenID Microformats
- Web Application Description Language (WADL) URI Templates REST Description Languages
- REST Discussion Group
- REST Blogs