org.primefaces.model.menu.DefaultSubMenu 无法转换为 javax.faces.component.UIComponent

org.primefaces.model.menu.DefaultSubMenu cannot be cast to javax.faces.component.UIComponent

我正在尝试从 PrimeFaces 3.5 升级到 PrimeFaces 4.0,在 3.5 版本上运行良好的代码行是:

private MenuModel modelPrincipal;
private Menubar menuBar;

menuBar.getChildren().addAll(modelPrincipal.getContents());

但是当我升级到4.0版本时,我必须改变它如下:

private org.primefaces.model.menu.DefaultMenuModel modelPrincipal;
private Menubar menuBar;
menuBar.getChildren().addAll((Collection<? extends UIComponent>) modelPrincipal.getElements());

它抛出标题异常,你们知道解决方法吗?我在迁移文档中找不到任何内容 https://github.com/primefaces/primefaces/wiki/Migration-Guide

我也试过:

menuBar.getElements().addAll(modelPrincipal.getElements());

但给了我同样的例外

感谢任何帮助

编辑(最小(这是我可以使代码出现错误的最小值)可重现示例):

这是 PrimeFaces 4.0:

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

import javax.faces.component.UIComponent;

import org.primefaces.component.menubar.Menubar;
import org.primefaces.model.menu.DefaultMenuItem;
import org.primefaces.model.menu.DefaultSubMenu;

public class MenuExampleMB {
    private org.primefaces.model.menu.DefaultMenuModel modelPrincipal;
    private Menubar menuBar;
    private HashMap<String, SubMenuItemObject> menuUrlCodigos;

    public static void main(String[] args) {
        MenuExampleMB menuExampleMB = new MenuExampleMB();
        // MenuList
        List<MenuObject> menuList = new ArrayList<>();
        // SubMenuItemList
        List<SubMenuItemObject> subMenuList = new ArrayList<>();
        // Add 1 item to the SubMenuItemList
        subMenuList.add(new SubMenuItemObject("1", "SubMenu", "an url"));
        // MenuObject
        MenuObject menu1 = new MenuObject("Menu 1");
        // Set the SubMenu list for this MenuObject
        menu1.setlSubmenus(subMenuList);
        menuList.add(menu1);
        // Call method that brings the Exception
        menuExampleMB.loadMenu(menuList);
    }

    public void loadMenu(List<MenuObject> lMenus) {

        menuUrlCodigos = new HashMap<String, SubMenuItemObject>();
        modelPrincipal = new org.primefaces.model.menu.DefaultMenuModel();
        menuBar = new Menubar();
        // Go through the list of MenuObject and create each SubMenu and add them to
        // DefaultMenuModel
        for (MenuObject menu : lMenus) {
            DefaultSubMenu subMenu = new DefaultSubMenu();
            subMenu = agregarSubmenu(menu.getlSubmenus());
            subMenu.setLabel(menu.getTitulo());
            modelPrincipal.addElement(subMenu);
        }
        // This is the one that brings the exception.
        menuBar.getChildren().addAll((Collection<? extends UIComponent>) modelPrincipal.getElements());

    }

    private DefaultSubMenu agregarSubmenu(List<SubMenuItemObject> lSubMenuUsuario) {

        DefaultMenuItem menuItem = null;
        DefaultSubMenu subMenuPadre = new DefaultSubMenu();

        for (SubMenuItemObject subMenuItem : lSubMenuUsuario) {

            // Ask if this submenu has sons
            if (subMenuItem.getlSubmenus().size() > 0) {

                DefaultSubMenu subMenuHijo = new DefaultSubMenu();
                subMenuHijo.setLabel(subMenuItem.getTitulo());

                /*
                 * Invoke this method with recursivity to get all the sons of this menu
                 * 
                 */
                subMenuHijo.getElements().addAll(agregarSubmenu(subMenuItem.getlSubmenus()).getElements());

                // Add sons to the father submenu.
                subMenuPadre.getElements().add(subMenuHijo);

            } else {
                // This submenu doesn't have sons so its created as an unique son of the
                // father submenu.
                menuItem = agregarItem(subMenuItem);
                subMenuPadre.getElements().add(menuItem);
                subMenuPadre.setLabel(subMenuItem.getTitulo());
            }

        }

        return subMenuPadre;
    }

    private DefaultMenuItem agregarItem(SubMenuItemObject pSubMenuItem) {
        DefaultMenuItem menuItem = new DefaultMenuItem();
        menuItem.setValue(pSubMenuItem.getTitulo());
        menuItem.setUrl(pSubMenuItem.getUrl());

        menuUrlCodigos.put(pSubMenuItem.getUrl(), pSubMenuItem);

        return menuItem;
    }

}

class MenuObject {
    private String titulo;
    private List<SubMenuItemObject> lSubmenus = new ArrayList<SubMenuItemObject>();

    public MenuObject(String pTitulo) {
        titulo = pTitulo;
    }

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public List<SubMenuItemObject> getlSubmenus() {
        return lSubmenus;
    }

    public void setlSubmenus(List<SubMenuItemObject> lSubmenus) {
        this.lSubmenus = lSubmenus;
    }
}

class SubMenuItemObject {
    private String codigo;
    private String titulo;
    private String url;
    private List<String[]> lJerarquia;
    private List<String> lTabs;
    private List<SubMenuItemObject> lSubmenus = new ArrayList<SubMenuItemObject>();

    public SubMenuItemObject(String pCodigo, String pTitulo, String pUrl) {
        codigo = pCodigo;
        titulo = pTitulo;
        url = pUrl;
        lJerarquia = new ArrayList<String[]>();
    }

    public SubMenuItemObject() {

    }

    public String getCodigo() {
        return codigo;
    }

    public void setCodigo(String codigo) {
        this.codigo = codigo;
    }

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public List<SubMenuItemObject> getlSubmenus() {
        return lSubmenus;
    }

    public void setlSubmenus(List<SubMenuItemObject> lSubmenus) {
        this.lSubmenus = lSubmenus;
    }

    public List<String[]> getlJerarquia() {
        return lJerarquia;
    }

    public void setlJerarquia(List<String[]> lJerarquia) {
        this.lJerarquia.clear();
        this.lJerarquia.addAll(lJerarquia);
    }

    public List<String> getlTabs() {
        return lTabs;
    }

    public void setlTabs(List<String> lTabs) {
        this.lTabs = lTabs;
    }
}

class演员

 menuBar.getChildren().addAll((Collection<? extends UIComponent>) modelPrincipal.getElements());

是合乎逻辑的,因为模型中的 org.primefaces.model.menu.DefaultMenuItem 元素在任何方面都不是 UIComponent(您可以通过跟踪源代码直到基础 class/interface 来看到这一点)。即使你没有明确地转换它,它也会因同样的错误而失败,但在另一个 class.

的另一行

menuBar.getElements().addAll(modelPrincipal.getElements());

同样的原因失败了。如果您检查了 menuBargetElements() 方法中的代码,您会看到

public List getElements() {
    MenuModel model = getModel();
    if (model != null) {
        return model.getElements();
    }
    else {
        return getChildren();
    }
}

您甚至可以调试它并看到模型为空,然后 getChildren() 将被返回,实际上以与您第一次尝试相同的调用结束。但是...

您还会在其中看到 getModel(),这可能是在何处寻找解决方案的提示。 menuBar 有一个 setModel(...),您可以在其中设置以编程方式创建的模型。所以解决方案是

menuBar.setModel(modelPrincipal);

如果您以编程方式创建菜单栏。

但大多数情况下它是通过

添加到 xhtml 中的
<p:menu model="#{menuBean.model}" />

一些额外的提示:

  • 搜索 "primefaces menu model 4.0 3.5" 得到的结果会给你 help/hints(至少 G00gle 当时向我展示)
  • 在 PrimeFaces 7 文档中键入 'menumodel' 会给通用菜单组件中的动态菜单部分一个完整的完整示例提示。 https://primefaces.github.io/primefaces/7_0/#/components/menu
  • 在 java 代码或 xhtml 中使用代码完成的 IDE 并检查 api 会显示 setModel 方法或 model属性。

但我同意,在迁移文档中多一点解释会有所帮助,但当时(至少我从 3.5 迁移到 4 时)论坛等中提到了这一点......所以它是 'actual' 当时