2015-06-15 5 views
0

Я разрабатываю клиент/серверное приложение, которое в бэкэнд имеет некоторые методы REST, разработанные с помощью RESTeasy.java.lang.AssertionError: Не удается создать экземпляр java.lang.Enum

В частности, существует способ POST, который в качестве ввода принимает строку JSON, а затем возвращает другой JSON вызывающему клиенту.

Преобразование из JSON в класс Java выполняется Джексоном прозрачным способом, но у меня есть эта проблема:

java.lang.AssertionError: Can not construct instance of java.lang.Enum, problem: abstract types can only be instantiated with additional type information

В JUnit Test, который не с этой ошибки:

/** 
* Test for creation of json of {@link FindRequestBody}. 
*/ 
@Test 
public void testJackson2(){ 
    try { 
     FindRequestBody findRequestBody = new FindRequestBody();   

     ObjectMapper jacksonMapper = new ObjectMapper(); 
     ObjectMapper mapper = new ObjectMapper(); 

     File file = new File("c:\\testFindRequestBody.json"); 
     jacksonMapper.writeValue(file, findRequestBody); 

     Path path = Paths.get("c:\\testFindRequestBody.json"); 
     byte[] data = Files.readAllBytes(path); 

     FindRequestBody returned = jacksonMapper.readValue(data, FindRequestBody.class); 

     Assert.assertNotNull(returned); 

    } 
    catch (JsonGenerationException e) { 
     e.printStackTrace(); 
     Assert.fail(e.getMessage()); 
    } 
    catch (JsonMappingException e) { 
     e.printStackTrace(); 
     Assert.fail(e.getMessage()); 
    } 
    catch (IOException e) { 
     e.printStackTrace(); 
     Assert.fail(e.getMessage()); 
    } 

метод REST является:

/** 
* {@inheritDoc} 
*/ 
@POST 
@Path("/filter") 
@Consumes(MediaType.APPLICATION_JSON) 
@Produces(MediaType.APPLICATION_JSON) 
@Override 
public List<Object> find(FindRequestBody findRequestBody){ 
    return service.find(findRequestBody); 
} 

JSON взят в качестве входных данных сюда м этот метод, например:

{  
    "orderReadContext":{ 
     "valid":"VALID_ONLY" 
    }, 
    "queryControl":{ 
     "firstResult":0, 
     "maxResults":-1, 
     "sortOrder":[  
     ] 
    } 
} 

В поле действует это поле, которая отображает Enum. FieldRequestBody класс содержит класс OrderReadContext, который:

public class OrderReadContext implements Serializable 
{ 
    protected ValidOrAll valid = ValidOrAll.VALID_ONLY; 

    public ValidOrAll getValid() 
    { 
     return this.valid; 
    } 

    public void setValid(ValidOrAll arg) 
    { 
     if (arg == null) 
     { 
      this.valid = ValidOrAll.VALID_ONLY; 
     } 
     else 
     { 
      this.valid = arg; 
     } 
    } 
} 

Вероятно, вызван тем, что, в классе Java, соответствующий JSON, есть некоторые поля, которые Enum.

Я не могу использовать аннотации, так что я хочу знать, если это возможно, используйте некоторые поставщик, или перехватчик и т.д.

+2

Не могли бы вы выслать некоторый код? Грубое предположение: вы не используете Java 5 или новее на своем сервере. Чтобы проверить версию Java на вашем сервере: 'java -version' –

+0

Вопрос отредактирован. – user140888

+3

Вот быстрый совет - вместо того, чтобы перехватывать все исключения в вашем тестовом примере, сделайте метод проверки «Исключением» и пусть все ошибки распространяются вверх - вы получите гораздо лучшую диагностику, если тест не завершится. – tddmonkey

ответ

0

Я решил эту проблему, создавая поставщик этого типа:

@Provider 
@Produces(MediaType.APPLICATION_JSON) 
public class JacksonJsonProvider implements ContextResolver<ObjectMapper> { 

    private ObjectMapper objectMapper; 

    public JacksonJsonProvider() throws Exception { 
     this.objectMapper = new ObjectMapper(); 

     System.out.println("JacksonJsonProvider():: Enter Into Constructor");   
     /* 
     * First, you can globally declare that certain types always require additional type information:   
     * objectMapper.enableDefaultTyping(); // default to using DefaultTyping.OBJECT_AND_NON_CONCRETE 
     * what this means is that for all types specified (for no-args, "Object.class" and all non-final classes), certain amount of default type information (Java class name, more specifically), is included, using default inclusion mechanism (additional wrapper array in JSON). This global default can be overridden by per-class annotations (more on this in next section). 
     * 
     * The only thing you can configure, then, is just which types (classes) are affected. Choices are: 
     * JAVA_LANG_OBJECT: only affects properties of type Object.class 
     * OBJECT_AND_NON_CONCRETE: affects Object.class and all non-concrete types (abstract classes, interfaces) 
     * NON_CONCRETE_AND+_ARRAYS: same as above, and all array types of the same (direct elements are non-concrete types or Object.class) 
     * NON_FINAL: affects all types that are not declared 'final', and array types of non-final element types. 
     * This is often simplest initial way to enable enough type information to get things going. 
     */ 
     getObjectMapperForSerialization(); 

     System.out.println("JacksonJsonProvider():: Enabled Default Typing And Exit Constructor"); 
    } 

    protected void getObjectMapperForSerialization() { 
     System.out.println("JacksonJsonProvider():: Enter Into getObjectMapperForSerialization()"); 
     StdTypeResolverBuilder typeResolverBuilder = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE); 
     typeResolverBuilder = typeResolverBuilder.inclusion(JsonTypeInfo.As.PROPERTY); 
     typeResolverBuilder.init(JsonTypeInfo.Id.CLASS, new ClassNameIdResolver(SimpleType.construct(Base.class), TypeFactory.defaultInstance())); 
     this.objectMapper.setDefaultTyping(typeResolverBuilder); 
    } 

    public ObjectMapper getContext(Class<?> objectType) { 
     return objectMapper; 
    } 
} 

И зарегистрируйте его в web.xml, между resteasy-providers.

Смежные вопросы