2017-04-05 77 views
4

我們現在開始在現有的JSF 2.2項目中使用JSF 2.3。在我們定製的轉換,我們得到了警告Converter is a raw type. References to generic type Converter<T> should be parameterized. 問題,我們遇到的,當我們試圖使用泛型來解決這一警告:JSF 2.3使用泛型的自定義轉換器

@FacesConverter(value = "myConverter", managed = true) 
public class MyConverter implements Converter<MyCustomObject>{ 

@Override 
public MyCustomObject getAsObject(FacesContext context, UIComponent component, String submittedValue){} 

@Override 
public String getAsString(FacesContext context, UIComponent component, MyCustomObject modelValue) {} 
} 

,當轉換器用於例如

<!DOCTYPE html> 
<ui:composition xmlns="http://www.w3.org/1999/xhtml" 
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core" 
xmlns:h="http://java.sun.com/jsf/html" 
xmlns:f="http://java.sun.com/jsf/core" 
xmlns:ui="http://java.sun.com/jsf/facelets"> 
<h:selectOneMenu id="#{componentId}" value="#{componentValue}"> 
    <f:converter converterId="myConverter" /> 
    <f:selectItem itemLabel="label" 
     itemValue="" /> 
    <f:selectItems value="listOfValues" 
     var="singleValue" 
     itemValue="singleValue.value" 
     itemLabel="singleValue.label" /> 
</h:selectOneMenu> 

然後ClassCastException用消息java.lang.String cannot be cast to MyCustomObject被拋出。 stacktrace中還有一行可能可以幫助com.sun.faces.cdi.CdiConverter.getAsString(CdiConverter.java:109)

但是,當轉換器仿製藥的定義從MyCustomObject變更爲Object

@FacesConverter(value = "myConverter", managed = true)  
public class MyConverter implements Converter<Object>{ 

@Override 
public Object getAsObject(FacesContext context, UIComponent component, String submittedValue){} 

@Override 
public String getAsString(FacesContext context, UIComponent component, Object modelValue) {} 
} 

然後一切正常,但顯然擊敗Converter<T>接口的目的。

+0

任何想法?也許@ arjan-tijms? –

+0

Btw:''是非常通用的,你可能想在這裏使用你的POJO或POJI而不是'Object'。就像我用'User'(我的POJI)做的那樣。 – Roland

回答

2

我這裏有同樣的問題,並與下面的解決方案,實際上不只是編譯出來了,但也可以工作:

some_page.xhtml(相關節選):

<h:selectOneMenu styleClass="select" id="companyUserOwner" value="#{adminCompanyDataController.companyUserOwner}"> 
    <f:converter converterId="UserConverter" /> 
    <f:selectItem itemValue="#{null}" itemLabel="#{msg.NONE_SELECTED}" /> 
    <f:selectItems value="#{userController.allUsers()}" var="companyUserOwner" itemValue="#{companyUserOwner}" itemLabel="#{companyUserOwner.userContact.contactFirstName} #{companyUserOwner.userContact.contactFamilyName} (#{companyUserOwner.userName})" /> 
</h:selectOneMenu> 

請注意,上面的JSF代碼是全自定義的東西,可能無法在你的最終。而我的轉換器編譯沒有rawtype警告(JSF 2.3 +,不是 2.2!):

SomeUserConverter.java

@FacesConverter (value = "UserConverter") 
public class SomeUserConverter implements Converter<User> { 

    /** 
    * User EJB 
    */ 
    private static UserSessionBeanRemote USER_BEAN; 

    /** 
    * Default constructor 
    */ 
    public SomeUserConverter() { 
    } 

    @Override 
    public User getAsObject (final FacesContext context, final UIComponent component, final String submittedValue) { 
     // Is the value null or empty? 
     if ((null == submittedValue) || (submittedValue.trim().isEmpty())) { 
      // Warning message 
      // @TODO Not working with JNDI (no remote interface) this.loggerBeanLocal.logWarning(MessageFormat.format("{0}.getAsObject(): submittedValue is null or empty - EXIT!", this.getClass().getSimpleName())); //NOI18N 

      // Return null 
      return null; 
     } 

     // Init instance 
     User user = null; 

     try { 
      // Try to parse the value as long 
      Long userId = Long.valueOf(submittedValue); 

      // Try to get user instance from it 
      user = USER_BEAN.findUserById(userId); 
     } catch (final NumberFormatException ex) { 
      // Throw again 
      throw new ConverterException(ex); 
     } catch (final UserNotFoundException ex) { 
      // Debug message 
      // @TODO Not working with JNDI (no remote interface) this.loggerBeanLocal.logDebug(MessageFormat.format("getAsObject: Exception: {0} - Returning null ...", ex)); //NOI18N 
     } 

     // Return it 
     return user; 
    } 

    @Override 
    public String getAsString (final FacesContext context, final UIComponent component, final User value) { 
     // Is the object null? 
     if ((null == value) || (String.valueOf(value).isEmpty())) { 
      // Is null 
      return ""; //NOI18N 
     } 

     // Return id number 
     return String.valueOf(value.getUserId()); 
    } 

} 

轉換器類有JNDI查找刪除(我將改寫這部分後來反正),但它應該表現出正確的零件已經足夠了:

  • Converter<User>User是一個自定義POJI),用於防止原始類型警告
  • value="UserConverter"這是您在JSF頁面中使用的實際名稱
  • 而最重要的,這實際上固定ClassCastException
  • <f:selectItem itemValue="#{null}" itemLabel="#{msg.NONE_SELECTED}" />
  • 通過省略#{null}空字符串代替null被處理到您getAsString方法!

最後一個實際上修復了上述異常,我的應用程序再次運行時警告更少,類型提示也更好。

需要刪除forClassvalue有:FacesConverter is using both value and forClass, only value will be applied.

+0

這個'f:selectItem itemValue =「#{null}」'確實是一個問題。仍然有問題:f:selectItem itemValue =「」'是否與Mojarra 2.2.X版本一起工作? –

+0

此問題也與此主題相關[link](https://stackoverflow.com/questions/17052503/using-a-please-select-fselectitem-with-null-empty-value-inside-a-pselectonem/) 。 –

+0

類似的問題,但與Primefaces和沒有JSF2.3(它允許泛型,但2.2不)。因此,如果這解決了您的問題(使用'#{null}'),您能否將我的答案標記爲解決方案? – Roland

1

我對FacesConverter有兩個問題。

第一個,當我沒有使用forClass = MyCustomObject.class我得到了完全相同的錯誤消息,因爲你有。將forClass屬性放在@FacesConverter註釋中解決了該問題。它應該解決它也爲你...

其次,我想這是發生在getAsString方法?我有另一個字符串鑄造問題,我不得不這樣做:return myCustomObject.getId().toString()其中id是Long類型。之後,我調整了我的getAsObject以基於id獲取MyCustomObject。也許它與你的問題沒有直接關係,但我認爲這很重要,因爲它是我在編寫轉換器時經常碰到的東西。

+0

如果我使用'forClass = MyCustomObject.class'它確實有效,但在我的情況下它不是理想的解決方案。另外,在'getAsString'方法中,字符串是不需要轉換的。因此,在'@ FacesConvertor'上設置'value'時的解決方案仍然不起作用。我認爲這是JSF/Mojarra/CDI集成的問題。 –

+1

某種程度上出現了錯誤,無論是在您的轉換器還是在您的selectOneMenu的定義中。你可以發佈轉換器的代碼,還有什麼在selectonemenu內? –

+0

我投了這個票,因爲它是一個替代方案(註釋中的「forClass」而不是「value」屬性),它在使用POJO(主要)時自動註冊轉換器。但'myPojo.getField()。toString()'看起來有點不對,因爲'getField()'可能返回'null',然後在這裏出現着名的'NullPointerException'。正如我的答案所示,我使用'String.valueOf(value.getField());'(當您查看方法的源代碼時)是無效的。 – Roland