我目前正在处理一项涉及将项目的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将不可避免地获得0
,1
,{{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
中的代码对我来说毫无意义。有没有人可以帮我弄清楚我没有得到什么?