If you're thinking about building a new Web site or re-launching an old one, it usually makes sense to consider a Content Management System (CMS). Using a CMS offers a number of advantages over hand-crafting individual pages. However, if you're building a complex Web site, an off-the-shelf CMS often won't satisfy all your requirements out of the box. You'll likely need to customize it and because each CMS its own API and architecture, you'll usually need to invest a fair amount of time learning its innards before you can start adding custom features.

From a development perspective, the ideal solution would be a CMS that can be customized without needing any special training or knowledge. If you're a Spring developer, this ideal CMS is closer than you may think. Magnolia CMS, an open-source, enterprise-grade CMS written entirely in Java, has recently added Spring support, allowing Spring developers to easily extend the base CMS with custom functionality using their existing knowledge of the Spring Framework.

In this article, I'll introduce you to Blossom, the Magnolia CMS module for Spring, and illustrate how you can use it to integrate Spring controllers and views into the Magnolia architecture. Let's get started!

Assumptions and Prerequisites

Before we dive into the code, a few notes and assumptions are worth mentioning. This tutorial assumes that you have a working knowledge of Spring 3.0.x, and that you're comfortable with deploying Web applications using Spring MVC. It also assumes that you're familiar with Java Server Pages (JSP) and the process of creating, building and deploying JAR files to an Apache Tomcat server using Apache Maven.

Introducing Blossom, the Spring and Magnolia CMS Bridge

As you may already know, Magnolia CMS uses a template-based architecture that allows users to define page types and subsections through a graphical, dialog-based interface. It then presents a composite WYSIWYG view with built-in editing controls for each subsection, allowing authors to directly modify different sections of the page and see the changes instantly. Figure 1 shows a screenshot that illustrates this in action.

Magnolia's templating system allows interface designers to easily create new templates to support custom use cases. There are two basic types of templates:

Paragraph templates represent elements within pages.

Page templates represent complete pages.

A single template can be reused multiple times to create different content pages.

To define a new template, a designer or developer must first create a template script using either JSP or FreeMarker. This script file contains the HTML markup for the template, together with placeholder variables that are replaced with actual content at runtime. This template script must then be registered with Magnolia via a template definition, which exposes basic information such as the template name and script path. As shown in this tutorial, these tasks can be easily accomplished through the Magnolia CMS browser-based administration panel.

If you're a Spring developer, though, there's an easier way to define templates: you can simply annotate your Spring controller classes with @Paragraph or @Template, deploy them as a Blossom-compatible module, and Magnolia will automatically detect and make them available as templates in the authoring interface. This can significantly speed up template development, while also offering the opportunity to attach custom workflows or functions to templates.

Magnolia Module Basics

To see how this works, let's create a new Magnolia module that exposes a Spring controller as a paragraph template. In your Spring development workspace, create a new project (I'll call it example-module) and within the project directory, create the directory structure shown in Figure 2.

Figure 2: Initial project directory structure

This is the conventional directory structure followed for all Magnolia modules. Java classes are stored in the src/main/java directory, while additional resources such as JSP scripts or bootstrap files are stored in the src/main/resources directory.

Every Magnolia module must include a module description file, expressed in XML. This file contains information on the module, such as its name, version number and dependencies (if any). This information is displayed in Magnolia CMS during and after the module deployment process.

To create this file, open a text editor and save the following content to src/main/resources/META-INF/magnolia/example.xml:

This specifies the name of the module (Example Module), its version number and the package it belongs to. By convention, Magnolia modules are packaged in the info.magnolia.module.moduleName namespace.

This ExampleModule class is responsible for starting Spring, initializing the application context and setting up the dispatcher servlet. It's generally recommended that this primary class extend the BlossomModuleSupport class; doing this ensures that the module is started and stopped correctly by Magnolia.

Save this file as src/main/java/info/magnolia/module/example/ExampleModule.java.

At this point, all the basic pieces are in place, and we can move on to actually creating templates with Spring.

As previously noted, every Magnolia CMS template has two components: a template script, written in either JSP or FreeMarker, and a template definition. Spring comes in particularly handy when defining the latter.

To illustrate, let's expose a Spring controller for a Web form as a paragraph template. Here's the controller code, which should be saved to src/main/java/info/magnolia/module/PizzaFormParagraph.java.

Notice the @Paragraph and @ParagraphDescription annotations in the controller; these specify the paragraph template label, internal name and description, and they're used by Blossom when auto-detecting and registering templates with Magnolia CMS. The name and description, in particular, are displayed to content authors when creating pages using the template.

The handleRequest() method will be automatically called by Spring's DispatcherServlet, and returns the name of the template script, either pizzaForm.jsp or pizzaFormResult.jsp. These scripts contain the HTML markup for the template.

At this point, your source directory structure should look something like Figure 3.

Figure 3: Project Directory Structure

The basic module is now ready, and all that's left is to build and deploy it. By convention, Magnolia modules are packaged as JAR archives and deployed to the WEB-INF/lib of the Magnolia CMS authoring and public instances. When Magnolia CMS restarts, it will automatically detect and install the new modules.

The easiest way to compile the new module is with Apache Maven. The included source code archive includes a pom.xmlproject build file that you can use for this purpose. Switch to the project directory, and run the following command at your shell prompt:

Copy the module JAR file from the project's example-module/target directory to the WEB-INF/lib directory of the Magnolia authoring instance.

If this is the first time you are deploying a Blossom module to Magnolia CMS, you will also need to update the Magnolia authoring instance's web.xml file with an additional context listener, as shown below. Note that this should be placed before Magnolia's own context listener:

Note: This section assumes that the Magnolia Blossom module and Spring Framework libraries are already present in the WEB-INF/lib directory of the Magnolia authoring instance. If this is not the case, you will have problems deploying and running the module. You can either manually copy these dependencies to the WEB-INF/lib directory of the Magnolia authoring instance, or (recommended) use Maven to manage these dependencies. You can read more about using Maven for dependency management here.

Install the new module, and then log in to the Magnolia CMS AdminCentral. Select the AdminCentral ->Configuration menu and browse through the modules list to the node modules/blossom/paragraphs/autodetected. If all has gone well, Blossom will have auto-detected your new paragraph template and it will appear in the list, as shown in Figure 6.

You can now utilize this paragraph template in any page template. Although the module created in the earlier section doesn't include a page template, it's still possible to manually create a page template in Magnolia CMS and use the new paragraph template inside it. To do this, select the AdminCentral -> Configuration menu and browse through the modules list to the node modules/blossom/templating/templates/. Then, create a new template definition as shown in Figure 7.

Most of this is explained in the templating tutorial, but it's worth pointing out the element, which lists the available paragraphs for this template. Notice that the name specified for the paragraph template matches that specified in the @Paragraph annotation in the controller.

Save this script as $TOMCAT/webapps/magnoliaAuthor/templates/example/example.jsp, and then go back to the Magnolia AdminCentral. You should now be able to use the AdminCentral -> Website -> New Page command to create a new page using this template (see Figure 8).

Once the page is created, you can preview it by selecting it in the AdminCentral -> Website workspace and using the Open Page... command. Click the New button in the resulting preview window, and Magnolia will present you with a list of available paragraph templates, as shown in Figure 9.

Enter some input into the form and submit it. The input will go back to the Spring controller, which will process your input and return the name of the result template. Figure 11 shows what you should see.

Tip: Blossom also supports the use of Spring controllers as page templates. The process is very similar to that for paragraph templates, except that you will annotate the controller with @Template instead of @Paragraph. Look here for an illustrative example.

Conclusion

Of course, this is just the tip of the iceberg. With Spring in play, all manner of interesting things become possible in Magnolia CMS. Still, the examples in this tutorial illustrate how Magnolia's Blossom module makes it easy to integrate advanced features of the Spring Framework with Magnolia's existing templating architecture. This allows developers a great deal of creativity and flexibility when building complex Web sites with custom workflows and non-standard use cases. The use of Spring annotations further simplifies the process, making it possible to reuse existing Spring controllers as Magnolia templates and thereby reduce the overall time, cost and risk of development. Try it out yourself, and see how easy it is!

About the Author

Vikram Vaswani is a consultant specializing in open-source tools and technologies. He has more than 11 years of experience deploying open-source tools in corporate intranets, high-traffic Web sites, and mission-critical applications. He is a frequent contributor of articles and tutorials to the open source community, and the author of six books on PHP, MySQL and XML technologies.