Magnolia 4.5 reached end of life on June 30, 2016. This branch is no longer supported, see End-of-life policy.

Page tree
Skip to end of metadata
Go to start of metadata

Magnolia Groovy module adds Groovy capabilities to Magnolia. Groovy is a popular dynamic language for the JVM. To know more about it, please visit the Groovy official website which has plenty of tutorials and excellent documentation both for beginners and advanced users of the language. The module provides a web based Unix-like console where you can access contents in Magnolia repositories in a "groovish" way, a scripts repository where you can store your scripts and the ability to plugin Groovy classes into Magnolia at runtime, without the need for deploying them and restarting the servlet container. All these tools will make for a more agile approach to coding Magnolia based websites and to maintain them.

Download

Download the Groovy module from Magnolia Store or Nexus repository.

Installing

Groovy is a community module available in the add-ons folder of both the Enterprise and Community bundles. To install the module, see the general module installation instructions .

Uninstalling

See the general module uninstalling instructions and advice.

Usage

Repository data navigation simplified

Thanks to the .(dot) notation and other handy shortcuts such as .children, .nodeData, .metaData, .parent, you will be able to read any content node and node data, change their values, create content and delete it, all with a clean, concise syntax. Since version 1.1 the module comes with some preinstalled sample scripts which show most of these features. As an example, here is how one could navigate to and print the node data named abstract:

hm = ctx.getHierarchyManager('website')
node = hm.getContent('/demo-project')
println node.about.history.abstract

One noticeable thing about the above snippet is that it is actually all you need to write: no imports, no need to explicitly get a MgnlContext, etc. Compare it with the Java code you need to achieve the same result.

import javax.jcr.RepositoryException;
import info.magnolia.cms.core.Content;
import info.magnolia.cms.core.HierarchyManager;
import info.magnolia.context.MgnlContext;
import info.magnolia.cms.util.NodeDataUtil;

public class Test {
public static void main(String[] args) {
    HierarchyManager hm = MgnlContext.getHierarchyManager("website");
    try {
        Content node = hm.getContent("/demo-project/about/history");
        String value = NodeDataUtil.getString(node, "abstract");
        System.out.println(value);
    } catch (RepositoryException e) {
        e.printStackTrace();
    }
  }
}

And, most importantly, with Groovy you do not need to deploy your class and restart the server. As an additional bonus, when using the Groovy Unix-like shell which comes with the module, when you navigate a repository, every time you press ENTER the node hierarchy is shown in the output, giving you an overview of the data structure. The picture below illustrates this point.

Being able to navigate a repository data like this can come in handy, for instance, when writing and testing your own scripts or trying things out. Or when you need to use the Rescue Servlet (more on that later) which implies the AdminCentral GUI is not available.

Back to the code example shown above. As node is also a Content , you can call any of its methods. 

println node.metaData.template
println node.about.children.title
println node.about.parent (this can return null)

The .children shortcut, unlike Content.getChildren(), always returns both ItemType.CONTENT and ItemType.CONTENTNODE. If you only need one type or the other, then call directly one of the Content.getChildren() methods on the parent node.

If you want to look at the attributes or data for a certain node you can simply call:

println node.about.nodeData

Create and update node data

It is also possible to assign values to node data or create new ones.

node.boo = 3.14d
node.coo = true
node.foo = 'some text'
node.doo = 100

This will assign the values on the right hand side to the node data on left hand side. Should those not exist, they will be automatically created. Moreover, the correct type will be detected based on the value assigned (Boolean, String, Long or Double).

All the above assignments will be in-memory only unless explicitly persisted via a call to save() on a parent node.

Use Groovy classes instead of Java classes

This feature will allow you to virtually replace every Magnolia Java class with a Groovy one. Although not a major issue for most tasks, due to its dynamic nature Groovy is slower than Java. Nevertheless, replacing classes can come in handy in situations where you are not allowed to deploy and restart the server and yet some piece of logic must be added or quickly fixed.

The Magnolia Groovy module comes with a sample class my.commands.GroovyMailCommand which sends an email. Here is how you might use it to create a new scheduled job on the fly using a Groovy command (assuming you have the  Scheduler module installed).

Create a command configuration as shown below.

Specify the Groovy class' fully qualified name (matching the path in the repository where it is saved my.commands) as if it were a plain Java class (which it actually is).

Create a scheduled job configuration, referring to the command. The parameters will be used at runtime by the Groovy script.

You can use this command to replace a similar Java command at runtime. Or you can edit it and have it compiled and replaced on the fly (a kind of class hot deploy). This relies on the Magnolia observation mechanism. Every time the value of the class node data changes the Groovy class will be recompiled.

Rescue servlet

The MgnlGroovyRescueServlet is a special servlet that can be used to bypass the Magnolia filter chain. This is useful when you need to perform rescue operations on a corrupted Magnolia instance or when AdminCentral is not loading. To enable the servlet you must explicitly comment out the Magnolia filter chain in the web.xml file and register the Groovy Rescue Servlet. You also need to add servlet and servlet-mapping configuration for info.magnolia.cms.servlets.ClasspathSpool. This is needed to serve the Javascript and CSS needed by the console.

All operations performed in the Groovy Console are executed in system context, meaning no security restrictions are enforced. This might expose your data to risk of irreversible damages if you are not aware of what you are doing. In other words, use it at your own risk.

Register the Groovy Rescue Servlet

1. Stop Magnolia

2. Open /your-servlet-container/webapps/magnoliaAuthor/WEB-INF/web.xml in a text editor.

3. Comment out the filter and filter-mapping sections:

<!--
<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>
-->

4. Add the following lines to web.xml in order to register the Groovy Rescue Servlet:

<servlet>
   <servlet-name>mgnlGroovyServlet</servlet-name>
   <servlet-class>info.magnolia.module.groovy.servlets.MgnlGroovyRescueServlet</servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>mgnlGroovyServlet</servlet-name>
   <url-pattern>/.magnolia/pages/groovyInteractiveConsole.html</url-pattern>
</servlet-mapping>
<servlet>
   <servlet-name>resourcesServlet</servlet-name>
   <servlet-class>info.magnolia.cms.servlets.ClasspathSpool</servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>resourcesServlet</servlet-name>
   <url-pattern>/.resources/*</url-pattern>
</servlet-mapping>

5. Save web.xml.

6. Start Magnolia

7. Open a Web browser and access the Groovy Rescue Console.

http://host/<contextPath>/.magnolia/pages/groovyInteractiveConsole.html

Make the required changes

Use Groovy commands to navigate to the data you want to change.

In the following example we delete an erroneous configuration node untitled from /config/modules/adminInterface/virtualURIMapping.

1. Assign HierarchyManager of config repository to hm.

hm = ctx.getHierarchyManager('config')

2. Assign the parent node content to root.

root = hm.getContent('/modules/adminInterface/virtualURIMapping')

3. Delete the child node untitled.

root.deleteNodeData('untitled')

4. Save the parent node.

root.save()

Deregister Groovy Rescue Servlet

  1. In web.xml, remove the servlet registration lines you added above.
  2. Remove comments from the filter and filter-mapping sections.
  3. Save web.xml.

Tomcat should notice that web.xml changed and read the changes automatically. If this does not happen, stop Magnolia, edit web.xml, and start Magnolia again. Then try to access AdminCentral.

Access scripts workspace via WebDAV

Since version 1.0.1, the WebDAV module  supports access to the Groovy scripts workspace. This allows you to use your favorite code editor to create and edit scripts.

Remote client connector

Since version 1.2 the Groovy module also allows a remote Java client application to run Groovy scripts against a Magnolia server.
For more information see Groovy Remote Client Connection .

Known issues

The Groovy module 1.2 has a bug that doubles the number of elements returned when you call myNode.children or myNode.each. For example, if you have a node structure like this:

+ myNode (mgnl:contentNode)
  + subNode1 (mgnl:contentNode)
  + subNode2 (mgnl:contentNode)

Using the "syntax sugar" expression myNode.children or myNode.each in a Groovy script would double the number of elements returned.

Further resources

Maven POM dependency sample.

<dependency>
  <groupId>info.magnolia</groupId>
  <artifactId>magnolia-module-groovy</artifactId>
  <version>1.1</version>
</dependency>

Module Maven site

Issue tracker

Download

More scripts