struts-menu =========== Introduction ------------ This project contains the source code for a web menuing component intended to work with Jakarta "Struts" subproject. See http://jakarta.apache.org/struts for details on Struts. This project consists of the following major components: - Menus are modeled in an xml resource file and parsed by a repository which is intended to be provided as an application scope attribute. - Implementations of a menu displayer interface that are used to display the menus defined in the xml file. The displayers utilize property files that contain the strings used for dislplaying the menus in html. The property files are utilized as org.apache.struts.util.MessageResources. This allows a page designer to modify the html (usually to change look and feel) in this file and have the menu displayer use their custom file. A designer could potentially have many variations of this file to provide many different look and feels for their menus. - A set of tags used for displaying menus using a menu displayer specified in the xml resource mentioned above. For example: For using a custom property file: ... Installing and Using struts-menu -------------------------------- You can utilize the binary distribution of struts-menu in your own web application by following these steps: - Download and install Struts into your web application. You can refer to the struts documentation on how to do this at . Note: struts-menu has not been tested with Struts 0.5, but with recent nightly builds. It is recommneded that you use one of the more recent nightly builds. - Copy the file "lib/struts-menu.tld" from the struts-menu distribution into the "WEB-INF" directory of your web application. - Copy the file "lib/struts-menu.jar" from the struts-menu distribution into the "WEB-INF/lib" directory of your web application. - Modify the application "WEB-INF/web.xml" file to include a tag library decleration for the struts-menu taglibrary. For example: /WEB-INF/struts-menu.tld /WEB-INF/struts-menu.tld - In each JSP page that will use the Struts custom tags, add the corresponding taglib directive for struts-menu.tld. For example: <%@ taglib uri="/WEB-INF/struts-menu.tld" prefix="menu" %> - Create an XML resource file containing definitions for your menus and place it under the WEB-INF/ directory of your web application. You may use the menu-config.xml file from the struts-menu example application as the basis for this. - Make the menu repository available to your web application as an application (or some other) scope attribute. The defualt key used by the menu displayer tags to find this attribute is "com.fgm.web.menu.MENU_REPOSITORY". You may specify a different key, but you will need to specify the key when using the useMenuDisplayer tag. Just use the default key, it's easier! ;) The following is an example of how you can load the MenuRepository from your action servlet: ---------- begin ---------------- MenuRepository repository = new MenuRepository(); repository.setLoadParam("/WEB-INF/menu-config.xml"); repository.setServlet(this); try { repository.load(); getServletConfig().getServletContext(). setAttribute(MenuRepository.MENU_REPOSITORY_KEY, repository); } catch (Exception e) { //handle this error } ------------ end ---------------- The repository will obtain the menu-config.xml file as an input stream by using the servlet.getServletContext().getResourceAsInputStream() method so that it may pass it to the Struts xml digester. You will probably want to subclass the ActionServlet and place this code into the init() method. This is done in the example application. Note: The load parameter has to do with my implementation of what I call a "loadable resource". I won't go into great detail about why I did this, but the jist of it is that at one time I was developing a web application in which I had various "resources", like the MenuRepository, and there was the possibility of adding more and reusing them in other JSP web applications. The basic idea is that you want to make some kind of "resource" avaialable as an application scope attribute, with as little effort as possible. I made my "loadable resources" implement a simple interface and defined what resources I wanted to load in an XML file. My controller servlet read and loaded all resources that were found. This is sort of akin to the MLET stuff in which services are implemented with a common interface that allows it to managed generically (such as with a stop() method). As an example, the MLET stuff is used by JBoss. I may or may not strip out the loadable resource stuff. Installing the Example Application ----------------------------- - Copy webapps/struts-menu.war to your servlet container web applications directory. - Run it! ;) NOTE: At this time, I have placed some of the necessary libraries into the example application. This is done only as a convenience and will be removed later! The only additional thing you will need is a SAX API. If you are using Tomcat 3.2 or >, it should already come with one. Also, see instructions from the Struts binary distribution about installing it with JSP/Servlet containers other than Tomcat (b/c that all I use :p ). Tag and Display Behaviours -------------------------- - useMenuDisplayer tag: The tag is basically used to setup an instance of a MenuDisplayer object for use by the displayMenu tags. The attributes of useMenuDisplayer: --name - Required attribute that specifies which menu displayer to use. The displayer ar defined in the menu-config.xml file. --bundle - Attribute key for a MessageResources object. If the MenuDisplayer is of type MessageResourcesMenuDisplayer, it will obtain a Struts MessageResources object as an attribute by doing a pageContext.findAttribute(bundle). --config - Specify a properties file to use for displaying the menu. The file is utilized as a Struts MessageResources object and, of course, the strings are obtained by the key value. The default file that is used is com.fgm.web.menu.displayer.DisplayerStrings. --locale - Attribute key for a locale object to use. If the displayer is of type MessageResourcesMenuDisplayer, it will obtain the locale object and set it in the displayer. --repository - Attribute key for the MenuRepository. Really, you will probably only need one MenuRepository. - displayMenu tag: Generally only valid within a tag. It will simply retrieve the menu from the MenuRepository and use the MenuDisplayer provided by useMenuDisplayer to display it. The attributes: --name - Required attribute that specifies which menu to get from the repository. --target - Override the menu item target (meant to go into an tag) with this one. - MessageResourcesMenuDisplayer Abstract implementation of a MenuDisplayer interface that provides some common methods for obtaining messages from MessageResources. i.e. it provides the ability to internationalize certain aspects of the menu like title, toolTip, etc. - SimpleMenuDisplayer Subclass of MessageResourcesMenuDisplayer that implements the display(MenuComponent menu) method. Displays a simple table layout of the provided menu. Note: All of the message keys used for this display is prefixed with "smd". An example property: smd.menu.top= - DropDownMenuDisplayer Subclass of MessageResourcesMenuDisplayer that implements the display(MenuComponent menu) method. Displays a collapsable menu based on the provided menu object. Note: The message keys are prefixed with "dd". This display only works 100% with IE >= 5.0 :( It works somewhat with Netscape 6.0 and the latest Mozilla. See notes below in the "To Do" section. To Do (not necessarily in any order) ------------------------------------ - Display dynamic menus (like collapsable, or heirarchical) that are compatible with various browsers. This is really a pain in the ass, especially since I'm not a JavaScript guru. I have found some web menuing libraries that perform this fairly well, but it will take a good amount of time figure out how they work. One that I have found is Joust (http://www.ivanpeters.com/) which seems to work on most common browsers like, IE (bleck!), Mozilla, Opera, and Netscape (4 and 6). If anyone would like to assist in this (please do!), just contact me. - Develop an example menu displayer that will look at user permissions and display or not display the appropriate menu components. - Overall clean up, documentation, enhanced functionallity, etc. since this is only in the early stages. - Provide additional menu display strings property files so that people can choose a look and feel for their menus from a default library. If anyone would like to assist in any of this, please contact me. Contact ------------ If you have any comments, questions, or wish to contribute, please contact me via email at ssayles@fgm.com