Question

I am trying to build a menu at runtime depending on the server call in JSP. The model that represents the menu is given below:

import java.util.ArrayList;
import java.util.List;

public class MenuItem {
    public String menuText;
    public List<MenuItem> subMenuItems=new ArrayList<MenuItem>();

    public MenuItem(String menuText) {
        super();
        this.menuText = menuText;
        this.subMenuItems = new ArrayList<MenuItem>();
    }

    public MenuItem(){

    }

    public MenuItem(String menuText, List<MenuItem> subMenuItems) {
        super();
        this.menuText = menuText;
        this.subMenuItems = subMenuItems;
    }

    // @Override
    // public String toString() {
    // // TODO Auto-generated method stub
    // StringBuffer buffer = new StringBuffer();
    // for (MenuItem menuItem : getSubMenuItems()) {
    // buffer.append(menuItem.toString());
    // }
    // return ("  Menu --->" + getMenuText() + buffer.toString());
    //
    // }

    public String getMenuText() {
        return menuText;
    }

    public void setMenuText(String menuText) {
        this.menuText = menuText;
    }

    public List<MenuItem> getSubMenuItems() {
        return subMenuItems;
    }

    public void setSubMenuItems(List<MenuItem> subMenuItems) {
        this.subMenuItems = subMenuItems;
    }

}

For the above model we pass the sample menu from the controller:

   List<MenuItem> menuMainList = new ArrayList<MenuItem>();
            List<MenuItem> submenus = new ArrayList<MenuItem>();
            MenuItem item1= new MenuItem();
            item1.setMenuText("****");
            submenus.add(item1);
            MenuItem item2 = new MenuItem();
            item2.setMenuText("SampleMenu");

            item2.setSubMenuItems(submenus);

            menuMainList.add(item2);
            System.out.println(menuMainList);
            model.addAttribute("menuItem", menuMainList);

On the JSP Page we try to do the following:

<c:forEach items="${menuItem}"  begin="0" var="menuListItem">
            <c:choose>
                <c:when test="${empty menuListItem.subMenuItems}">
                    <div>
                        <c:out value="${menuListItem.menuText}" />
                    </div>
                </c:when>
                <c:otherwise>
                    <div>
                        <span><c:out value="${menuListItem.menuText}" /></span>
                        <div style="width: 150px;">
                            <cobTags:menuDivItem menuList="${menuListItem.subMenuItems}"></cobTags:menuDivItem>
                        </div>
                    </div>
                </c:otherwise>
            </c:choose>
        </c:forEach>

And the custom tag being:

 <%@ tag language="java" pageEncoding="ISO-8859-1"%>
<%@ attribute name="menuList" required="true"%>
<%@ taglib tagdir="/WEB-INF/tags" prefix="cobTags"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<c:forEach items="${menuList}" begin="0" var="menuListItem">
    <div>
        <cobTags:drawMenuItem  menuItem="${menuListItem}"></cobTags:drawMenuItem>
        <c:out value="${menuListItem}" />
    </div>
</c:forEach>

And

    <%@ tag language="java" pageEncoding="ISO-8859-1"%>
<%@ attribute name="menuItem" type="com.sample.bean.MenuItem"
    required="true"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<div style="color: red;">
    <c:out value="${menuItem.menuText}" />
</div>

When I execute the following code, I am getting the error:

Cannot convert [com.sample.bean.MenuItem@547ca73] of type class java.lang.String to class com.sample.bean.MenuItem

I am not getting why the model's toString method is getting called when I pass the object to the custom tag.? Any pointers?

Was it helpful?

Solution

Declaring the type of the argument should fix the problem:

<%@ attribute name="menuList" required="true" type="java.util.Collection" %>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top