Feb 08 2010

Magnolia and Railo Part 2: Templating and Paragraphs

Published by jfrank at 9:50 pm under coldfusion, magnolia, open source

This is part two in a three part series on how to make Magnolia CMS and Railo work together beautifully.

If you missed part one you’ll need to have read it and done all steps to get anything out of this.

Step One: Wipe out your repositories folder

We’re starting over with content, so at this point I am assuming you dont have anything in your website tree that is not replaceable. If you have something you want to keep, export it first. This is /repositories in the webroot by default, and is the location that magnolia has stored its derby database. Delete it.

Step Two: Get the magnolia-railo-sample files

Export some sample files and configuration with subversion.

svn export https://www.joshuafrankamp.com/svn/incubator/magnolia-railo-sample/trunk/ tempWebroot

Step Three: Merge the sample files

Copy the contents of tempWebRoot into your webroot, this will overwrite the two files we wrote last time, and add many more.

Step Four: Start up your container

Bootstrapping of the app will occur. While it does, lets go over some of the files that I have prepared for you in this sample.

  1. Adding a template renderer
    1. config.modules.templating.template-renderers.cfm.xml
    2. This is required to bind the cfm type to a backing class. We will use the JSP renderer, because it is a dispatch model that is native to Railo since it is a web app.
  2. Creating a template definition node, and backing cfm
    1. config.modules.templating.templates.sampleTemplate.xml
    2. template.cfm with some assets/ that it needs to render properly
    3. This is a specific template instance, that in a normal magnolia application would represent one of many template choices. For this example, we will create a simple template.
  3. Creating a cf include paragraph definition, dialog, and backing cfm
    1. config.modules.templating.paragraphs.cf.xml
    2. config.modules.templating.dialogs.cf.xml
    3. cfinclude.cfm
  4. Creating an example content style “Whats New” paragraph, dialog, and backing cfm
    1. config.modules.templating.paragraphs.whatsNew.xml
    2. config.modules.templating.dialogs.whatsNew.xml
    3. whatsnew.cfm
  5. Creating a page dialog, this will be an editor for page level properties
    1. config.modules.templating.dialogs.page-properties.xml
  6. Example Page
    1. website.index.xml
    2. This page uses the sampleTemplate, and pulls in the example paragraph types in paragraph instances that show them off.  It also allows access to the page properties dialog.
  7. Magnolia Tag Libraries
    1. cms-taglib.tld
    2. These are typically in the magnolia jars, but we need them out where CF can get ahold of them.

Step Five: Hit /index

Magnolia will render the node at the path /index. Since this node is configured in the magnolia administrator to use the simpleTemplate template, it will include the definition of that template to render the page. The templatePath for simpleTemplate is /template.cfm which is a traditional CFML file on disk. At this point the standard Railo request lifecycle will start, including Application.cf(c|m). Then the file will execute, with one signifigant difference. The magnolia context has been set up, and some request scope variables have already been set for easy access to magnolia state information about the page.

A few notes about parts of the example template.cfm

  • The tag libraries give simple access to magnolia controls and data structures. These allow you to render magnolia chrome inline in CFML.Example:
    <cfimport taglib="/tags/cms" prefix="cmsmod" />
    <cfimport taglib="/META-INF/cms-taglib.tld" prefix="cms" />
  • There are three ways to read information from the content repository. The tag library, request scope context objects, and instantiation of singleton magnolia api objects. They all get the information from the same underlying jcr, but with varying levels of complexity and power.Example:
    <cms:setNode var="page" />...
    <title>#page['title']#</title>

    This pulls the properties from the current content node into a Java Map (struct) whose keys and values give you access to the properties. You can also get at the same information through request['state'] which the reader could dump out and traverse to find all kinds of wonderful things in the api

  • Paragraphs are at the heart of everything in Magnolia. They are the single reason for having templates, is the content you want to put on them. By default, Magnolia dispatches the requests for paragraphs to paragraph handlers which in turn for Java technologies, dispatch them as includes through the web app container. This is the point of failure for a technology like Railo, because each request in Railo assumes that it is the beginning and end of that request. It tries to read multi part data on the inbound request, it tries to set headers and response sizes on the outbound response. That is problematic for paragraphs and a big sticking point in the integration between Railo and Magnolia, and it is also not a problem anymore!
    Fortunately, Railo includes its own custom tag concept, and it is simple to implement around the problem. Replacing container includes with calls in a reimplementation of (contrary to its name, this is the tag responsible for including paragraphs, not templates). Look for <cmsmod: includeTemplate /> custom tag calls, in a different namespace. That is the custom implementation of the <cms:includeTemplate /> that would have required going outside the current Railo request.Example:

    <div id="center">
    	<cms:contentNodeIterator contentNodeCollectionName="main">
    		<cmsmod:includeTemplate />
    	</cms:contentNodeIterator>
    	<cms:newBar contentNodeCollectionName="main" paragraph="cf,whatsNew" contentnodename="mgnlNew"/>
    	<hr />
    </div>

4 responses so far

4 Responses to “Magnolia and Railo Part 2: Templating and Paragraphs”

  1. [...] merged app tutorials. Part one will walk through the merging of the two web apps into one. Part two shows how to enable Railo templating and explore the interaction between Magnolia and Railo. Part [...]

  2. gjosephon 09 Feb 2010 at 2:12 pm

    Hi Joshua,

    Cool stuff! It’s always great to see people digging into Magnolia and coming up with stuff we didn’t think of !

    Did you consider implementing a custom ParagraphRenderer for this? I don’t know the Railo API, I’m a little surprised it doesn’t have entry points outside the servlet. Well, assuming it does, maybe you’re going to tell me you would lose the JSP taglib support if you went that way ? We’re actually currently working towards extracting (at least some of) the business off of our JSP tags, in order to facilitate integration with other rendering technologies. I might blog about that in the coming weeks, so keep your eyes peeled; I’ll need feedback from people like you, to see if we’re on the right track! ;)

    Cheers,

    -greg

  3. jfrankon 09 Feb 2010 at 10:19 pm

    Greg,

    I’d love to pretend I know the exact answer to your question, but here are a few things I do know.

    1. I have used a modified jsp paragraph renderer and it seems to work, but its really kludgy. It wants to “start the request over” each time a requestDispatcher.include happens. Railo right now also wants to encode the output and put it on the OutputStream instead of using the Writer, which is another big problem because it munges everything.

    2. Railo (and the language CFML) are incredibly powerful rapid application framework and language, and so not primarily for “dumb” templating. As such they do things like process events like onSessionStart and onApplicationStart, and generally have a whole range of enterprise class features (pdf creation, form building, trivially easy querying/grouped output, OO language constructs, mail, image manipulation). Exiting the template, back to the container for an include, context switching like this doesn’t do anything for railo->railo, it only hurts performance. What we really want is to set the paragraph’s context, and then call to the templatePath of the paragraph.

    3. The reimplementation of is pretty clean, although it does rely on some of your underlying API. I would be sad to see some of those objects be hidden behind DI where I couldn’t get a reference to them. Check it out here: https://www.joshuafrankamp.com/svn/incubator/magnolia-railo-sample/trunk/tags/cms/includeTemplate.cfm It uses ParagraphManager’s singleton nature to get a reference and perform the template lookups (although it wouldn’t be that hard to look it up manually). I could always switch on the paragraphs type, and call the real if it were anything else besides cfm.

    Perhaps some of the Railo guys can come along and tell us how to call from an API perspective, because that would take care of our custom paragraph renderer.

    Joshua

  4. Matteoon 11 Feb 2010 at 12:38 am

    Hi Frank,
    really nice approach!
    We are a small company, in the past we spent our knowledge over Coldfusion technology and now we are moving towards Magnolia.
    I know that was possible to implement what you say but reading that you managed to make it work and that you provided a step-by-step tutorial… so nice!
    Thanks a lot!

    Matteo

Trackback URI | Comments RSS

Leave a Reply