Copyright © 2009-2010 UCS - unique computing solutions gmbh
Abstract
[fleXive] CMS is a Content Management System based on Java Enterprise Edition 5 and JavaServer Faces 1.2.
Its main features include:
To install [fleXive] CMS on your machine, you need to have Java installed (version 5 or later). You can download the current version of Java from java.sun.com.
Download and run the installer from the download page.
If your operating system does not launch Java archives (JARs) automatically,
open a command line and type
java -jar [path-to-installer.jar]
to launch the installer.
The installer will prepare a fully functional installation on your local machine. After the installation process is finished, start the CMS server using the application menu shortcut or manually with the start.sh/start.bat scripts in the root installation directory.
When the server is running and you first access the CMS through the browser (http://localhost:8080),
you are redirected to the [fleXive] backend. Complete the installation by logging in with the
default superuser credentials,
supervisor/supervisor,
and wait a few moments until the initialization is complete.
If something went wrong, please stop by in our forum.
After the initialization was completed, you can access the actual CMS website on http://localhost:8080. By default, there are three example CMS users available:
cms-author/cms-author
can create pages,
cms-editor/cms-editor
can modify all contents and publish changes, and
cms-admin/cms-admin
can edit the page templates.
To login, click on the "Login" link in the upper right corner or open http://localhost:8080/admin/login.xhtml. Use the default admin user and password to login (cms-admin/cms-admin).
After successful login the CMS control bar appears above the page:

Here you can perform the common tasks for managing the web site:
Edit allows you to edit the current page,
New Page is for creating new pages,
Templates allows you to edit and assign the templates of the current page,
Actions is for publishing changes from the edit mode to the live website,
and the select box in the middle provides a sitemap as quick navigation. On the far right the current user is displayed, as well as the current view settings:
Templates: edit and Contents: edit indicate that the "edit" versions of templates and contents are shown. You can toggle both settings independently to preview the content changes with the live template settings, or the live contents with the anticipated template changes. For now, leave both settings on "edit", this is by far the most common mode unless you are heavily editing both contents and templates.
Let's create a new page. Click on the "New Page" icon in the administration bar and enter the new page data:

The
Page path
determines the initial URI of this page (in this case,
first_page.xhtml),
and the
Page title
is used as the HTML page title e.g. in the website navigation or in the HTML page title.
You can change both values afterwards.
For now, leave the other input fields. They are set to sensible defaults based on the current page.
Click on Create child page to actually create the new page. You will then see the new page in the navigation panel on the left and in the sitemap in the administration bar:

What are those funny blobs near the reference our new page? Clicking on them reveals a context menu that can be used to move the page around (in the navigation pane) or to edit the page content (in the content pane). The color indicates the publishing state of the page:
To check this, click on the "Contents: edit" link in the upper right corner. Now you see the website as an anonymous visitor would see it currently: our new page has not been published, thus it is not visible to anyone but other CMS users. Click on "Contents: live" again to switch back to edit mode.
Now, let's fill our new page with content. Navigate to the new page by clicking on the link. The page renders OK, but is devoid of any content:

To change this, click on the Edit button in the upper left corner. This opens the page editor in an overlay popup window:

The amount of buttons and inputs may seem intimidating at first, but it's actually pretty simple:
The Templates box is a group of properties that determines the templates to be used for this page.
Path name and title are the page parameters you set when creating the page.
Node reference is a CMS-internal setting (it should not be visible actually), please ignore it for now.
Each property has a few control buttons on the left: The first opens a context-sensitive menu for this node, the arrows can be used to change the property position (irrelevant for our current page template), and the plus/minus symbols add an additional line for the field (if possible) or remove the field (unless it is mandatory).
To add page content, we have to create a property that is not yet visible. To do this, click on a context menu icon on the far left:

You get a selection of properties that can be added to the current instance:

Since we want to add text content, select Paragraph and click Insert selected assignments. This creates a new paragraph with the properties that are defined by our page type:

In the default page type, the page content is described by paragraphs with a title, a HTML text body, and an optional image. The text fields are multilingual, so you can use a single content instance for different languages. Enter some text (you can leave the image property empty for now) and click the Save content button on the bottom of the page. The content instance is saved and the paragraph should be rendered immediately.
Now that you created a new page you want the rest of the world to see it. To do this, navigate to the page and click on the Actions button in the toolbar. Currently there are two actions available, Publish and Publish all:

Publish all publishes a complete part of a web page, i.e. the page itself and all subpages. Since we only have a single page, it's sufficient to click on Publish. This will add the page to the live website navigation and make the content readable for everyone. You can verify this by clicking on the "Content: edit" link in the upper right corner again. You can also logout and view the page as an anonymous user, but be sure to refresh it since the CMS allows browsers to cache public pages for a certain amount of time (currently 30 minutes).
Congratulations, you now have the tools to build pages with [fleXive] CMS. However, there is still a lot of stuff to know to really use the possibilities that [fleXive] provides:
We will cover these topics eventually, but for the moment let's take a step back and look at the fundamental concepts we used for building this page in the next chapter.
Websites in [fleXive] CMS are organized in a hierarchical page tree similar to the folders of a file system.
When logging into the backend application under http://localhost:8080/flexive/, the page tree is visible in the left panel:

Pages are [fleXive] content instances derived from a common type, CMS_PAGE. CMS_PAGE defines the bare minimum of properties that a [fleXive] CMS page has:
The unique name for the URI of this page.
The (possibly localized) title of this page that is used for building a site map or
navigation panel with
cms:navigation
and can also be used for the HTML
<title>
element.
The template that is used for rendering this page as a standalone frontend page (i.e. with complete HTML headers and so on). It can use content templates to defer the rendering of the page content to a separate template.
The template to be used for rendering a teaser (short preview of the content for embeddeding in another page) for this page.
Since every website has different requirements on how its content is organized, [fleXive] CMS does not impose a predefined structure for page contents.
Instead, the user controls both data structures and display templates, making it a very versatile site generation tool similar to a Structured Wiki.
An example is the CMS_BASIC_PAGE type that is used for the packaged example website. In addition to the properties listed above, this type defines the following properties:
The teaser definition. Briefly describes this content when listed on another page.
A list of paragraphs that make up the page content. Each paragraph can contain a title, HTML text, and an image.
Templates determine how a page is rendered to the user. Usually the output is some sort of HTML, but you can also create templates for different output formats like plain text or binary formats like PDF.
Templating is based on the Facelets XHTML templating language for JavaServer Faces 1.2. A basic template could look like this:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:fx="http://www.flexive.com/jsf/core" xmlns:cms="http://www.flexive.com/jsf/cms"> <fx:content var="page" pk="#{fxPageBean.pagePK}"> <head> <title>#{page.title}</title> </head> <body> <h1> <cms:value value="#{page.title}"/> </h1> <fx:children var="paragraph" value="#{page}" property="paragraph"> <ui:fragment rendered="#{not empty paragraph.title}"> <h2 class="title"> <cms:value value="#{paragraph.title}"/> </h2> </ui:fragment> <p class="paragraph"> <cms:image value="#{paragraph.image}"/> <cms:value value="#{paragraph.text}"/> </p> </fx:children> </body> </fx:content> </html>
For someone familiar with JSF, this template contains no surprises. The CMS-specific part is the
<fx:content> tag that provides the all page properties in the variable
#{page}.
<cms:value> is used to render the title. Then the paragraph(s) of the
page are rendered using the <fx:children> component that iterates
over all paragraphs of the page.
A [fleXive] CMS page exists in two mostly independent versions:
The live version is the public-facing version of the website.
The edit version is only visible to authorized CMS users. Changes can be made in the edit version and even follow a custom workflow, before they eventually get published to the live website.
Contents can be published individually, or as a group. In the latter case, all contents of a part of the website including their templates are published in one sweep.
A user accessing a CMS page falls into one of the following categories:
A visitor can only view published contents, while an administrator has complete access to the CMS. Authors and Editors are CMS users that manage the page content.
Authors generate page content. They can create articles and make changes to their own articles, but cannot modify articles created by other users. They also cannot publish contents, and cannot undo publishing of contents (including their own).
Editors manage the website. They can edit all contents, publish contents, remove contents from the website. They cannot, however, change page templates.
Administrators are the CMS superusers. They are the only ones who can change the page templates. They also can create new users and data structures in the backend.
A user is member of one of these user groups, all users of a group share the same permission configuration.
A page is a single content instance of a predefined, structured type. It contains all non-presentational content in all languages that are supported by the website.
Pages are kept in a hierarchical, filesystem-like structure.
A page determines how it should be rendered by referencing templates.
A template is a Facelets XHTML template for JavaServer Faces 1.2.
A page can include and reference arbitrary contents, either through common subfolders referenced by the template or through SQL-like queries with FxSQL.
A content included on a page either knows how to render itself in a given context through an assigned template, or the enclosing template specifies a template to render the child content.
The website exists in a live and in an edit version. The former is the public-facing website, the latter is only accessible to authorized CMS users and is used to prepare the next live version of the website.
User groups control the permissions of a user. The predefined groups are Author, Editor, and Administrator.
Page templates usually load the content associated with the page with the fx:content tag:
<fx:content var="page" pk="#{fxPageBean.pagePK}"> ... (page content) ... </fx:content>
The properties of the content type can then be accessed through the
page
variable, e.g.
#{page.title}
or
#{page.paragraph[0].title}.
Please check the
[fleXive] documentation on fx:content
for further details.
Renders an image tag, based on fx:thumbnail and fx:fxValueInput.
PREVIEW1,
PREVIEW2,
PREVIEW3,
SCREENVIEW,
ORIGINAL
(default).
Renders content values, based on fx:fxValueInput.
This field will turn into an edit component when inline editing is activated.
If this functionality is not required, the output is similar to writing
the (string) value directly, e.g. through
#{page.field}.
Apply a template on a content.
The goal is to achieve a decoupling of the page template (which may be shared for many different types of pages) from the rendering of the actual page content (e.g. an article, news item, product description, etc.).
For example, the default page template uses the component like this:
<cms:applyTemplate template="/templates/content"/>.
The templating engine will now perform two steps:
Lookup the template defined in
/templates/content
for the current page content (defined through the page URL).
Render the page content using this template and include the output in the page.
The current FxContent entry is exposed to the body in the variable "content", the page path in the variable "path", and the node ID in "nodeId" (as in cms:renderChildren).
This component is vital for including other contents into the current page. In its current form, it only supports rendering the contents stored in a subfolder of the page (including the page itself, i.e. all page contents linked under the current page), or from an absolute folder reference.
There are two modes of operation:
When the template attribute is set, all contents that contain a template reference under this path are rendered using the corresponding template. I.e. the contents themselves control how they are rendered, the caller only determines which logical template class is selected (teaser templates).
When the type attribute is set, the template is provided in the tag body.
The template can use the following variables to access the content to be rendered:
The node content, as exposed by fx:content .
the name of the template assignment,
including the root type that defines it (e.g.
CMS_PAGE/TEMPLATES/PAGE
or
CMS_MY_ARTICLE/TEMPLATES/SNIPPET
).
This implicitly limits the type of the rendered children, which must have a
content type derived from this root type.
If template is not set, the template must be provided in the tag body and the
type
attribute must be set to specify the root type.
the base type of the contents to be rendered, e.g.
CMS_PAGE
(if
template
is not set, otherwise this attribute will be ignored,
default: CMS_PAGE).
header markup of an item. To work around entity encoding issues
with some browsers (even if the entities are correctly escaped, some
browsers replace the escaped entities when editing the template
in a textarea), you may want to use the
cms:openTag
and
cms:closeTag
functions instead. For example:
#{cms:openTag('li')}
instead of
<li>.
This component renders links for a part of the page tree, e.g. for creating the website navigation menu.
Please refer to the [fleXive] documentation on fx:navigation for a complete description of its parameters. A short snippet using this component can be found in the navigation example.
Render a link menu for choosing the language of the page.
A comma-separated list of languages (as 2-digit ISO codes like "en") that should be available. If not specified, all enabled languages are rendered (this can be configured in the [fleXive] backend).
The separator to be rendered between tags. If you need to include HTML markup, please use the cms:tagOpen and cms:tagClose to avoid problems with invalid XHTML templates.
Template parameters are specified in the tag body with
<ui:define>.
The template for a language item. The
language
variable contains the language to be rendered
(of type
FxLanguage).
By default, this renders plain text links for toggling the language.
You can use the
fx:urlWithLocale
JSF-EL function, for example (taken from the default template):
<cms:languageSelect languages="en,de"> <ui:define name="item"> <c:if test="#{language.iso2digit eq fxPageBean.languageCode}"> <!-- Current language --> <strong>#{language.label}</strong> </c:if> <c:if test="#{language.iso2digit ne fxPageBean.languageCode}"> <!-- Render link to the current page in the given language --> <a href="#{fx:urlWithLocale(language.iso2digit, fxPageBean.treePath)}">#{language.label}</a> </c:if> </ui:define> </cms:languageSelect>
These components can be added to own templates to offer popup menus when the CMS frontend editor is active.
Renders a menu with options for a child rendered by cms:renderChildren when the edit mode is active.
Renders a login button for guest users or a logout button if the user is already logged in.
The edit mode menu for a navigation item rendered by cms:navigation.
[fleXive] CMS offers static helper functions that can be used in page templates, e.g. for converting strings to uppercase or for creating absolute page URLs.
Submit a FxSQL query and return the result set. For complex queries is is usually easier to construct them in a separate expression or provide them from a managed bean.
Example 3.1. Submitting a FxSQL query in a template
<c:set var="queryString" value=" SELECT @pk, modified_at, caption FILTER version=live WHERE typedef = 'CMS_BASIC_PAGE' ORDER BY modified_at DESC "/> <c:set var="result" value="#{cms:query(queryString)}"/> <ui:repeat var="row" value="#{result.rows}"> <h3>PK: #{row[0]}</h3> <p> Title: #{row[2]}<br/> Last modified: #{row[1]}<br/> </p> </ui:repeat>
Escape the argument for use in a SQL expression. For example, strings get quoted and escaped, dates get properly formatted, and so on.
For example, to escape a parameter passed from a request parameter (e.g.
page.xhtml?queryName=name):
<c:set var="query" value="SELECT @pk FILTER version=live WHERE caption=#{cms:escapeSql(request.parameterMap['queryName'])}" />
Returns the tree nodes for the given navigation level. The CMS root node is at level #{fxPageBean.treeRootLevel}.
Example 3.2. Using the cms:pagesForLevel function
<ui:repeat var="node" value="#{cms:pagesForLevel(fxPageBean.treeRootLevel)}"> <li> <cms:navigationMenu/> Root navigation: <h:outputLink value="#{fx:url(node.name)}">#{node.label}</h:outputLink> </li> </ui:repeat>
Escapes quotes in its String argument with backslashes, e.g. for use in JavaScript expressions.
Converts its argument to lower case.
For example:
#{cms:toLowerCase('Pete')}
=>
pete.
Converts its argument to upper case.
For example:
#{cms:toUpperCase('Pete')}
=>
PETE.
Renders an opening tag. This is useful to avoid issues with escaping control characters in XHTML contexts, e.g. in tag attributes.
For example:
#{cms:tagOpen('li')}
=>
<li>
Renders a closing tag. This is useful to avoid issues with escaping control characters in XHTML contexts, e.g. in tag attributes.
For example:
#{cms:tagClose('li')}
=>
</li>
Replaces a part of an input string and returns the new string.
For example:
#{cms:replace('Hello NAME', 'NAME', 'Pete')}
=>
"Hello Pete"
Objective: Automatically generate a top-level navigation for the pages of the website.
To create a navigation that resembles the pages of your website use the cms:navigation component, for example:
Example 4.1. Using cms:navigation
<cms:navigation depth="3"> <f:facet name="item"> <h:panelGroup> <h:outputLink value="#{fx:url(node.path)}"> #{node.label} </h:outputLink> <cms:navigationMenu/> </h:panelGroup> </f:facet> </cms:navigation>
Objective: Render short preview texts (teasers) of pages attached to the current page.
Use the cms:renderChildren component to render the pages in a specific subfolder with a teaser template.
Example 4.2. Rendering teasers with cms:renderChildren
Page template:
<cms:renderChildren id="teasers" template="CMS_PAGE/TEMPLATES/TEASER" folder=""/>
Teaser template:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:fx="http://www.flexive.com/jsf/core" xmlns:cms="http://www.flexive.com/jsf/cms"> <ui:composition> <!-- Link to the article --> <h3> <a href="#{fx:url(path)}"><cms:value value="#{content.title}"/></a> </h3> <!-- Render teaser text --> <p> <cms:value value="#{content['teaser/text']}"/> </p> </ui:composition> </html>
Objective: Map arbitrary URLs to CMS pages.
[fleXive] CMS does all internal URL rewriting with UrlRewriteFilter. You can define additional rules that are applied before the CMS rules.
Example 4.3. Custom URL rewriting with UrlRewriteFilter
Execute the following Groovy script in the backend script console with a user that has
"Script Execution" privileges, e.g. the supervisor user. This example configuration
redirects requests to
/legacy-url
to
/info.xhtml
and use page URLs ending in
.html
instead of
.xhtml.
import com.flexive.shared.EJBLookup EJBLookup.configurationEngine.put(com.flexive.cms.shared.CMSConst.REWRITE_RULES, ''' <urlrewrite> <!-- Rewrite /legacy-url to /info.xhtml --> <rule> <from>/legacy-url</from> <to type="permanent-redirect" last="true">/info.xhtml</to> </rule> <!-- Support .html URLs --> <rule> <from>(.+)\\.html</from> <to>$1.xhtml</to> </rule> <!-- Rewrite generated URLs to .html suffix --> <outbound-rule> <from>(.*)\\.xhtml</from> <to>$1.html</to> </outbound-rule> </urlrewrite> ''')
Objective: store website resources like images or stylesheets in the CMS.
[fleXive] CMS provides two special folders,
/files
and
/resources,
for dealing with website resources:

/files acts as a simple, path-based store for binary objects like images. Anything that is put there can be reached through the tree path that is visible in the backend.
/resources
is a collection of text-based resources like stylesheets and scripts.
These resources are actually normal CMS pages with custom templates that set
the correct content types, e.g.
text/css
for CSS files.
In the screenshot above, the resources can be reached from the website with the following paths:
/files/flexive.jpg
/resources/default.css
/resources/perfect-3col-liquid.css
/resources/perfect-2col-liquid.css
To create a new content in one of these folders, right-click the folder, select Create content... and then the appropriate content type:
For image formats like PNG or JPG, select "Image".
For other binary formats like PDF files select "Document".
For text resources like CSS or JS files, select "CMS Resource". You then have to set the page template according to the resource type, like "Resource: CSS" or "Resource: Javascript".
These resource can be reached through the URI that is displayed in the backend when node paths are displayed (activate the ":/" icon in the content tree menu). In the image above, this mode is not activated. You are viewing node paths if the page root node has the name "flexiveCMS" instead of the page title ("Welcome to...").
Note that you have to activate the resources for them to be available on the public website. To do this, right-click the resource and choose Activate. You can also activate the whole resource folder by right-clicking the folder and choosing Activate subtree.
Using the [fleXive] content repository enables you to build multilanguage websites very quickly. For an example, check the demo website that the installer creates.
The demo website sets up a URL pattern that matches all URLs starting with
/en
and
/de
to English and German, respectively. This mapping is created with the following
script that can be executed in the backend script console:
EJBLookup.configurationEngine.put(com.flexive.cms.shared.CMSConst.REWRITE_RULES, '''<?xml version="1.0" encoding="utf-8"?> <urlrewrite> <!-- URL-based website locale: map /en to English page, /de to German, everything else uses the browser language (if possible) --> <rule> <from>^/(de|en)/(.*)?</from> <to>/$2</to> <set name="languageCode">$1</set> </rule> <rule> <from>.*</from> <!-- Set CMS language URL format, on this demo website this is the same for all pages --> <set name="cmsEncodeLanguageFormat">/{languageCode}{url}</set> </rule> </urlrewrite> ''')
You can use the <cms:languageSelect> component to render a menu for choosing the locale of the current page.
In the rewrite rules, you have to create a URL mapping for localized URLs that sets the correct language. [fleXive] then uses this language for the rest of the request.
You also have to specify the link format in the request attribute
cmsEncodeLanguageFormat.
Any URL rendered with
#{fx:url(path)}
on the current page
will then use this format and encode the current page locale accordingly
(in this case, the format is set for all URLs to enable cms:languageSelect
on URLs without locale).
Using the installer gets you started with little effort, but it is not advisable to turn this version directly into a production instance.
The installer uses Jetty, OpenEJB, and H2. While all of them are mature technologies, we we recommend using a supported application server and a scalable, standalone database system. JBoss with MySQL or PostgreSQL is usually a fine and free combination. The website itself can be migrated between databases with the import/export tools in the backend .
For detailed installation instructions please refer to the [fleXive] installation guide .
The CMS comes pre-packaged as an EAR application including the [fleXive] backend. You can download the latest stable release from the download page.
While the CMS is a fine out-of-the-box solution for relatively static websites, one can only go so far without writing custom business logic.
Maven WAR overlays
provide a way to override or extend the CMS web application's configuration.
The existing CMS web application,
flexive-cms-war,
is used as an overlay where existing configuration
files can be replaced (e.g. web.xml for adding servlets or filters).
The easiest way to integrate custom logic is by creating a Maven JAR module and implementing one
or more custom JSF managed beans. These can be initialized with an additional
faces-config.xml
that will be discovered by JSF when the JAR file is added to the EAR.
The JAR file with custom business logic can then be added to a stock CMS EAR file.
To achieve fully automatic packaging a new EAR Maven module similar to flexive-cms-ear,
but including the additional dependency, must be created. This is also necessary to include
additional EJB modules, which have to be listed in the EAR's
application.xml.
The CMS artifacts are available in our Maven repository under http://repo.flexive.org/maven2/com/flexive/cms.
As of today, [fleXive] CMS is not yet a complete product. However, it is stable enough that we use it for our own projects, and it should serve well as a base technology for a wider range of websites. Among the things still missing are:
Referencing pages from contents (dynamic link replacement). (CMS-2)
Frontend editing of resources (images, stylesheets, etc.). (CMS-3)
A Maven quickstart archetype for a customized CMS application. (CMS-4)
...and more. Contact us if you have suggestions that are not listed here.