Obtaining Alfresco Web Content Management (WCM)

Exclusive offer: get 50% off this eBook here
Alfresco Developer Guide

Alfresco Developer Guide — Save 50%

Customizing Alfresco with actions, web scripts, web forms, workflows, and more

$35.99    $18.00
by Jeff Potts | November 2008 | Content Management Open Source

People have been using Alfresco to manage web content since the early days of the product. In 2007, Alfresco released its formal web content management functionality that added features most people expect when they think of a Web Content Management (WCM) offering, including templating, site preview, snapshots, virtualization, and deployment. WCM is a specialized subset of the larger Enterprise Content Management (ECM) umbrella that is focused specifically on authoring, managing, and publishing files used to produce a website.

In this article by Jeff Potts, we will discuss how to create a web project and define web forms using XML Schema to allow non-technical users to create content.

You must obtain and install an additional download to enable Alfresco WCM functionality. The download includes a new Spring bean configuration file, a standalone Tomcat instance pre-configured with JARs, and server settings that allow a separate Tomcat instance (which is called the virtualization server) to run web applications stored in Alfresco WCM web folders. This capability is used when content managers "preview" an asset or a website. Just as in the core Alfresco server, you can either build the WCM distribution from source or obtain a binary distribution.

Step-by-Step: Installing Alfresco WCM

If you are building from source, the source code for Alfresco WCM is included with the source code for the rest of the product. Once the source code is checked out, all you have to do is run the distribute Ant task as follows:

 ant -f continuous.xml distribute

After several minutes, the WCM distribution will be placed in the build|dist directory of your source code's root directory. Alternatively, if you are using binaries, download the binary distribution of the Alfresco WCM extension. Where you get it depends on whether you are running Labs or Enterprise. The Labs version is available for download from http://www.alfresco.com. The Enterprise version can be downloaded from the customer or partner site using the credentials provided by your Alfresco representative. Regardless of whether you chose source or binary, you should now have an Alfresco WCM archive. For example, the Labs edition for Linux is named alfresco-labs-wcm-3b.tar.gz.

To complete the installation, follow these steps:

  1. Expand the archive into any directory that makes sense to you. For example, on my machine I use |usr|local|bin|alfresco-labs-3.0-wcm.
  2. Copy the wcm-bootstrap-context.xml file to the Alfresco server's extension directory ($TOMCAT_HOME|shared|classes|alfresco|extension).
  3. Edit the startup script (virtual_alf.sh) to ensure that the APPSERVER variable is pointing to the virtual-tomcat directory in the location to which you expanded the archive. Using the example from the previous step, the APPSERVER variable would be:
    APPSERVER=|usr|local|bin|alfresco-labs-3.0-wcm|virtual-tomcat
  4. Start the virtual server by running:
    |virtual_alf.sh start</i>
  5. Start the Alfresco server (or restart it if it was already running). You now have Alfresco with Alfresco WCM up and running. You'll test it out in the next section, but you can do a smoke test by logging in to the web client and confirming that you see the Web Projects folder under Company Home.

Creating Web Projects

A web project is a collection of assets, settings, and deployment targets that make up a website or a part of a website. Web projects are stored in web project folders, which are regular folders with a bunch of web project metadata. The number of web project folders you use to represent a site, or whether multiple sites are contained within a single web project folder is completely up to you. There is no "right way" that works for everybody. Permissions are one factor. The ability to set permissions stops at the website. Therefore, if you have multiple groups that maintain a site that are concerned with the ability of one to change the other's files, your only remedy is to split the site across web project folders. Web form and workflow sharing is another thing to think about. As you'll soon learn, workflows and web forms are defined globally, and then selectively chosen and configured by each site. Once made available to a web project, they are available to the entire web project. For example, you can't restrict the use of a web form to only a subset of the users of a particular site. SomeCo has chosen the approach of using one web project folder to manage the entire SomeCo.com website.

Step-by-Step: Creating the SomeCo Web Project

The first thing you need to do is create a new web project folder for the SomeCo website. Initially, you don't need to worry about web forms, deployment targets, or workflows. The goal is simply to create the web project and import the contents of the website.

To create the initial SomeCo web project, follow these steps:

  1. Log in as admin. Go to Web Projects under Company Home.
  2. Click Create, and then Create Web Project.
  3. Specify the name of the web project as SomeCo Corporate Site.
  4. Specify the DNS name as someco-site.
  5. Click Next for the remaining steps, taking all defaults. You'll come back later and configure some of these settings.
  6. On the summary page, click Finish.
  7. You now have a web project folder for the SomeCo corporate site. Click SomeCo Corporate Site. You should see one Staging Sandbox and one User Sandbox. Click the Browse Website button for the User Sandbox.
  8. Obtaining Alfresco Web Content Management (WCM)

  9. Now you can import SomeCo's existing website into the web project folder. Click Create, and then Bulk Import. Navigate to the "web-site" project in your Eclipse workspace. Assuming you've already run Ant for this project, there should be a ZIP file in the build folder called someco-web-site.zip. Select the file. Alfresco will import the ZIP into your User Sandbox.

What Just Happened

You just created a new web project folder for SomeCo's corporate website. But upon creation of a web project folder, there is no website to manage. This is a big disappointment for some people. The most crestfallen are those who didn't realize that Alfresco is a "decoupled" content management system—it has no frontend framework and no "default" website like "coupled" content management systems such as Drupal. This will change in the 3.0 releases as Alfresco introduces its new set of clients. But for now, it's up to you to give Alfresco a website to manage.

You just happened to have a start on the SomeCo website sitting in your Eclipse workspace. Alfresco knows how to import WAR and ZIP files, which is a convenient way to migrate the website into Alfresco for the first time. Because web project sandboxes are mountable via CIFS, simply copying the website into the sandbox via CIFS is another way to go. The difference between the two approaches is that the WAR/ZIP import can only happen once. The import action complains if an archive contains nodes that already exist in the repository.

If you haven't already done so, take a look at the contents of your sandbox. You should see index.html in the root of your User Sandbox and a someco folder that contains additional folders for CSS, images, JavaScript, and so on. The HTML file in the root is the same index.html file you deployed to the Alfresco web application in order to implement the AJAX ratings widget. Click the preview icon. (Am I the only one who thinks it looks eerily similar to the Turkish nazar talisman used to ward off the "evil eye"?) You should see the index page in a new tab or window. The list of Whitepapers won't be displayed. That's because the page is running in the context of the virtualization server, which is a different domain than your Alfresco server. Therefore, it is subject to the cross-domain restriction, which will be addressed later.

Playing Nicely in the Sandbox

Go back to the root of your web project folder. The link in the breadcrumb trail is likely to be the fastest way to navigate back. Click the Browse Website link in the Staging Sandbox. It's empty. If you were to invite another user to this website, his/her sandbox would be empty as well. Sandboxes are used to isolate changes each content owner makes, while still providing him/her the full context of the website. The Staging Sandbox represents your live website. Or in source code control terms, it is the HEAD of your site. It is assumed that whatever is in the Staging Sandbox can be safely deployed to the live website at any time. It is currently empty because you have not yet submitted any content to staging. Let's go ahead and do that now. If you click the Modified Items link in the User Sandbox, you'll see the index.html file and the someco folder. You could submit these individually. But you want everything to go to staging, so click Submit All:

Obtaining Alfresco Web Content Management (WCM)

Provide a label and a description such as initial population and click OK. It is safe to ignore the warning that a suitable workflow was not found. That's expected because you haven't configured a workflow for this web project yet.

Now the files have been submitted to staging. Here are some things to notice:

  • If you click the Preview Website link in the Staging Sandbox, you'll see the website just as you did in the User Sandbox earlier.
  • If you browse the website in the Staging Sandbox, you'll see the same files currently shown when you browse the website in your User Sandbox.
  • A snapshot of the site was automatically taken when the files were committed and is listed under Recent Snapshots:
  • Obtaining Alfresco Web Content Management (WCM)

Inviting Users

To get a feel for how sandboxes work, invite one or more users to the web project (Actions, Invite Web Project Users). The following table describes the out of the box web project roles:

 

WCM User Role

Can do these things

Content Contributor

Create and submit new content; but cannot edit or delete existing content

Content Reviewer

Create, edit, and submit new content; but cannot delete existing content

Content Collaborator

See all sandboxes, but only have full control over their own

Create, edit, and submit new content; but cannot delete existing content

Edit web project settings

Content Manager

See and modify content in all sandboxes; exert full control over all content

See and deploy snapshots and manage deployment reports

Edit web project settings

Invite new users to the web project

Delete the web project and individual sandboxes

You'll notice that each new user gets his/her own sandbox, and that the sandbox automatically contains everything that is currently in staging. If a user makes a change to his/her sandbox, it is only visible within their sandbox until they commit the change to staging. If this is done, everyone else sees the change immediately. Unlike some content management and source code control systems, there is no need for other users to do an "update" or a "get latest" to copy the latest changes from staging into their sandbox.

It is important to note that Alfresco will not merge conflicts. When a user makes a change to a file in his/her sandbox, it will be locked in all other sandboxes to prevent conflicts. If you were to customize Alfresco to disable locking, the last change would win. Alfresco would not warn you of the conflict.

The Alfresco admin user and any user with Content Manager Access can see (and work within) all User Sandboxes. Everyone else sees only their own sandboxes.

Mounting Sandboxes via CIFS

All sandboxes are individually mountable via CIFS. In fact, in staging, each snapshot is individually mountable. This gives content owners the flexibility to continue managing content in their sandbox using the tools they are familiar with. The procedure for mounting a sandbox is identical to that of mounting the regular repository via CIFS, except that you use "AVM" as the mount point instead of "Alfresco".

One difference between mounting the AVM repository through CIFS and mounting the DM repository is that the AVM repository directory structure is more complicated. For example, the path to the root of admin's sandbox in the SomeCo site is:

|someco-site--admin|HEAD|DATA|www|avm_webapps|ROOT

The first part of the path, someco-site, is the DNS name you assigned when you set up the web project. The admin string indicates which User Sandbox we are looking at. If you wanted to mount to the Staging Sandbox, the first part of the path would be someco-site without --admin. The next part of the path, HEAD, specifies the latest-and-greatest version of the website. Alternatively, you could mount a specific snapshot like this:

|someco-site--admin|VERSION|v2|DATA|www|avm_webapps|ROOT

As you might expect, the normal permissions apply. Users who aren't able to see another user's sandbox in the web client won't be able to do so through CIFS.

Alfresco Developer Guide Customizing Alfresco with actions, web scripts, web forms, workflows, and more
Published: October 2008
eBook Price: $35.99
Book Price: $59.99
See more
Select your format and quantity:

Virtualization and Layering

The AVM store makes use of "layered directories" to make virtualized copies of underlying directories available while isolating changes to individual layers. A user sandbox, for example, is simply a layer on top of the Staging directory. Let's look at a simple example.

Suppose we have a layer with a folder and a piece of content. This base layer could be the Staging Sandbox or just as easily be any other AVM store in the repository:

Obtaining Alfresco Web Content Management (WCM)

A Transparent Layer on top of the Base Layer can see the objects beneath it:

Obtaining Alfresco Web Content Management (WCM)

When new objects are added to the lower layer, they are immediately visible in the top layer:

Obtaining Alfresco Web Content Management (WCM)o

Objects can be added to the top layer without affecting objects in lower layers:

Obtaining Alfresco Web Content Management (WCM)

If a background object is edited, a copy is placed in the upper layer:

Obtaining Alfresco Web Content Management (WCM)

When modified items are submitted to staging, an AVM merge is performed that merges the Transparent Layer with the Base Layer. This explains why all changes committed to Staging are automatically visible to all other User Sandboxes immediately with no further synchronization required:

Obtaining Alfresco Web Content Management (WCM)

Note that using the AVM API, you can arbitrarily create as many layers as you want.

Creating Web Forms

In the previous example you created a web project folder and imported the SomeCo website. For some sites, that may be enough. In a bare bones implementation, once the site is migrated to the repository, life continues pretty much as normal. Content providers use authoring tools to save content via CIFS or edit content directly in the web client, and the system handles review and approval, snapshots, and deployment.

The next step for many people, however, is to identify subsections of the site that lend themselves to being managed through web forms. Web forms allow non-technical content owners to manage, approve, and deploy their own web content. Good candidates for web forms include content that:

  • Is managed by non-technical content owners. Technical people such as designers, developers, and technical writers are not the target audience for web forms.
  • Changes fairly often. You don't want to go to the trouble of creating templates if the content is created once and never changed again.
  • Is more than one or two pages. Similar to the previous point, you may not want to invest time in creating and maintaining a web form if there are only a handful of pages that will ever be created using that web form.
  • Has multiple output formats. One of the beauties of a web form is that its data is stored as XML, and then optionally transformed into one or more output formats. Content that needs to be available as HTML, RSS, and mobile-friendly HTML, for example, might be good to manage with web forms because it can be entered once and rendered in each desired format.
  • Has a structure that might be generic enough to be reused in multiple places within a site or across multiple sites. Examples include content types such as "alert", "news item", "contact information", or "information request form".
  • Has a relatively fixed and simple structure. If you think of the spectrum of structured content from SGML-like structured authoring tools on one end to very unstructured tools such as word processors, page layout tools, or graphics tools on the other, web forms are somewhere to the left of center. A web form is structured—it has a fixed number of fields that are ordered a certain way. But a web form would never be used as a replacement for editing highly complex XML documents such as flight maintenance manuals.

These are not hard-and-fast rules. There are those that will move 100% of their site into web forms. As long as the ultimate value of WCM is achieved, making it easier to manage your website, by all means go for it!

Step-by-Step: Creating a SomeCo Press Release Web Form

SomeCo has decided to use web forms to manage press releases because the corporate communications team is looking to remove the web team bottleneck. The web team is happy because it is looking forward to getting away from mundane "please convert this from Microsoft Word to HTML and post it" tasks and moving toward more value-added tasks such as information architecture and user interface design.

The press release is simple. It includes a title, subtitle, location, date, body, contact information, and footer. The index or list of press releases will be addressed in another example.

Creating the press release web form involves creating an XML Schema (XSD) document to define the data structure and a presentation rendering file (you'll use FreeMarker in this example), configuring the web form in the data dictionary, and finally, adding the web form to the SomeCo web site. Web forms may seem similar to content types, and they are. But don't be confused. A web form XSD defines the structure of an XML document. The data saved by the web form will be XML conforming to the XSD. A customized content model, on the other hand, defines metadata on the object. Web form data lives in a file. Object metadata lives in the relational database.

To implement a simple press release form, follow these steps:

  1. Create a new XML Schema file in Eclipse in the |src|forms folder. This book won't cover XSD in any depth. I recommend you to pick up a book on XML Schema, use XSD creation tools to save some time, or refer to other XSDs in the source code as examples, or all three. For SomeCo's press release, the XSD begins by defining the XML Schema, Alfresco, and SomeCo Press Release namespaces:
    <?xml version="1.0"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:pr="http://www.someco.com/corp/pr"
    xmlns:alf="http://www.alfresco.org"
    targetNamespace="http://www.someco.com/corp/pr"
    elementFormDefault="qualified">
  2. Next, add the root element for press_release. In schema terms, the press_release element is a complex type made up of a sequence that includes the fields you need to capture in order to produce a press release. Add the schema definition XML to define the fields (title, sub_title,location, date, body, company_footer, and company_info) and close out the xs:schema tag:
    <!-- defines the form for creating a press release -->
    <xs:element name="press_release">
    <xs:complexType>
    <xs:sequence>
    <xs:element name="title" type="xs:normalizedString"/>
    <xs:element name="sub_title" type=
    "xs:normalizedString"/>
    <xs:element name="location" type=
    "xs:normalizedString" default="Austin, TX"/>
    <xs:element name="date" type="xs:date"/>
    <xs:element name="body" type="xs:string" minOccurs=
    "1" maxOccurs="1">
    <xs:annotation>
    <xs:appinfo>
    <alf:appearance>custom</alf:appearance>
    </xs:appinfo>
    </xs:annotation>
    </xs:element>
    <xs:element name="company_footer" type="xs:string"
    minOccurs="0" maxOccurs="unbounded"/>
    <xs:element name="contact_info" type="xs:string"
    minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    </xs:complexType>
    </xs:element>
    </xs:schema>
  3. Save the XSD file.
  4. Create a new FreeMarker file in |src|forms called press-release.ftl to use as the rendering engine presentation file. The FreeMarker needs to convert the XML saved by the web form into an HTML version of the press release. You'll see an XSLT example shortly. Begin the FTL by declaring the press release prefix and assigning the root press_release element to a variable:
    <#ftl ns_prefixes={"pr":"http://www.someco.com/corp/pr"}>
    <#assign press_release = .vars["pr:press_release"]>
  5. Then, add the markup for the press release, inserting FreeMarker calls to extract data from the XML where necessary:
    <div class="node">
    <h2>${press_release["pr:sub_title"]}</h2>
    <p><p>${press_release["pr:location"]} - ${press_release
    ["pr:date"]} - ${press_release["pr:body"]}
    <#list press_release["pr:company_footer"] as cf>
    <p>${cf}</p>
    </#list>
    <#list press_release["pr:contact_info"] as ci>
    <p>${ci}</p>
    </#list>
    </p></p>
    <div class="clearfix"></div>
    </div>
    <div class="clearfix"></div>
  6. Save the FTL file.
  7. Log in as admin.
  8. Go to Data Dictionary, and then Web Forms.
  9. Click Create, and then Create Web Form.
  10. Browse for the schema.
  11. Alfresco needs to know where to store the web form XML. In this example, you'll store it in |news|press-releases|data. So specify the output path pattern:
    /${webapp}/news/press-releases/data/${name}.xml
    Obtaining Alfresco Web Content Management (WCM)
  12. Click Next.
  13. Select the Rendering Engine template file you created earlier. It should be in src|web|forms|press-release.ftl.
  14. Alfresco needs to know where to store the rendition. This markup is going to eventually be read by an AJAX call from the press release list page. The call expects the press release to reside in |ajaxnews|news|press-releases, so specify the following output path pattern:
    /${webapp}/ajaxnews/news/press-releases/${name}.${extension}
    Obtaining Alfresco Web Content Management (WCM)
  15. Click Add to List.
    Obtaining Alfresco Web Content Management (WCM)
  16. Click Next. Specify No, not now to defer associating a workflow with this web form.
  17. Click Next, then Finish.
  18. The web form has been defined in the data dictionary. Now, any web project can choose to use it. You need to make sure the SomeCo web project is configured to use the form. Go to the web project then click Actions, and then Edit Web Project Settings.
  19. Click Next until you get to the web form step. Click Add to list.
    Obtaining Alfresco Web Content Management (WCM)
  20. Click Finish.

Test the web form. You can either create content using the web form by using the Create Content link from the list of web forms in the sandbox as shown here, or you can browse the website and click Create, and then Create Web Content:

Obtaining Alfresco Web Content Management (WCM)

Either way, you will launch the create web content wizard. In the first step, specify a name for the content. The next step launches the web form:

Obtaining Alfresco Web Content Management (WCM)

Click the preview icon (the little eyeball) to preview the generated press release HTML:

Obtaining Alfresco Web Content Management (WCM)

When you are happy with the content, click Finish to save the content to the repository.

Did preview work? If not, the first thing to check is whether your virtualization server is running. Preview depends on it. Next, are you connected to the Internet? Unless you've changed the alfrescovirtserver.properties file in the virtualization server's virtual-tomcat|conf directory, Alfresco expects connectivity to the alfrescodemo.net domain.

Alfresco Developer Guide Customizing Alfresco with actions, web scripts, web forms, workflows, and more
Published: October 2008
eBook Price: $35.99
Book Price: $59.99
See more
Select your format and quantity:

Mapping XML Schema Types to Web Form Controls

The type of control that appears in the web form depends on the XML Schema data type. In the press release example, you saw that the XSD type xs:normalizedString maps to a text input field, the xs:date type maps to a date picker, and an xs:string maps to a rich text editor.

In addition to types, XSD supports annotations. In the context of XForms and Alfresco, annotations allow you to fine-tune the appearance of web form controls. For example, in the press-release XSD, you used an annotation to set the appearance attribute of the body element to custom. If you take a look at web-client-configwcm.xml, you'll see where this is configured:

<widget xforms-type="xf:textarea"
appearance="custom"
javascript-class-name="alfresco.xforms.RichTextEditor">
<param name=
"theme_advanced_buttons1">bold,italic,underline,strikethrough,
separator,fontselect,fontsizeselect</param>
<param name=
"theme_advanced_buttons2">link,unlink,image,separator,justifyleft,
justifycenter,justifyright,justifyfull,separator,bullist,numlist,
separator,undo,redo,separator,forecolor,backcolor</param>
<param name="height">600</param>
<param name="mode">exact</param>
<param name="force_p_newlines">true</param>
<param name="apply_source_formatting">true</param>
<param name="plugins">table</param>
<param name="theme_advanced_buttons3">tablecontrols</param>
</widget>

Here's how to make sense of what's happening:

  1. You declared body to be an xs:string.
  2. Alfresco's embedded XForms implementation, Chiba, maps xs:string to xf:textarea.
  3. You annotated body to have an appearance of custom.
  4. In web-client-config-wcm.xml, the xf:textarea widget is defined for the custom appearance as being implemented with the TinyMCE Rich Text Editor, with a specific set of buttons, the table plug-in, and so on. When the form is rendered, the widget uses the parameters from web-client-configwcm.xml to render itself. The parameters include things such as the editor component to use, the specific set of buttons to display, and so on.

The following table, a subset of what's on the Alfresco wiki, shows some of the more common XSD datatypes supported by Alfresco, the appearance annotations they support, and how they map to Alfresco web form controls:

XML Schema Datatype

"alf:appearance" Annotations Supported

XForms Control

Alfresco Web Form UI Control

xs:string

Full

Default

Minimal

xf:textarea

xf:textarea

xf:textarea

Rich text editor

Rich text editor, min.

Text area

xs:normalizedString

None

xf:input

Text field

xs:boolean

None

xf:input

Checkbox

xs:double

None

xf:input

Text field

xs:decimal

None

xf:input

Text field

xs:float

None

xf:input

Text field

xs:integer, xs:double, xs:decimal, xs:float with inclusive bounds

None

xf:range

Slider

xs:anyType

None

xf:textarea

Rich text editor

xs:anyURI

Full

Minimal

Configurable

xf:upload

xf:upload

xf:upload

File picker

Text field

File picker with filters

xs:anyType

None

xf:textarea

Rich text editor

Localizing Web Forms with Labels and Alerts

In addition to using annotations to customize the appearance of a control, you can also use annotations to override the default label and field validation alert message. The override can be static text or a localized string.

In the press release example, you created an element called sub_title. By default, this results in a label called Sub Title and the alert message: "Please provide a valid value for Sub Title. Sub Title is a required NormalizedString value". What if, instead of Sub Title, you wanted to keep the sub_title element in the XML, but have the web form show Lead-in and maybe give a friendlier alert message? Annotations let you do that. In this case, the sub_title element would be updated as follows:

<xs:element name="sub_title" type="xs:normalizedString">
<xs:annotation>
<xs:appinfo>
<alf:label>${leadIn}</alf:label>
<alf:alert>${leadInAlert}</alf:alert>
</xs:appinfo>
</xs:annotation>
</xs:element>

The corresponding key and value for the label and alert would then be added to one of three places:

  • A strings.properties file in the web form's folder (Data Dictionary|Web Forms|press-release, in this example)
  • A strings.properties file in the Web Forms folder, which would be used globally across all web forms
  • Within the custom webclient.properties file, which would be packaged and deployed with your other extensions

Externalizing labels and alerts to properties files isn't required. You could have put the values directly in the annotations as string literals, but externalizing the strings is better because the web form labels and alerts can then be localized.

If you were to compose a web form with these changes in place, the label and alert message would show the annotated values as shown here:

Obtaining Alfresco Web Content Management (WCM)

Generating XSD Dynamically

You didn't have a reason to do this for SomeCo, but there might be times when the XSD cannot be fully expressed at design time. For example, suppose you wanted to populate a drop-down list on a web form with the results of an SQL query to some external database. Alfresco's sample website that ships with Alfresco WCM has an example of this. In this case, it uses a query against the web project rather than a database, but the same technique applies. In its press release XSD (every WCM vendor on Earth uses "press release" as an example), it uses an xs:include tag that points to a JSP, which defines part of its schema:

<xs:include schemaLocation="/media/releases/get_company_footer_
choices_simple_type.jsp"/>

Later in the XSD, it adds an element that refers to a type defined by the dynamic schema:

<xs:element name="include_company_footer" type=
"pr:company_footer_choices" minOccurs="1" maxOccurs="unbounded"/>

Where does that pr:company_footer_choices XSD type get defined? When the include is processed and the JSP is invoked, the result is the XML Schema that defines the type and includes the query results. Here is the relevant chunk of the JSP referred to by the xs:include:

<jsp:root>
...
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:alf="http://www.alfresco.org"
elementFormDefault="qualified">
<xs:simpleType name="company_footer_choices">
<xs:restriction base="xs:normalizedString">
<!-- call into CompanyFooterBean to retrieve all company
footers -->
<c:forEach items="${pr:getCompanyFooterChoices(pageContext)}"
var="companyFooter">
<jsp:element name="xs:enumeration">
<!-- this is the file name of the company footer -->
<jsp:attribute name="value"><c:out value=
"${companyFooter.fileName}"/></jsp:attribute>
<jsp:body>
<xs:annotation>
<xs:appinfo>
<!-- this produces the label displayed in the
combobox within the press release form -->
<alf:label><c:out value=
"${companyFooter.name}"/></alf:label>
</xs:appinfo>
</xs:annotation>
</jsp:body>
</jsp:element>
</c:forEach>
</xs:restriction>
</xs:simpleType>
</xs:schema>

You can use this same pattern in your projects to dynamically generate XSD. But remember that the JSP is invoked in the context of the web project. That means the virtualization server has to be running and the web project has to have everything it needs to render the JSP. In Alfresco's press release example, that includes the JSP, a tag library, a bean, and dependent JARs.

Step-by-Step: Creating a Press Release Index Page

You now have a press release web form that has one presentation rendition. But SomeCo's website needs to show a list of press releases. The user experience team wants to create a press release index page that shows a list of press release titles alongside the body of the first press release in the list. Clicking another press release title should load the body of the press release without requiring an entire page refresh.

The trick here is deciding how to grab the list of press releases and when to generate the press release index page. There are a few options:

  • Build a static version of the press release index page. Use XSLT or FreeMarker to build the list of press release titles. Either add the index page generation as an additional rendition to the press release web form or create a separate web form just for the press release index.
  • Use JSP to dynamically render the press release index page. The JSP can build the list of press release titles and links by querying the repository with the AVMRemote API.
  • Use JSP as in the previous option, but use a call to a web script to build the list of press release titles instead of the AVMRemote API. Web scripts are preferred over the AVM Remote API.

The best choice depends entirely on how you've chosen to set up your site and deploy content. In a completely static site, your only choice will be to render the press release list prior to deployment. You'll have to decide whether you want to generate the list every time a web form is saved, in which case you could add the press release list as an additional rendition to the existing press release web form, or you can create a separate web form for the list.

If you've decided to include dynamic calls to Alfresco as a part of your site's architecture, you may decide that generating the press release list dynamically (either through the AVMRemote API or a web script) makes the most sense. The nice thing about this approach is that you don't have to worry about when to generate the list, but you do have to pay attention to potential timing issues. If your pages depend on any content that is statically deployed (maybe a video that accompanies the press release, for example), the query on the index page might pick up a press release title by querying staging. However, the static assets have yet to be deployed to the frontend.

Let's run through the "static index page, list generated at press release author time" example. The previous example used FreeMarker. Let's use XSLT this time, though FreeMarker would have worked just as well. By the end of this example, you'll have a new XSLT presentation file to add as an additional rendition to the existing press release web form. Every time a press release gets saved, the index page will be regenerated.

To implement the press release list page, follow these steps:

  1. Create a new XSL file in the client-extensions Eclipse project under src|formscalled press-release-index.xsl by copying the press-release-index.xsl.sample file from the source code.
  2. The HTML for the press release index page is a bit involved. It has been copied into the press-release-index.xsl.sample file for you with the sections relevant to this example fl agged with "TODO" comments. Search for the first "TODO". Add an XSL variable that makes a call to the AVMRemote function, parseXMLDocuments, to retrieve a list of press release XML:
    <xsl:variable name="pressReleaseList" select="alf:
    parseXMLDocuments('press-release', '/news/press-releases/data')"
    />
  3. Now search for the next "TODO". This is where the list of press release titles should go. Use an xsl:for-each to iterate over the list, and output the press release title and a link to the press release HTML. This snippet includes a call to an XSL function you are about to add, which is used to change the suffix of the target press release file from xml to html:
    <xsl:for-each select="$pressReleaseList">
    <xsl:variable name="selectedVar">
    <xsl:choose>
    <xsl:when test="position() = 1">selected</xsl:when>
    <xsl:otherwise>leaf</xsl:otherwise>
    </xsl:choose>
    </xsl:variable>
    <li class="{$selectedVar}">
    <xsl:variable name="fileNameFixed"><xsl:call-template name=
    "fixFileName"><xsl:with-param name="fileName"><xsl:value-of
    select="@alf:file_name" /></xsl:with-param>
    </xsl:call-template></xsl:variable>
    <a href="{$fileNameFixed}"><xsl:value-of select="pr:title" />
    <span class="bioListTitle"></span>
    </a>
    </li>
    </xsl:for-each>
  4. The next "TODO" is to use a couple of xsl:value-of statements to output the title and body of the first press release in the list:
    <h2>
    <xsl:value-of select="$pressReleaseList[1]/pr:title" />
    </h2>
    <p></p><p></p>
    <xsl:value-of select="$pressReleaseList[1]/pr:body" />
    <div class="clearfix"></div>
  5. The final "TODO" is to add the fixFileName function referred to in the press release iterator. The function simply does a substring replacement on the xml suffix:
    <xsl:template name="fixFileName">
    <xsl:param name="fileName" />
    <xsl:value-of select="concat(substring-before($fileName, '.xml')
    , '.html')" />
    </xsl:template>
  6. Save the file.
  7. Now you need to add the new press release index presentation as an additional rendering engine template to the press release web form. This will cause the index page to be regenerated every time a new press release is created. Go to Data Dictionary|Web Forms and click the Edit Web Form icon.
  8. Click Next to display the Configure Templates dialog.
  9. Browse for the newly created press-release-index.xsl file.
  10. Set the output path to:
    ${webapp}/news/press-releases/index.${extension}
  11. Click Add to List.
    Obtaining Alfresco Web Content Management (WCM)
  12.  

  13. Click Next until the Finish button is enabled, and then click Finish.
  14. You may find that the existing web project needs to have the web form dropped and re-added for the new change to take effect smoothly. Go to the web project, click Actions and then Edit Web Project Settings, and then click Next until you get to the Configure Web Forms step in the wizard. Click the trash can icon to remove it from the list, and then click Add to List, and then Finish.

Now test your change. You should be able to edit the existing web content or create a new press release, and see that both the press release and the press release list get generated. Preview the index page to validate that the AJAX call works appropriately.

Making Changes to an Existing Web Form

As you saw in the previous example, certain changes made to the web form definition in the data dictionary may require touching the web form configuration in the individual web project. If these are repeatable in your environment, they should probably be logged as bugs in Jira. If you do see quirky behavior after making a web form change, it can usually be addressed by removing and re-adding the web form to the web project. Of course, if you have many web projects this could get tedious quickly.

Changes to an XSD when web form data has already been created can be tricky. If you are just doing something simple such as adding annotations, you can make the change and update the XSD using the Update action on the XSD object in the web form folder. But if you are changing the data structure, you should first test that change on a development Alfresco instance to see how existing web form XML content will behave after the change. Depending on how that goes, you may have to use a script to update the existing XML to be compatible with the new XSD.

Using Web Forms Outside the WCM User Interface

In the Labs edition, Alfresco has added forms capability to the web client without requiring a web project. This is handy when you need non-technical users to author XML, which you then subsequently process with rules, actions, web scripts, or some other mechanism.

The differences between WCM forms and non-WCM forms are:

  • Non-WCM forms do not have associated presentation rendition files. Forms simply save as XML. If you need to transform the XML into one or more renditions, you can use rule actions to fire when the XML gets created.
  • Correspondingly, because there is no transformation, there is no need for a Preview to see how the renditions transformed the XML.
  • Forms do not have an output path. XML data is saved where the user is sitting in the folder structure when he/she clicks Create Content.

The ability to do simple XML authoring in the web client outside a web site's context is often requested as a feature. So, hopefully, it will "graduate" from the Labs edition to the Enterprise edition soon.

Summary

In this article you looked at a simple application of Alfresco to create a web project and define web forms using XML Schema to allow non-technical users to create content.

About the Author :


Jeff Potts

Jeff Potts leads the industry’s largest group of certified Alfresco consultants as the Director of the Enterprise Content Management (ECM) Practice at Optaros. Jeff brings over 10 years of ECM practice leadership and over 16 years of IT and technology implementation experience in IT departments and professional services organizations.

Jeff began working with and blogging about Alfresco in November of 2005. In 2006 and 2007, Jeff published a series of Alfresco tutorials and published them on his blog, ecmarchitect.com. That work, together with other Community activity in Alfresco's forum, wiki site, and Jira earned him Alfresco's 2007 Community Contributor of the Year Award. The same year, Optaros earned Alfresco's Global Partner of the Year and Implementation of the Year awards.

Jeff’s areas of business expertise include document management, content management, workflow, collaboration, portals, and search. Throughout his consulting career he has worked on a number of projects for Fortune 500 clients across the Media & Entertainment, Airline, Consumer Packaged Goods, and Retail sectors.

Prior to Optaros, Mr. Potts was a Vice President at Hitachi Consulting (formerly Navigator Systems, Inc.) where he founded and grew the ECM practice around legacy knowledge management, document management, Web Content Management (WCM), and collaboration solutions in addition to custom development.

Contact Jeff Potts

Books From Packt

Joomla! Web Security
Joomla! Web Security

WordPress Theme Design
WordPress Theme Design

Moodle Administration
Moodle Administration

WordPress Complete
WordPress Complete

Building Powerful and Robust Websites with Drupal 6
Building Powerful and Robust Websites with Drupal 6

Building Websites with Joomla! 1.5
Building Websites with Joomla! 1.5

Drupal 6 Themes
Drupal 6 Themes

Professional Plone Development
Professional Plone Development

 


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software