The question is, I have a RestDataSource. I have used these before, and it all works well for me. I created my web-services to specifically work with RestDataSources with a SmartGWT web-app.
However, for this RestDataSource, the only thing I changed is that in the init() method, when I set the bindings, for the fetch binding, using the setHttpMethod GET, I want to send back an object with some information in it, so I set the data protocol to POSTMESSAGE.
However, I keep getting the Error 415 UNSUPPORTED_MEDIA_TYPE from my Spring MVC Controller (which is documented below).
The Controller was unit tested, and seems to work just fine, but the call from the datasource seems to be missing something.
I should also explain that the data being passed as JSON looks like:
String jsonData = "{\"userId\":3, \"ddUserId\":301010651, \"customerCode\":\"QA\", \"customerId\":8}";
and using the JacksonMessageConverter in Spring, this json string is correctly translated into the SearchInvoiceDTO, so that should not be an issue.
I have tried to provide as much information as I can. I have provided the RPC Request and DS Request as shown in the SmartGWT Dev Console.
If anymore information is needed, please let me know.
1. SmartGWT 4.0
SmartClient Version: v9.0_2013-07-03/LGPL Development Only (built 2013-07-03)
2. FireFox 23.0.1
3. Log:
4. RPC Request
DS Request
I have a RestDataSource:
Spring MVC Controller:
The Unit Test shows the controller works great:
However, for this RestDataSource, the only thing I changed is that in the init() method, when I set the bindings, for the fetch binding, using the setHttpMethod GET, I want to send back an object with some information in it, so I set the data protocol to POSTMESSAGE.
However, I keep getting the Error 415 UNSUPPORTED_MEDIA_TYPE from my Spring MVC Controller (which is documented below).
The Controller was unit tested, and seems to work just fine, but the call from the datasource seems to be missing something.
I should also explain that the data being passed as JSON looks like:
String jsonData = "{\"userId\":3, \"ddUserId\":301010651, \"customerCode\":\"QA\", \"customerId\":8}";
and using the JacksonMessageConverter in Spring, this json string is correctly translated into the SearchInvoiceDTO, so that should not be an issue.
I have tried to provide as much information as I can. I have provided the RPC Request and DS Request as shown in the SmartGWT Dev Console.
If anymore information is needed, please let me know.
1. SmartGWT 4.0
SmartClient Version: v9.0_2013-07-03/LGPL Development Only (built 2013-07-03)
2. FireFox 23.0.1
3. Log:
Code:
09:55:50.808 [ERROR] [RevenueManager] 09:55:50.808:XRP5:WARN:RPCManager:Server returned TRANSPORT_ERROR with no error message. - response: {status: -90, data: Obj, httpResponseCode: 415, transactionNum: 0, clientContext: Obj, httpHeaders: Obj, context: Obj, queueStatus: -1, startRow: 0, endRow: 0, totalRows: 0} com.smartgwt.client.core.JsObject$SGWT_WARN: 09:55:50.808:XRP5:WARN:RPCManager:Server returned TRANSPORT_ERROR with no error message. - response: {status: -90, data: Obj, httpResponseCode: 415, transactionNum: 0, clientContext: Obj, httpHeaders: Obj, context: Obj, queueStatus: -1, startRow: 0, endRow: 0, totalRows: 0} at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:105) at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71) at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172) at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:293) at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:547) at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364) at java.lang.Thread.run(Thread.java:662)
Code:
{ "actionURL":"rest/invoices/searchAndCount", "showPrompt":true, "prompt":"Finding Records that match your criteria...", "transport":"xmlHttpRequest", "useSimpleHttp":true, "promptStyle":"cursor", "httpMethod":"GET", "contentType":"application/json", "sendNoQueue":true, "bypassCache":true, "data":"{\r \"userId\":3, \r \"ddUserId\":301010651, \r \"customerCode\":\"QA\", \r \"customerId\":8\r}" }
Code:
{ dataSource:"restInvoiceDS", operationType:"fetch", componentId:"isc_ListGrid_0", data:"{\r \"userId\":3, \r \"ddUserId\":301010651, \r \"customerCode\":\"QA\", \r \"customerId\":8\r}", startRow:0, endRow:75, textMatchStyle:"substring", resultSet:[ResultSet ID:isc_ResultSet_0 (created by: isc_ListGrid_0)], callback:{ caller:[ResultSet ID:isc_ResultSet_0 (created by: isc_ListGrid_0)], methodName:"fetchRemoteDataReply" }, willHandleError:true, showPrompt:true, prompt:"Finding Records that match your criteria...", requestId:"restInvoiceDS$6270", clientContext:{ requestIndex:1 }, fallbackToEval:false, lastClientEventThreadCode:"MUP4[E]", httpMethod:"GET", contentType:"application/json", bypassCache:true, actionURL:"rest/invoices/searchAndCount" }
Code:
public class InvoiceDataSource extends RestDataSource { private static InvoiceDataSource instance = null; public static InvoiceDataSource getInstance() { if (instance == null) { instance = new InvoiceDataSource("restInvoiceDS"); } return instance; } 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"); fetchProps.setContentType("application/json"); 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(); } private DataSourceIntegerField invoiceNumberIdField; private DataSourceIntegerField invoiceNumberField; private DataSourceFloatField invoiceAmountField; private DataSourceTextField invoiceCurrencyField; private DataSourceIntegerField invoiceWaitingField; private DataSourceTextField invoiceAccounts; private DataSourceTextField invoicePeriodField; private DataSourceTextField invoiceTimingField; protected void init() { setDataFormat(DSDataFormat.JSON); setJsonRecordXPath("/"); RPCManager.setAllowCrossDomainCalls(true); invoiceNumberIdField = new DataSourceIntegerField(InvoiceConstants.INVOICE_NUMBER_ID, InvoiceConstants.TITLE_INVOICE_NUMBER_ID); invoiceNumberIdField.setPrimaryKey(true); invoiceNumberIdField.setCanEdit(false); invoiceNumberField = new DataSourceIntegerField(InvoiceConstants.INVOICE_NUMBER, InvoiceConstants.TITLE_INVOICE_NUMBER); invoiceNumberField.setCanEdit(false); invoiceAmountField = new DataSourceFloatField(InvoiceConstants.INVOICE_AMOUNT, InvoiceConstants.TITLE_INVOICE_AMOUNT); invoiceCurrencyField = new DataSourceTextField(InvoiceConstants.INVOICE_CURRENCY, InvoiceConstants.TITLE_INVOICE_CURRENCY); invoiceWaitingField = new DataSourceIntegerField(InvoiceConstants.INVOICE_WAITING, InvoiceConstants.TITLE_INVOICE_WAITING); invoiceAccounts = new DataSourceTextField(InvoiceConstants.INVOICE_ACCOUNTS, InvoiceConstants.INVOICE_ACCOUNTS); invoicePeriodField = new DataSourceTextField(InvoiceConstants.INVOICE_PERIOD, InvoiceConstants.TITLE_INVOICE_PERIOD); invoiceTimingField = new DataSourceTextField(InvoiceConstants.INVOICE_TIMING, InvoiceConstants.TITLE_INVOICE_TIMING); // ================================================================================================================ setFields(invoiceNumberIdField, invoiceNumberField, invoiceAmountField, invoiceCurrencyField, invoiceWaitingField, invoiceAccounts, invoicePeriodField, invoiceTimingField); setFetchDataURL(getServiceRoot() + "/searchAndCount"); setAddDataURL(getServiceRoot() + "/create"); setUpdateDataURL(getServiceRoot() + "/update"); setRemoveDataURL(getServiceRoot() + "/remove/{id}"); } protected String getServiceRoot() { return "rest/invoices"; } protected String getPrimaryKeyProperty() { return "invoiceNumberId"; } @Override protected Object transformRequest(DSRequest dsRequest) { System.out.println("InvoiceDataSource: transformRequest: START"); dsRequest.setContentType("application/json"); JavaScriptObject jso = dsRequest.getData(); String s1 = JSON.encode(jso); System.out.println("InvoiceDataSource: transformRequest: FINISH: s1=" + s1); return s1; } protected void transformResponse(DSResponse response, DSRequest request, Object data) { System.out.println("InvoiceDataSource: transformResponse: START"); JavaScriptObject jso = (JavaScriptObject) data; String jsoText1 = JSON.encode(jso); System.out.println("InvoiceDataSource: transformResponse: START: jsoText1=" + jsoText1); String jsoText2 = JSON.encode(jso); System.out.println("InvoiceDataSource: transformResponse: FINISH: jsoText2=" + jsoText2); super.transformResponse(response, request, data); System.out.println("InvoiceDataSource: transformResponse: FINISH"); } }
Code:
@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; }
Code:
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/invoices/searchAndCount").contentType(MediaType.APPLICATION_JSON) .content(test); this.mockMvc.perform(requestBuilder).andDo(print());