2017-04-05 75 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