2016-01-07 55 views
0

所以我想在JAX-RS創建自定義ParamConverter<Integer>如何創建一個處理原始int的ParamConverter <Integer>?

public class IntParamConverter implements ParamConverter<Integer>{ 

    @Override 
    public Integer fromString(String value) { 
     try{ 
      return Integer.valueOf(value); 
     }catch (Exception e){ 
      //do some stuff 
      throw new BadRequestEx("Convert Exception"); 
     } 
    } 
    @Override 
    public String toString(Integer value) { 
     return String.valueOf(value); 
    } 
} 

然後,我通過ParamConverterProvider註冊它:

@Provider 
public class CustomParamConverterHandler implements ParamConverterProvider { 

     @Override 
     public <T> ParamConverter<T> getConverter(final Class<T> rawType, Type genericType, Annotation[] annotations) { 
      if (rawType.equals(Integer.class)){ 
       return (ParamConverter<T>) new IntParamConverter(); 
      } 
      return null; 
     } 
    } 

,然後在資源POJO使用它,如下所示:

@GET 
    @Path("/conv") 
    @Produces({MediaType.TEXT_PLAIN}) 
    public String conv(@QueryParam("no") int no) { 
     return ""+no; 
    } 

在運行時(使用system.out測試),我發現Tomee(Apache cfx?)不使用我的IntParamConverter。相反,如果我宣佈@QueryParam("no") Integer no而不是@QueryParam("no") int no然後一切工作正常(tomee使用我的自定義paramConverter

我試着註冊我IntParamConverter與原始INT:

if (rawType.equals(int.class)){ 
    return (ParamConverter<T>) new IntParamConverter(); 
} 

但隨後運行時異常occures:

java.lang.ClassCastException: Cannot cast java.lang.Integer to int 
    at java.lang.Class.cast(Class.java:3369) 
    at org.apache.cxf.jaxrs.utils.InjectionUtils.handleParameter(InjectionUtils.java:388) 
    at org.apache.cxf.jaxrs.utils.InjectionUtils.createParameterObject(InjectionUtils.java:978) 
    at org.apache.cxf.jaxrs.utils.JAXRSUtils.readQueryString(JAXRSUtils.java:1210) 

我該如何創建這樣一個處理原始int的ParamConverter?

回答

2

你不能。

編譯時(通過名爲類型擦除的過程),Java泛型都轉換爲java.lang.Object

原始類型如int沒有java.lang.Object作爲它們的基類,所以在這種情況下這種轉換是不可能的。

+0

我明白了,但Apache CFX或其他實現如何做到這一點?如果我沒有註冊我的自定義IntParamConverter,Tomee完成提供int值的工作。這只是對無效int輸入tomee返回錯誤404,我想避免這一點... – kosta

1

我不會明確表示這是一個錯誤,但他們對InjectionUtils.handleParameter的執行很奇怪。他們有以下幾種:

// [...] 
Object result = null; 
try { 
    result = createFromParameterHandler(value, pClass, genericType, paramAnns, message); 
} catch (IllegalArgumentException nfe) { 
    throw createParamConversionException(pType, nfe); 
} 

從您的ParamConveter獲得值。然後,他們這樣做

if (result != null) { 
    return pClass.cast(result); 
} 
// [...] 

顯然,cast將嘗試和失敗。但是沒有理由對原始類型進行這樣的投射,反射的Method#invoke會照顧到這一點。換句話說,您可以(並且您必須)將Integer的值傳遞給Method#invoke,運行時將負責爲您進行轉換。

如果他們想進行額外的驗證,他們可以首先檢查目標類型是否爲原始類型,並進行適當的驗證(檢查您的值是否爲相應的包裝類型)。對於其他類型,它們可以回退到cast(因爲方法返回類型是綁定到pClass的通用T)或使用類似isInstance之類的東西。

我不會與開發人員打開票證,但具有如此高用量的圖書館應該能夠做到這一點。


如何創建這樣一個處理原始INT一個ParamConverter?

你不行。 ParamConverter是一個泛型類,原語不能與泛型一起使用。但是,圖書館應該支持爲你做最後的Integerint轉換,但它似乎沒有。

+0

有效的點。當我看到他們實施中的「怪異」時,我也會這樣想。事情是我在Glassfish中部署了應用程序,並且我得到了相同的行爲...也許這是設計選擇而不是bug?我真的很想打開一張票,但不知道如何:( – kosta

相關問題