restlet / restlet-framework-java

The first REST API framework for Java
https://restlet.talend.com
Other
654 stars 284 forks source link

PUT/POST requests are failing for JSON as request body. #1190

Open vivek-dhayalan opened 8 years ago

vivek-dhayalan commented 8 years ago
ClientResource cr = new ClientResource("127.0.0.1:8080/api/devices");
cr.getConverterService().setEnabled(true);

Engine.getInstance().getRegisteredConverters().add(new JacksonConverter());

try
{
    cr.getRequest().setEntity(cr.toRepresentation(putBody));
    log.info("update Message to core is " + putBody + "attributes is " + cr.getRequest().getEntityAsText());
    Representation response = cr.put(putBody);
    if(cr.getResponse().getStatus().getCode() < 207)
    {
        responseBody = response.getText();
    }           

}
catch(IOException e)
{
    log.error("Error while updating managedDevice " + e.getMessage());
}
catch(Exception e)
{
    log.error("Error while updating managedDevice " + e.getMessage());
}
finally {
    cr.release();
}

The following is the data that I got from the logs:

**update Message to core is {"statusUpdateDate":"2016-02-07T06:31:28Z","deviceName":"BC-CR-MWS5","geoLocationInfoId":6,"virtualLocationInfo":null,"deviceSpecificationId":3,"deviceDesc":"Marrys Park - Club Road - Water Sensor ","deviceExternalId":"74890","managedAssetGroupId":null,"id":64,"calibrationAdj":0,"deviceUUId":"MAD-2dacad9d-0e91-442b-b805-2a6dc773ea99","status":0}attributes is null**

The following is the error message that I have got:

Feb 15, 2016 12:19:20 PM org.restlet.ext.httpclient.internal.HttpMethodCall sendRequest
WARNING: An error occurred during the communication with the remote HTTP server.
com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.json.JSONObject and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:59)
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:26)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:250)
    at com.fasterxml.jackson.databind.ObjectWriter._configAndWriteValue(ObjectWriter.java:802)
    at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:642)
    at org.restlet.ext.jackson.JacksonRepresentation.write(JacksonRepresentation.java:466)
    at org.restlet.ext.httpclient.internal.HttpMethodCall$3.writeTo(HttpMethodCall.java:332)
    at org.apache.http.entity.HttpEntityWrapper.writeTo(HttpEntityWrapper.java:89)
    at org.apache.http.impl.client.EntityEnclosingRequestWrapper$EntityWrapper.writeTo(EntityEnclosingRequestWrapper.java:108)
    at org.apache.http.impl.entity.EntitySerializer.serialize(EntitySerializer.java:117)
    at org.apache.http.impl.AbstractHttpClientConnection.sendRequestEntity(AbstractHttpClientConnection.java:265)
    at org.apache.http.impl.conn.AbstractClientConnAdapter.sendRequestEntity(AbstractClientConnAdapter.java:231)
    at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:236)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:121)
    at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:685)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:487)
    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
    at org.restlet.ext.httpclient.internal.HttpMethodCall.sendRequest(HttpMethodCall.java:339)
    at org.restlet.engine.adapter.ClientAdapter.commit(ClientAdapter.java:105)
    at org.restlet.engine.adapter.HttpClientHelper.handle(HttpClientHelper.java:119)
    at org.restlet.Client.handle(Client.java:153)
    at org.restlet.routing.Filter.doHandle(Filter.java:150)
    at org.restlet.routing.Filter.handle(Filter.java:197)
    at org.restlet.resource.ClientResource.handle(ClientResource.java:1092)
    at org.restlet.resource.ClientResource.retry(ClientResource.java:1650)
    at org.restlet.resource.ClientResource.handle(ClientResource.java:1100)
    at org.restlet.resource.ClientResource.handleOutbound(ClientResource.java:1176)
    at org.restlet.resource.ClientResource.handle(ClientResource.java:1047)
    at org.restlet.resource.ClientResource.handle(ClientResource.java:1023)
    at org.restlet.resource.ClientResource.put(ClientResource.java:1564)
    at org.restlet.resource.ClientResource.put(ClientResource.java:1502)
    at com.waygum.mbaas.helper.MbaasRestClient.updateManagedDevice(MbaasRestClient.java:60)
    at com.waygum.mbaas.helper.SensorAssignPostProcessor.process(SensorAssignPostProcessor.java:35)
    at org.apache.camel.processor.DelegateSyncProcessor.process(DelegateSyncProcessor.java:63)
    at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
    at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:460)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:190)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:121)
    at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
    at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:190)
    at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:109)
    at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:87)
    at org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:112)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:689)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:649)
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:619)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:307)
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:245)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1144)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1136)
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1033)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

I think need to upgrade to jackson-databind as per the following bug: https://github.com/FasterXML/jackson-databind/issues/539

thboileau commented 8 years ago

Hello,

first of all, the main issue is that Jackson can't serialize the JSONObject instance, because JSONObject has no properties.

Actually, if you use JSONObject, you should rely on the org.restlet.ext.json extension only. That is to say, remove the org.restlet.ext.jackson extension from your classpath, and add the org.restlet.ext.json. You can then write this code:

ClientResource cr = new ClientResource("127.0.0.1:8080/api/devices");
Representation response = cr.put(putBody);

Or even simpler:

ClientResource cr = new ClientResource("127.0.0.1:8080/api/devices");
JSONbject response = cr.put(putBody, JSONObject.class);

If you really prefer using Jackson, remove the dependency to org.json and use beans, or Map.

Then, I notice the following points:

Could you tell us why you register the Jackson converter manually? If the org.restlet.ext.jackson extension is in the classpath, the registration is automatic, unless you are in a very specific case (e.g.: android).

You should remove this line, since you set the entity when sending the put request: cr.put(putBody)

You can shorten this to cr.getStatus()