Database Driven Menu

This page is designed to show how easy it is create menus from a couple of database tables. I'm using JSTL's SQL Tags because they're easy and you can see all the code that's needed in this one page. This example creates tables, populates them and then extracts the values to build a menu. This logic should probably go into a Servlet, Struts Action or a Servlet Filter to get the logic of who sees what out of the view. But this works, so feel free to copy and/or improve.

DONE: successfully created menu_items table and added the following entries.

If you view the source of the code above - you can see that it just creates a table and inserts some data. This table will be dropped, re-created and populated every time this page is loaded.

Now let's build a Menu definition with this data. Below is the Java scriplet code that is used to build this menu.

In a well-architected application, you might pull the data from the database using Hibernate, iBATIS, or JDBC. You could then use a Business Delegate for your who-sees-what logic and call the Delegate from a ServletFilter, a ServletContextListener or a Login Servlet.

---- begin scriplet code ----

// I had issues using the existing repository - creating a new one
// seems to solve the problem.  If you figure out how to use the default
// Repository and keep your menus from duplicating themselves - please
// let me know!

MenuRepository repository = new MenuRepository();
// Get the repository from the application scope - and copy the
// DisplayerMappings from it.
MenuRepository defaultRepository = (MenuRepository)
        application.getAttribute(MenuRepository.MENU_REPOSITORY_KEY);
repository.setDisplayers(defaultRepository.getDisplayers());

Result result = (ResultpageContext.getAttribute("menus");
Map[] rows = result.getRows();
for (int i=0; i < rows.length; i++) {
    MenuComponent mc = new MenuComponent();
    Map row = rows[i];
    String name = (Stringrow.get("name");
    mc.setName(name);
    String parent = (Stringrow.get("parent_name");
    System.out.println(name + ", parent is: " + parent);
    if (parent != null) {
        MenuComponent parentMenu = repository.getMenu(parent);
        if (parentMenu == null) {
            System.out.println("parentMenu '" + parent + "' doesn't exist!");
            // create a temporary parentMenu
            parentMenu = new MenuComponent();
            parentMenu.setName(parent);
            repository.addMenu(parentMenu);
        }

        mc.setParent(parentMenu);
    }
    String title = (Stringrow.get("title");
    mc.setTitle(title);
    String location = (Stringrow.get("location");
    mc.setLocation(location);
    repository.addMenu(mc);
}
pageContext.setAttribute("repository", repository);

---- end scriplet code ----

Now that we've built our menu repository, we can easily display it with the following code:

<menu:useMenuDisplayer name="ListMenu" repository="repository">
    <menu:displayMenu name="DatabaseMenu"/>
    <menu:displayMenu name="StandaloneMenu"/>
</menu:useMenuDisplayer>

Which results in:

You could also grab the menu names dynamically from the repository and loop through them using JSTL's <c:forEach> tag:

<menu:useMenuDisplayer name="Velocity" config="/templates/xtree.html"
    repository="repository">
    <c:forEach var="menu" items="${repository.topMenus}">
        <menu-el:displayMenu name="${menu.name}"/>
    </c:forEach>
</menu:useMenuDisplayer>

Which results in:

View JSP Source
Back to Index