PrimeFaces UIMenuItem对象获取无效ID

时间:2016-12-01 12:56:22

标签: jsf primefaces jsf-2

我目前正在处理一项涉及将项目的PrimeFaces库从PrimeFaces 3.2更新到6.0的任务。

从版本3.5到4.0,有一个API change in PrimeFaces' MenuModel不向后兼容。

我处理的代码使用了扩展org.primefaces.component.menuitem.MenuItem的类javax.faces.component.UICommand

从PrimeFaces 4.0开始,org.primefaces.component.menuitem.MenuItem是一个接口,并且有一个新类org.primefaces.component.menuitem.UIMenuItem实现了该接口,并且还扩展了javax.faces.component.UICommand。新的UIMenuItem类与旧的MenuItem类具有或多或少相同的接口,至少它支持我正在处理的代码中使用的所有方法。

显然,我更改了MenuItem个对象的实例化代码,以便使用新的UIMenuItem类。这样做,代码编译时没有错误,但它在运行时因此异常而失败:

Dec 01, 2016 11:58:02 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet Faces Servlet threw exception
java.lang.IllegalArgumentException: 0
    at javax.faces.component.UIComponentBase.validateId(UIComponentBase.java:542)
    at javax.faces.component.UIComponentBase.setId(UIComponentBase.java:363)

在调试器中,我可以看到实际上有UIMenuItem个ID为0的对象。

UIMenuItem个对象都是由工厂方法创建的,如下所示:

public static MenuItem createNavigationMenuItem() {
    UIMenuItem item = new UIMenuItem();
    item.setStyle("padding: 0;");
    item.setUpdate(":tableForm,:navForm");
    item.addActionListener(actionListener);
    return item;
}

现在就是这样的事情。这些UIMenuItem个对象的ID由org.primefaces.model.menu.BaseMenuModel中的此代码设置:

public void generateUniqueIds() {
    this.generateUniqueIds(getElements(), null);
}

private void generateUniqueIds(List<MenuElement> elements, String seed) {
    if(elements == null || elements.isEmpty()) {
        return;
    }

    int counter = 0;

    for(MenuElement element : elements) {
        String id = (seed == null) ? String.valueOf(counter++) : seed + ID_SEPARATOR + counter++;
        element.setId(id);

        if(element instanceof MenuGroup) {                
            generateUniqueIds(((MenuGroup) element).getElements(), id);
        }
    }
}

我按如下方式阅读此代码:调用generateUniqueIds()时,elements参数引用的MenuElements将不可避免地获得01,{{1}的ID等等。

现在请在2中查看此方法:

javax.faces.component.UIComponentBase

可以清楚地看到,以数字开头的ID总是会导致private static void validateId(String id) { if (id == null) { return; } int n = id.length(); if (n < 1) { throw new IllegalArgumentException("Empty id attribute is not allowed"); } for (int i = 0; i < n; i++) { char c = id.charAt(i); if (i == 0) { if (!Character.isLetter(c) && (c != '_')) { throw new IllegalArgumentException(id); } } else { if (!Character.isLetter(c) && !Character.isDigit(c) && (c != '-') && (c != '_')) { throw new IllegalArgumentException(id); } } } } ,这正是我的代码失败的地方!

现在我想知道:为什么PrimeFaces库中的代码显然无效(根据它正在构建的JSF代码)id IllegalArgumentException对象?

First Rule of Programming之后,我确信PrimeFaces代码很好,而且我的困惑是建立在对我不了解的基础之上。但是,MenuElement中的代码对我来说毫无意义。有没有人可以帮我弄清楚我没有得到什么?

1 个答案:

答案 0 :(得分:3)

你不能将MenuModel与UIMenuItems混合:https://github.com/primefaces/primefaces/issues/199