2012-06-13 2 views
2

표준 POST 데이터, 컨텐트를 처리하도록 설계된 HTTP POST 메서드를 통해 여러 매개 변수를 수락하는 기존 저지 웹 서비스 메서드가있었습니다. application/x-www-form-urlencoded의 유형; 이 매개 변수 중 하나는 문자열 목록이었습니다. 다음은 내가 가지고있는 메소드 서명의 예입니다.멀티 파트의 컨텐트 유형을 사용하는 Jersey 웹 서비스의 매개 변수로 목록 수락

@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 매개 변수가 전달되면 Jersey에서 올바르게 생성되어 메서드에 전달됩니다.

이제는 기존 매개 변수와 함께 파일을 업로드 할 수 있도록 다중 부분 요청을 허용하는이 방법의 대체 버전을 만들어야합니다. 그래서 아래와 같이 다중 파트 요청을 사용하기 위해 매우 유사한 메소드 서명을 만들었습니다. 나는 여러 부분으로 데이터를 소모 할 때이 필요 생각으로

@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 { 

나는 FormDataParam에 FormParam 주석을 변경했습니다. 나는이 메소드를 호출하기 위해 RESTAssured를 사용하는 JUnit 테스트에서 호출하려고 시도했다. (원래 메소드와 동일하다.)하지만 다음과 같은 에러가 난다.

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) 

스택 추적에 indentified 점의 일부에, 저지 코드로 일부 중단 점을 넣어 데, 그것을 호출 할 수있는 올바른 방법을 확인 것 같다,하지만 매개 변수 목록에이에 노력하고있다 그것을 전달하면 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() 

PARAM 대신에 RESTAssured 테스트 코드에 formParam를 사용하지만, 동일한 결과를 얻을 때 나는 또한 노력했다.

미리 감사드립니다. 도움을 주시면 감사하겠습니다.

+1

와태 버전의 RESTAssured를 사용하고 있습니까? > 1.5이면'given()'다음에'log()'를 추가하고 요청을보십시오. –

+0

RESTAssured 버전 1.6을 사용하고 있습니다. log()를 추가하면 요청에서 p3의 값이 전달되는 것으로 나타납니다. – Rob

+0

@rob,이 해결책이 있습니까? –

답변

2

저지 코드를 좀 더 자세히 살펴보면 다중 부분을 사용할 때 내 메서드에 List 형식의 매개 변수를 사용할 수 없다는 결론이났습니다. 프로세스의 한 지점에서 Jersey는 메서드에 대한 각 매개 변수를 반복하여 각 매개 변수의 값을 읽을 수있는 주입 물을 찾습니다 (유감스러운 설명은 아니지만 필요한만큼 디버깅했습니다). getInjectables 방법에 sun.jersey.multipart.impl.FormDataMultiPartDispatchProvider 다음 코드입니다 :

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에 쉼표로 구분 된 문자열을 허용하도록 메서드를 변경했습니다.