2016-12-01 61 views
1

我目前正在從事一項任務,涉及從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必然會得到012 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中的代碼對我來說沒有意義。有沒有人能幫我弄清楚我沒有得到什麼?

+0

不知道這是相關的,但我認爲你應該創建「DefaultMenuItem」 – Kukeltje

+0

嗨Kukeltje,感謝您的評論!問題是,我正在處理的代碼調用'MenuItem'上的'getAttributes()','UIMenuItem'通過擴展'UICommand'繼承,但DefaultMenuItem不會...... – anothernode

回答