PrimeFaces UIMenuItem 对象获取无效 ID
PrimeFaces UIMenuItem objects get invalid IDs
我目前正在执行一项任务,涉及将项目的 PrimeFaces 库从 PrimeFaces 3.2 更新到 6.0。
从 3.5 版到 4.0 版,API change in PrimeFaces' MenuModel 不向后兼容。
我正在处理的代码使用了扩展 javax.faces.component.UICommand
.
的 class org.primefaces.component.menuitem.MenuItem
从 PrimeFaces 4.0 开始,org.primefaces.component.menuitem.MenuItem
是一个接口,并且有一个新的 class org.primefaces.component.menuitem.UIMenuItem
实现了该接口并扩展了 javax.faces.component.UICommand
。新的 UIMenuItem
class 与旧的 MenuItem
class 具有或多或少相同的接口,至少它支持我正在处理的代码中使用的所有方法.
很明显,我更改了 MenuItem
对象的实例化代码以利用新的 UIMenuItem
class。这样做,代码编译没有错误,但在运行时失败并出现以下异常:
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
、2
,等等
现在请看一下javax.faces.component.UIComponentBase
中的这个方法:
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);
}
}
}
}
可以清楚地看到,以数字开头的 ID 总是会导致 IllegalArgumentException
,而这正是我的代码失败的地方!
现在我想知道:为什么 PrimeFaces 库中的代码会为 MenuElement
对象提供明显无效的(根据它所构建的 JSF 代码)id?
在 First Rule of Programming 之后,我确信 PrimeFaces 代码没有问题,我的困惑是因为我缺乏理解。但是,BaseMenuModel
中的代码对我来说仍然毫无意义。有没有人可以帮我弄清楚我没有得到什么?
不能将 MenuModel 与 UIMenuItems 混合使用:https://github.com/primefaces/primefaces/issues/199
我目前正在执行一项任务,涉及将项目的 PrimeFaces 库从 PrimeFaces 3.2 更新到 6.0。
从 3.5 版到 4.0 版,API change in PrimeFaces' MenuModel 不向后兼容。
我正在处理的代码使用了扩展 javax.faces.component.UICommand
.
org.primefaces.component.menuitem.MenuItem
从 PrimeFaces 4.0 开始,org.primefaces.component.menuitem.MenuItem
是一个接口,并且有一个新的 class org.primefaces.component.menuitem.UIMenuItem
实现了该接口并扩展了 javax.faces.component.UICommand
。新的 UIMenuItem
class 与旧的 MenuItem
class 具有或多或少相同的接口,至少它支持我正在处理的代码中使用的所有方法.
很明显,我更改了 MenuItem
对象的实例化代码以利用新的 UIMenuItem
class。这样做,代码编译没有错误,但在运行时失败并出现以下异常:
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
、2
,等等
现在请看一下javax.faces.component.UIComponentBase
中的这个方法:
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);
}
}
}
}
可以清楚地看到,以数字开头的 ID 总是会导致 IllegalArgumentException
,而这正是我的代码失败的地方!
现在我想知道:为什么 PrimeFaces 库中的代码会为 MenuElement
对象提供明显无效的(根据它所构建的 JSF 代码)id?
在 First Rule of Programming 之后,我确信 PrimeFaces 代码没有问题,我的困惑是因为我缺乏理解。但是,BaseMenuModel
中的代码对我来说仍然毫无意义。有没有人可以帮我弄清楚我没有得到什么?
不能将 MenuModel 与 UIMenuItems 混合使用:https://github.com/primefaces/primefaces/issues/199