我目前正在從事一項任務,涉及從PrimeFaces 3.2到6.0更新項目的PrimeFaces庫。PrimeFaces UIMenuItem對象獲取無效ID
從版本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
是一個接口,並且有一個新類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
對象與0
遊逛的ID。
public static MenuItem createNavigationMenuItem() {
UIMenuItem item = new UIMenuItem();
item.setStyle("padding: 0;");
item.setUpdate(":tableForm,:navForm");
item.addActionListener(actionListener);
return item;
}
下面是現在的事情:
的UIMenuItem
對象都由工廠方法,看起來像這樣創建的。這些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
IDS等
現在,請在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庫中的代碼顯然無效(根據它構建的JSF代碼)id到MenuElement
對象?
繼First Rule of Programming之後,我肯定PrimeFaces的代碼很好,而我的困惑是建立在我身邊缺乏理解的基礎上的。但是,BaseMenuModel
中的代碼對我來說沒有意義。有沒有人能幫我弄清楚我沒有得到什麼?
不知道這是相關的,但我認爲你應該創建「DefaultMenuItem」 – Kukeltje
嗨Kukeltje,感謝您的評論!問題是,我正在處理的代碼調用'MenuItem'上的'getAttributes()','UIMenuItem'通過擴展'UICommand'繼承,但DefaultMenuItem不會...... – anothernode