Jan 19 2010

Magnolia and Railo, Together at Last

Published by jfrank at 1:19 pm under coldfusion, magnolia, open source

Railo and Magnolia CMS are finally together. It’s been a bit of a bumpy road, what with issues arising immediately when they first met. A casual observer might think the relationship was doomed. But a funny thing happened over the course of the last year, Railo changed for the better and for that matter so did Magnolia. I’m proud to say they’ve even moved in to the same bulding at JBoss (in a matter of speaking). From what I hear the landlord thinks the world of both of them but they have still led separate lives.

Until now.

This will be the first in a series of magnolia-railo 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 three is about the dark side, potential problems and workarounds.

Before we dive in, I will address the question “why should these two technologies be merged?” It is simple really. Magnolia is a superior CMS to anything offered in the CFML world, and has amazing interoperability with other technologies. Railo on the other hand, blows the pants off any of the native templating options available in Magnolia and its rapid and powerful tag based language easily unlocks the power of Magnolia’s Jackrabbit JCR. In short, they were made for each other.

Lets put these two together:

  1. Download the latest railo custom all os war, extract to /merge-target. I’ll refer to this directory as the location of our new merged app, however you can name it what you wish.
  2. Delete these files from /merge-target/WEB-INF/lib These files overlap with magnolia’s jars.
    1. apache-jakarta-commons-codec.jar
    2. apache-jakarta-commons-collections.jar
    3. apache-jakarta-commons-fileupload.jar
    4. apache-jakarta-commons-httpclient.jar
    5. apache-jakarta-commons-io.jar
    6. apache-jakarta-commons-lang.jar
    7. apache-jakarta-oro.jar
    8. apache-lucene.jar
    9. backport-util-concurrent.jar
    10. concurrent.jar
    11. PDFBox.jar
  3. Download the latest railo patch (currently 3.1.2.006.rc). Put it in /merge-target/WEB-INF/lib/railo-server/patches/
  4. Download Magnolia Community Edition war extract to /magnolia-temp
  5. Copy /magnolia-temp/WEB-INF/lib/* to /merge-target/WEB-INF/lib/* There should be no file name conflicts.
  6. Copy /magnolia-temp/WEB-INF/config to /merge-target/WEB-INF/config
  7. Merge web.xmls. Use Magnolia’s xml header with namespaces! It doesn’t like anything else, because it reads it in at runtime. Here is the one I created:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
      <description>Magnolia</description>
      <display-name>magnolia</display-name>
    
      <distributable/>
      <filter>
        <display-name>Magnolia global filters</display-name>
        <filter-name>magnoliaFilterChain</filter-name>
        <filter-class>info.magnolia.cms.filters.MgnlMainFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>magnoliaFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>ERROR</dispatcher>
      </filter-mapping>
      <listener>
        <listener-class>info.magnolia.cms.servlets.MgnlServletContextListener</listener-class>
      </listener>
    
    	<servlet>
    		<servlet-name>CFMLServlet</servlet-name>
    		<description>CFML runtime Engine</description>
    		<servlet-class>railo.loader.servlet.CFMLServlet</servlet-class>
    		<init-param>
    	      <param-name>configuration</param-name>
    	      <param-value>/WEB-INF/railo/</param-value>
    	      <description>Configuraton directory</description>
    	    </init-param>
    		<!-- init-param>
    	      <param-name>railo-server-root</param-name>
    	      <param-value>.</param-value>
    	      <description>directory where railo root directory is stored</description>
    	    </init-param -->
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	<servlet>
    		<servlet-name>AMFServlet</servlet-name>
    		<description>AMF Servlet for flash remoting</description>
    		<servlet-class>railo.loader.servlet.AMFServlet</servlet-class>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	<servlet>
    		<servlet-name>FileServlet</servlet-name>
    		<description>File Servlet for simple files</description>
    		<servlet-class>railo.loader.servlet.FileServlet</servlet-class>
    		<load-on-startup>2</load-on-startup>
    	</servlet>	 
    
    	<servlet-mapping>
    		<servlet-name>CFMLServlet</servlet-name>
    		<url-pattern>*.cfm</url-pattern>
    	</servlet-mapping>
    	<servlet-mapping>
    		<servlet-name>CFMLServlet</servlet-name>
    		<url-pattern>*.cfml</url-pattern>
    	</servlet-mapping>
    	<servlet-mapping>
    		<servlet-name>CFMLServlet</servlet-name>
    		<url-pattern>*.cfc</url-pattern>
    	</servlet-mapping>
    	<servlet-mapping>
    		<servlet-name>AMFServlet</servlet-name>
    		<url-pattern>/flashservices/gateway/*</url-pattern>
    	</servlet-mapping>
    	<servlet-mapping>
    		<servlet-name>FileServlet</servlet-name>
    		<url-pattern>/</url-pattern>
    	</servlet-mapping> 
    
    <welcome-file-list>
    	  <welcome-file>index.cfm</welcome-file>
    	<welcome-file>index.cfml</welcome-file>
    </welcome-file-list>
    
    </web-app>
  8. Create file /merge-target/WEB-INF/bootstrap/common/config.server.filters.bypasses.railo.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <sv:node sv:name="railo" xmlns:sv="http://www.jcp.org/jcr/sv/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <sv:property sv:name="jcr:primaryType" sv:type="Name">
        <sv:value>mgnl:contentNode</sv:value>
      </sv:property>
      <sv:property sv:name="jcr:uuid" sv:type="String">
        <sv:value>11577b1a-3123-4cae-80a9-96c1cd5c27ad</sv:value>
      </sv:property>
      <sv:property sv:name="class" sv:type="String">
        <sv:value>info.magnolia.voting.voters.URIStartsWithVoter</sv:value>
      </sv:property>
      <sv:property sv:name="pattern" sv:type="String">
        <sv:value>/railo-context</sv:value>
      </sv:property>
      <sv:node sv:name="MetaData">
        <sv:property sv:name="jcr:primaryType" sv:type="Name">
          <sv:value>mgnl:metaData</sv:value>
        </sv:property>
        <sv:property sv:name="mgnl:activated" sv:type="Boolean">
          <sv:value>false</sv:value>
        </sv:property>
        <sv:property sv:name="mgnl:activatorid" sv:type="String">
          <sv:value>superuser</sv:value>
        </sv:property>
        <sv:property sv:name="mgnl:authorid" sv:type="String">
          <sv:value>superuser</sv:value>
        </sv:property>
        <sv:property sv:name="mgnl:creationdate" sv:type="Date">
          <sv:value>2007-04-25T18:23:31.784+02:00</sv:value>
        </sv:property>
        <sv:property sv:name="mgnl:lastaction" sv:type="Date">
          <sv:value>2007-05-02T17:00:15.025+02:00</sv:value>
        </sv:property>
        <sv:property sv:name="mgnl:lastmodified" sv:type="Date">
          <sv:value>2010-01-14T15:46:52.318-08:00</sv:value>
        </sv:property>
      </sv:node>
    </sv:node>
  9. Set magnolia.update.auto=true in /WEB-INF/config/default/magnolia.properties
  10. Start your container such as tomcat.
  11. Go to /.magnolia, login superuser/superuser
  12. Navigate to Configuration. server->filters->bypasses. You will see the railo node appears, in the configuration bypasses. If you inspect it you will see it is a uriStartsWithVoter that is configured with /railo-context. This node gives you bypassing of magnolia filters for any url starting with /railo-context.
  13. Because of this you can hit /railo-context/admin/index.cfm and setup railo.

The bypass rule is required because Magnolia controls the url space with its chain of filters. You can right click on it and copy it to make another arbitrary bypass that is applied immediately. The filters are configurable and this gives you flexibility in fronting CFML apps with arbitrary urls configurable at runtime. At this point you can build anything you want using Magnolia’s built in templating. The bypasses allow you to run standalone CFML apps in the same JVM, under specified url paths (/myapp/*).

That is it for part one. The next article highlights how your templates and paragraphs can be built in standard CFML, and the interaction between Magnolia and Railo.

One response so far

One Response to “Magnolia and Railo, Together at Last”

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

Trackback URI | Comments RSS

Leave a Reply