2013-08-20 1 views
1

이 문제는 하루 종일 나를 괴롭 히며 저는 여기에 많은 시간을 할애했으며 올바른 답을 찾고 많은 수정을 시도했습니다.SmartGWT RestDataSource를 Spring REST Controller로 가져 오기 GET이 415 오류를 반환합니다.

나는 여기에 정의 된 스프링 MVC 컨트롤러가 있습니다

@RequestMapping(value = "/searchAndCount", method = RequestMethod.GET, produces = "application/json", headers = 
{ "Accept=application/json", "Content-Type=application/json" }, consumes = "application/json") 
public @ResponseBody 
RequestResults<?> searchAndCount(@RequestBody SearchInvoiceDTO searchInvoiceDto) 
{ 
     RequestResults<?> requestResults = invoiceApprovalService.searchAndCount(searchInvoiceDto); 
    return requestResults; 
} 

나는 대부분의 도착과 함께 간단한 매개 변수를 다시 전송받을 수 있다는 것을 알고 있지만,이 경우에는, 내가 더 잘 내 모든 검색을 넣어 발견 기준을 하나의 물건에 담아서 보내십시오. 그래서 내가 @RequestBody를하고있다.

이전 수정 사항마다 JSON 출력을 받아들이는 데 필요한 두 헤더가 모두 있는지 확인했습니다.

JSON 문자열은 다음과 같습니다.문자열 s1 = "{\"userId \ ": 3, \"ddUserId \ ": 301010651, \"customerCode \ ": \"QA \ ", \"customerId \ ": 8} "; 그리고 잭슨 ObjectMapper 도구를 사용하여이 코드가이 String에서 Object로 올바르게 매핑되는지 확인하고 그 반대의 경우도 마찬가지입니다. POJO를 볼 때 Serializable을 구현하고 기본 생성자를가집니다.

JUnit 테스트 끝내 작동하고 데이터를 반환하지 :

MockHttpServletRequestBuilder requestBuilder = 
     MockMvcRequestBuilders.get("/invoices/searchAndCount").contentType(MediaType.APPLICATION_JSON) 
     .content(test); 

    this.mockMvc.perform(requestBuilder).andDo(print()); 

이 컨트롤러에 전화를하지, 내가 헤더가 무엇인지 출력에서 ​​볼 수있는, 그리고 내가 실제로 돌아가는 것을 볼 수있다 실제 데이터는 훌륭합니다. 그래서 저는 컨트롤러 측면에서 할 수있는 일이 훨씬 더 많지 않다고 생각합니다.

컨트롤러에 대한 실제 호출은 SmartGWT RestDataSource에서 제공됩니다.

private InvoiceDataSource(String id) 
{ 
    setID(id); 
    setClientOnly(false); 

    // set up FETCH to use GET requests 
    OperationBinding fetch = new OperationBinding(); 
    fetch.setOperationType(DSOperationType.FETCH); 
    fetch.setDataProtocol(DSProtocol.POSTMESSAGE); 
    fetch.setDataFormat(DSDataFormat.JSON); 
    DSRequest fetchProps = new DSRequest(); 
    fetchProps.setHttpMethod("GET"); 
    fetch.setRequestProperties(fetchProps); 

    // set up ADD to use POST requests 
    OperationBinding add = new OperationBinding(); 
    add.setOperationType(DSOperationType.ADD); 
    add.setDataProtocol(DSProtocol.POSTMESSAGE); 
    // =========================================== 
    DSRequest addProps = new DSRequest(); 
    addProps.setHttpMethod("POST"); 
    add.setRequestProperties(addProps); 

    // set up UPDATE to use PUT 
    OperationBinding update = new OperationBinding(); 
    update.setOperationType(DSOperationType.UPDATE); 
    update.setDataProtocol(DSProtocol.POSTMESSAGE); 
    // =========================================== 
    DSRequest updateProps = new DSRequest(); 
    updateProps.setHttpMethod("PUT"); 
    // updateProps.setContentType("application/json"); 
    update.setRequestProperties(updateProps); 

    // set up REMOVE to use DELETE 
    OperationBinding remove = new OperationBinding(); 
    remove.setOperationType(DSOperationType.REMOVE); 
    DSRequest removeProps = new DSRequest(); 
    removeProps.setHttpMethod("DELETE"); 
    remove.setRequestProperties(removeProps); 

    // apply all the operational bindings 
    setOperationBindings(fetch, add, update, remove); 

    init(); 
} 

가이 PostMessage를 설정 transformReponse 페치를 사용하여 데이터를 전달하는 가장 좋은 방법이 될 것 같다 :

RequestMethod가 데이터 소스에 정의 여기 init 메소드이다. 나는 그가 올바른 URL을 알고 있기 때문에

@Override 
protected Object transformRequest(DSRequest dsRequest) 
{ 
    // gets the correct URL - (web-app-root)/rest/invoices/searchAndCount 
    postProcessTransform(dsRequest); 

    System.out.println("InvoiceDataSource: transformRequest: START"); 
    dsRequest.setContentType("application/json"); 
    JavaScriptObject jso = dsRequest.getData(); 

    // setting more headers, but this doesn't seem to change anything 
    dsRequest.setAttribute("Access-Control-Allow-Origin", "*"); 
    dsRequest.setAttribute("Content-Type", "application/json"); 
    dsRequest.setAttribute("Accept", "application/json"); 

    String s1 = JSON.encode(jso); 
    System.out.println("InvoiceDataSource: transformRequest: FINISH: s1=" + s1); 
    return s1; 
} 

, 나는 또한 내가 변수 "S1은"또한 올바른 JSON 데이터를 가지고 밖으로 뱉어하고 알고, 내가 다시는 JSON 그것이 충돌 것이 확인 테스트를 할 않았다 컨트롤러를 올바르게 연결하십시오.

또한 pom.xml 파일에 정의 된대로 Jackson에 대한 종속성이 있습니다. 또한 springmvc-servlet.xml 파일에 메시지 변환기가 설정되어 있습니다. 이것이 정확하지 않으면 단위 테스트가 작동하지 않습니다. 그러나, pom.xml 파일이나 springmvc-servlet.xml 파일을 볼 필요가 있다면 알려주십시오.

저는 하루 종일 많은 것을 연구하고 시도해 왔으며, 지금까지는 ... 행운이 없습니다. 충분한 정보를 제공해주기를 바랍니다. 그러나 더 필요한 정보가 있으면 알려 주시기 바랍니다. 궁극적으로 SmartGWT RestDataSource를 조정하여 올바른 데이터를이 컨트롤러에 전달하여 실제로 데이터를 가져올 수 있기를 바랍니다.

업데이트 : Eclipse에서 Jetty를 실행할 때 Firefox 23.0.1을 사용하여 웹 응용 프로그램을 엽니 다.Eclipse에서 콘솔 내에서 , 여기에 내가 무엇을 볼 수 있습니다 :

[WARN] 415 - GET /rest/invoices/searchAndCount (127.0.0.1) 1440 bytes 
Request headers 
    Host: 127.0.0.1:8888 
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0 
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
    Accept-Language: en-US,en;q=0.5 
    Accept-Encoding: gzip, deflate 
    Cookie: GLog=%7B%0D%20%20%20%20left%3A22%2C%20%0D%20%20%20%20top%3A11%2C%20%0D%20%20%20%20width%3A705%2C%20%0D%20%20%20%20height%3A855%2C%20%0D%20%20%20%20priorityDefaults%3A%7B%0D%20%20%20%20%20%20%20%20Log%3A4%0D%20%20%20%20%7D%2C%20%0D%20%20%20%20defaultPriority%3A3%2C%20%0D%20%20%20%20trackRPC%3Atrue%0D%7D 
    Connection: keep-alive 
    If-Modified-Since: Thu, 01 Jan 1970 00:00:00 GMT 
Response headers 
    Content-Type: text/html; charset=iso-8859-1 
    Content-Length: 1440 
    Accept: application/json 

주의가 요청 헤더 : 동의 : text/html과, 응용 프로그램/XHTML + XML, 응용 프로그램/XML, Q = 0.9, /, Q = 0.8 응용 프로그램/JSON 또한, 요청 헤더를 표시하지 않습니다 "콘텐츠 유형은"하지

존재 내가 크롬을 사용하는 경우, 그 결과는 다음과 같습니다

[WARN] 415 - GET /rest/invoices/searchAndCount (127.0.0.1) 1440 bytes 
Request headers 
    Host: 127.0.0.1:8888 
    Connection: keep-alive 
    Accept: */* 
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36 
    DNT: 1 
    Accept-Encoding: gzip,deflate,sdch 
    Accept-Language: en-US,en;q=0.8 
    If-Modified-Since: Thu, 01 Jan 1970 00:00:00 GMT 
    Cache-Control: max-age=0 
Response headers 
    Content-Type: text/html; charset=iso-8859-1 
    Content-Length: 1440 
    Accept: application/json 

JUnit 테스트에서 실행하면 항상 "Content-Type : application/json"이 있습니다. 그래서, SmartGWT RestDataSource에게 여러 곳에서 JSON을 사용하고 있다고 말하고 있지만, 웹 서비스 호출이 올바른 헤더를 생성하지 못하는 것 같습니다.

UPDATE

: 은 내가 SmartGWT RestDataSource transformRequest 메서드에 다음 코드를 추가 :

Map<String, String> httpHeaders = new HashMap<String, String>(); 
    httpHeaders.put("Accept", "*/*"); 
    httpHeaders.put("Content-Type", "application/json"); 
    dsRequest.setHttpHeaders(httpHeaders); 

나는 "승인"요청 헤더를 추가하고 난 여전히 415 지원되지 않는 미디어 오류 메시지를 받았습니다. "Content-Type"요청 헤더를 추가하면 400 BAD REQUEST 오류 메시지가 표시됩니다.

지금은 콘솔이 얻을 :

[WARN] 400 - GET /rest/invoices/searchAndCount (127.0.0.1) 1418 bytes 
Request headers 
    Host: 127.0.0.1:8888 
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0 
    Accept: */* 
    Accept-Language: en-US,en;q=0.5 
    Accept-Encoding: gzip, deflate 
    Connection: keep-alive 
    If-Modified-Since: Thu, 01 Jan 1970 00:00:00 GMT 
    Content-Type: application/json 
Response headers 
    Content-Type: text/html; charset=iso-8859-1 
    Content-Length: 1418 
+0

[첫 번째 질문] (http://stackoverflow.com/questions/18279743/smartgwt-restdatasource-with-springmvc-and-cross-client)에서 답변이 업데이트되었습니다. 무엇보다도 415는 실패한 비행 전 OPTIONS 요청의 상태 코드입니다. – Sithsu

답변

2

이 많은 일을했다, 그러나 나는 마침내 그것을 알아 냈어.

동사 GET은 내 필요에 맞지 않습니다 ... 나는 바보입니다. 어떤 양의 작업도 요청 데이터의 객체로 매개 변수를 전송하여 GET 작업을 수행하지 않습니다. 따라서이 작업을 수행하기 위해 변경해야하는 코드를 보여 드리겠습니다.

SmartGWT RestDataSource를 변경했습니다. fetchProps.setHttpMethod ("GET"); fetchProps.setHttpMethod ("POST"); 나는 여전히 보관했다 : fetch.setDataProtocol (DSProtocol.POSTMESSAGE);

// set up FETCH to use GET requests 
    OperationBinding fetch = new OperationBinding(); 
    fetch.setOperationType(DSOperationType.FETCH); 
    fetch.setDataProtocol(DSProtocol.POSTMESSAGE); 
    fetch.setDataFormat(DSDataFormat.JSON); 
    // =========================================== 
    DSRequest fetchProps = new DSRequest(); 
    fetchProps.setHttpMethod("POST"); 
    fetchProps.setContentType("application/json"); 
    fetch.setRequestProperties(fetchProps); 

또한 같은 RestDataSource에서 "transformRequest"방법에, 나는 추가 :
Map<String, String> httpHeaders = new HashMap<String, String>(); 
    httpHeaders.put("Content-Type", "application/json"); 
    httpHeaders.put("Accept", "application/json"); 
    dsRequest.setHttpHeaders(httpHeaders); 

내가 사용하던 어떤 브라우저,이 두 헤더를 수동으로 설정되고 있는지 확인했다.

스프링 MVC 컨트롤러는 동일한 웹 애플리케이션에 상주하므로 현재까지이를 테스트 할 수있을 때까지 모든 SOP 사이트 간 도메인 문제가 발생하지 않습니다. 그 동안 내 컨트롤의 헤더는 다음과 같습니다.

@RequestMapping(value = "/searchAndCount", method = RequestMethod.POST, headers = 
{ "Accept=application/json", "Content-Type=application/json" }) 
public @ResponseBody 
ArrayList<?> searchAndCountPOST(@RequestBody SearchInvoiceDTO searchInvoiceDto) 

이 작업은 좋은 결과를 얻었으며 내 데이터를 반환했습니다. 원래 가지고있는 단위 테스트는 MockMVc.get을 수행하여 작동하고 저를 통해 수행했습니다. 그것은 데이터를 통해 인식하고 있어야하고 POST가 작동하도록 GET을 변경해야합니다. 이제 유닛 테스트가 POST로 바뀌었고 잘 작동합니다.

나는이 모든 작업이 다른 사람에게 돈을 지불하기를 바랍니다.

관련 문제