2012-06-13 7 views
2

У меня был существующий метод веб-сервиса Джерси, который принимает несколько параметров с помощью метода Http POST, который предназначен для обработки стандартных данных формы, контента тип приложения/x-www-form-urlencoded; одним из этих параметров был список строк. Ниже приведен пример подписи метода, который у меня есть.Принятие списка в качестве параметра для веб-службы Джерси, которая потребляет контент типа многочастности

@POST 
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
public Response createItem(
     @FormParam("p1") long p1, 
     @FormParam("p2") String p2, 
     @FormParam("p3") List<String> p3, 
     @FormParam("p4") String p4, 
     @Context UriInfo uriInfo 
) throws SQLException { 

Это работало правильно, и когда несколько параметров p3 переданы в Списке, он правильно генерируется Джерси и передается в метод.

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

@POST 
@Consumes(MediaType.MULTIPART_FORM_DATA) 
public Response createItemWithFile(
     @FormDataParam("p1") long p1, 
     @FormDataParam("p2") String p2, 
     @FormDataParam("p3") List<String> p3, 
     @FormDataParam("p4") String p4, 
     @FormDataParam("file") InputStream inputStream, 
     @Context UriInfo uriInfo 
) throws SQLException { 

Я изменил аннотаций FormParam к FormDataParam, как я считаю, что это необходимо, когда потребление данных из нескольких частей. Я пытаюсь вызвать этот метод из теста JUnit, используя RESTAssured для выполнения вызова (так же, как это было сделано для исходного метода), но я получаю следующую ошибку.

java.lang.IllegalArgumentException: wrong number of arguments 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
at java.lang.reflect.Method.invoke(Method.java:597) 
at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60) 
at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:205) 
at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75) 
at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288) 

Вложив несколько точек останова в код Джерси, в некоторых точках идентифицировали в трассировке стеки, кажется, что он определил правильный метод для вызова, но в списке параметров он пытается перейдите к нему, p3 опущено.

Есть ли что-то другое, что необходимо сделать для поддержки приема списка в качестве входа при работе с многочастными данными? Учитывая, что это необязательный параметр, я ожидал, что его можно будет опустить в любом случае, так обстоит дело с исходным методом.

RESTASSured код в тесте, который используется для вызова метода, выглядит следующим образом.

Response response = given()      
       .header("my_header", "xyz") 
       .param("p1", "8000040") 
       .param("p2", "sample string") 
       .param("p3", "first_value") 
       .param("p4", "abcde") 
       .multiPart("file", myFile1, inputStream) 
       .expect() 

Я также попытался при использовании formParam в тестовом коде RESTAssured вместо пар, но получить тот же результат.

Заранее спасибо, любая помощь будет оценена по достоинству.

+1

waht версия RESTAssured вы используете? Если> 1.5, то добавьте 'log()' сразу после 'given()' и посмотрите ваш запрос. –

+0

Я использую RESTAssured версию 1.6. добавив log(), в запросе передается значение для p3. – Rob

+0

@rob, Вы нашли решение для этого? –

ответ

2

Пройдя еще какой-нибудь код Джерси, я пришел к выводу, что у меня не может быть параметра типа List на моем методе при использовании многочастности. В какой-то момент процесс Джерси проходит через каждый параметр по методу нахождения Инъецируемого, чтобы прочитать значение для каждого параметра (извините, вероятно, не большое объяснение, но я отлаживал столько, сколько мне нужно), в классе com. sun.jersey.multipart.impl.FormDataMultiPartDispatchProvider в методе getInjectables является следующий код:

private List<Injectable> getInjectables(AbstractResourceMethod method) { 
    List<Injectable> list = new ArrayList<Injectable>(method.getParameters().size()); 
    for (int i = 0; i < method.getParameters().size(); i++) { 
     Parameter p = method.getParameters().get(i); 
     if (Parameter.Source.ENTITY == p.getSource()) { 
      if (FormDataMultiPart.class.isAssignableFrom(p.getParameterClass())) { 
       list.add(new FormDataMultiPartInjectable()); 
      } else { 
       list.add(null); 
      } 
     } else if (p.getAnnotation().annotationType() == FormDataParam.class) { 
      if (Collection.class == p.getParameterClass() || List.class == p.getParameterClass()) { 
       Class c = ReflectionHelper.getGenericClass(p.getParameterType()); 
       if (FormDataBodyPart.class == c) { 
        list.add(new ListFormDataBodyPartMultiPartInjectable(p.getSourceName())); 
       } else if (FormDataContentDisposition.class == c) { 
        list.add(new ListFormDataContentDispositionMultiPartInjectable(p.getSourceName())); 
       } 
      } else if (FormDataBodyPart.class == p.getParameterClass()) { 
       list.add(new FormDataBodyPartMultiPartInjectable(p.getSourceName())); 
      } else if (FormDataContentDisposition.class == p.getParameterClass()) { 
       list.add(new FormDataContentDispositionMultiPartInjectable(p.getSourceName())); 
      } else { 
       list.add(new FormDataMultiPartParamInjectable(p)); 
      } 
     } else { 
      Injectable injectable = getInjectableProviderContext().getInjectable(p, ComponentScope.PerRequest); 
      list.add(injectable); 
     } 
    } 
    return list; 
} 

Так где он видит тип параметра является список или коллекция будет игнорировать его, когда общий тип ничего, кроме FormDataBodyPart или FormDataContentDisposition.

Чтобы обойти проблему, я только что изменил свой метод, чтобы принять строку с разделителями-запятыми для p3 вместо списка.