Basic Grails wrapper for Struts Menu

  • Tags: navigation, menu
  • Latest: 1.2.1
  • Last Updated: 22 December 2011
  • Grails version: 1.3.5 > *
  • Authors: null
0 vote
Dependency:
compile ":struts-menu:1.2.1"

 Documentation

Summary

Installation

grails install-plugin struts-menu

Description

NOTE: Due to http://jira.grails.org/browse/GRAILS-8119 this plug in will not work with Grails 2.0 M2 +. I dont currently have a solution to this but am happy to accept a patch.

Introduction

A Grails wrapper around Struts Menu. Users are expected to implement their own menu impls, some samples included are YUI menu and Dojo menu.

Struts Menu (http://struts-menu.sourceforge.net/) is a well established menu framework allowing simple menu configuration using an XML based configuration file. It is a mature and stable framework, allowing developers easily configure a menu structure and ACL access to menus declaritively in XML, and then plug-in different tag library menu renderers.

Struts Menu was designed to be used as a JSP tag library. This plugin includes a simple Grails taglib wrapper around the Struts Menu framework, with a lot of the original code -borrowed/copied- from the Struts Menu JSP tag libraries - a side effect of this is that is may not be the -best- :) groovy syntax, and some of the code may be redundant - but it works well for my usages - and I think others may find it useful.

Struts Menu is open source and has an Apache license.

Quick Start

  1. Install plugin
  2. Follow section "Loaded via Spring" and instantiate menu in Spring beans e.g resources.groovy
  3. Follow section "Uses Original Struts Menu configuration" - create struts-menu.xml config file for your menu in WEB-INF - see Struts Menu website for details.
  4. Follow seciton "Use in a GSP" and either reuse the Dojo or Yui menu provided by plugin - or preferably create your own.

Extend Plugin with Custom Menus

It is possible to "plug in" your own menu implementation required for your own project by creating a class that inherits grails.plugin.strutsmenu.adapter.AbstractMenuDisplayerAdapter. AbstractMenuDisplayerAdapter provides sub classes with a few methods that allow access to the underlying struts menu API, and also declares some abstract methods that all menu implementations should implement. These abstract methods are called by the Struts Menu grails tag library MenuDisplayTagLib.

A developer is expected to implement methods in each concreate menu renderer implementation:

/**
     * Implementations of this method should render the meat and bones of a menu, I.E recursivly iterate over the menu
     * components until the menu is completely rendered.
     *
     * @param menu the menu component to render
     */
    public abstract void display ( MenuComponent menu );

/** * Implementations should close of the HTML menu, or leave empty if not needed */ protected abstract void end ();

/** * Implementations should start the HTML menu, or leave empty if not needed */ protected abstract void start ();

/** * Return a string buffer of the CSS and Javascript that the menu impl needs. * * @return a string buffer of the CSS and Javascript that the menu impl needs. */ StringBuffer renderCssAndJavascript ( HttpServletRequest request )

There is two example menu impls provided - DojoTitlePaneMenuDisplayer and YuiMenuDisplayer. DojoTitlePaneMenuDisplayer is a simple wrapper around a Dojo TitlePage menu, and YuiMenuDisplayer provides a horizontal dropdown menu displayer using the YUI framework.

Uses Original Struts Menu configuration

There is an example struts menu config file provided in WEB-INF/menu-config.xml. Your menu configuration must comform to the expected Struts Menu syntax as the XML parsing and menu structure is managed by Struts Menu.

<?xml version="1.0" encoding="UTF-8"?>
<MenuConfig>
    <Displayers>
        <Displayer name="YUIDisplayer" type="grails.plugin.strutsmenu.renderer.YUIMenuDisplayer" />
        <Displayer name="DojoDisplayer" type="grails.plugin.strutsmenu.renderer.DojoTitlePaneMenuDisplayer" />
    </Displayers>
    <Menus>
        <Menu name="NavMenu0" title="Menu 0" page="#" roles="ROLE_ADMIN,ROLE_XXX" />
        <Menu name="NavMenu1" title="Menu 1" roles="ROLE_ADMIN">
            <Item name="Menu2" title="Menu 2" page="#" roles="ROLE_ADMIN"/>
            <Item name="Menu3" title="Menu 3" page="#" roles="ROLE_ADMIN"/>
            <Item name="Menu4" title="Menu 4" page="#" roles="ROLE_ADMIN"/>
        </Menu>
        <Menu name="NavMenu5" title="Menu 5" roles="ROLE_ADMIN">
            <Item name="Menu6" title="Menu 6" page="#" roles="ROLE_ADMIN"/>
            <Item name="Menu7" title="Menu 7" page="#" roles="ROLE_ADMIN"/>
        </Menu>
    </Menus>
</MenuConfig>

Menu ACL

The tag library has a permissions parameter available, this can be a fully qulified class name to a permissions adapter that implements the provided plugin hook PluginPermissionsAdapter. E.g. foo.bar.MyPermissionAdapter implements PluginPermissionsAdapter.

Your menu implementation can decide to show or hide menus by using your custom permissions adapter impl. A sample is provided showing how you might use the Spring Security framework to enforce ACL for your menu. To avoid a dependancy on Spring Security plugin, I have commented out some of the code.

Also, as of version 1.2, a SimpleRolePermissionsAdapter has been added to demonstrate how you might use the UserPrincipal object to control ACL. (Please note these are examples and are not recommended for production).

Use in a GSP

The menu shown above could be rendered on a GSP page like below HTML. Note that "DojoDisplayer" name will be used to identify the renderer implementation defined in the <Displayer> element above.

<html>
    <head>
        <title>Dojo Sample</title>
        <link rel="stylesheet" href="${resource(dir:'css',file:'main.css')}" />
        <link rel="shortcut icon" href="${resource(dir:'images',file:'favicon.ico')}" type="image/x-icon" />
        <sm:renderCssAndJavascript  name="DojoDisplayer"/>
    </head>
    <body class="claro">

<div id="menu"> <!-- No permissions adapter - will default to Struts Menu RoleBased Adapter. --> <sm:displayMenu id="navigationDiv" name="DojoDisplayer" menuName="NavMenu"/> <!-- example showing how to plug in a custom ACL adapter --> <!--<sm:displayMenu id="navigationDiv" name="DojoDisplayer" permissions="grails.plugin.strutsmenu.acl.SimpleRolePermissionsAdapter" menuName="NavMenu"/>--> </div>

</body> </html>

Loaded via Spring

Finally, Struts Menu is instantiated in your applicaiton via declaring Struts Menu Loaded in your Spring beans (resources.groovy), it will assume the menu config file is localed inside WEB-INF. If this is in a different place, then you need to set the property "menuConfig" to its correct location.

menu(net.sf.navigator.menu.MenuLoader) {
    }

This plugin is provided as is - it fits my purpose and as such I have not tried to over engineer or over integrate the solution. If you have ideas or improvements I would be happy to include them as patches providing the code remains backward compatible to the original release.

Release Notes

1.2.1 - (22/12/2011) After Grails 2.0 upgrade the Groovy compiler complained about an overloaded method throwing exceptions which the original method did not declare in its signature. Changed the example Menu Renders to not throw exceptions explicitly, suppose a Runetime eXception should be throw by the devloper instead.

1.2 - (10/11/2011) Included compile dependency to Commons BeanUtils as some users required this when exporting their applciaiton to a WAR. Added a new interface "setHttpRequest" to the PluginPermissionsAdapter class so that the request object can be passed to permissions adapters. This means that userPrincipal object can be used during ACL. Implementations that dont need the request can implement an empty method. Also, renamed method "isAllowxed" to "isAllowed" in AbstractMenuDisplayerAdapter. A typo prevented this from been used correctly. Updated the Example GSP to show how to pass in custom security ACL impl.

1.1 - (03/11/2011) Fixed a few issues with initial plugin import.

1.0 - (01/11/2011) Initial import of source code to subversion repository. Contains basic wrapper functionality around Struts Menu.